summaryrefslogtreecommitdiff
path: root/src/rtl/modexps6_modinv32.v
blob: dc08b7b91ef827eee323e9d3d03c0853b1d64034 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
`timescale 1ns / 1ps

module modexps6_modinv32
	(
		clk,
		ena, rdy,
		n0, n0_modinv
	);
	
	
		//
		// Ports
		//
	input		wire				clk;
	
	input		wire				ena;
	output	wire				rdy;
	
	input		wire	[31: 0]	n0;
	output	wire	[31: 0]	n0_modinv;	


		//
		// Trigger
		//
	reg ena_dly = 1'b0;
	wire ena_trig = ena && !ena_dly;
	always @(posedge clk) ena_dly <= ena;


		//
		// Ready Register
		//
	reg rdy_reg = 1'b0;
	assign rdy = rdy_reg;
	
	
		//
		// Counter
		//
	reg	[ 7: 0]	cnt		= 8'd0;
	wire	[ 7: 0]	cnt_zero = 8'd0;
	wire	[ 7: 0]	cnt_last	= 8'd132;
	wire	[ 7: 0]	cnt_next	= cnt + 1'b1;
	wire	[ 1: 0]	cnt_phase = cnt[1:0];
	wire	[ 5: 0]	cnt_cycle = cnt[7:2];
	
	always @(posedge clk)
		//
		if (cnt == cnt_zero)	cnt <= (!rdy_reg && ena_trig) ? cnt_next : cnt_zero;
		else cnt <= (cnt == cnt_last) ? cnt_zero : cnt_next;
		
	
		//
		// Enable / Ready Logic
		//
	always @(posedge clk)
		//
		if (cnt == cnt_last) rdy_reg <= 1'b1;
		else if ((cnt == cnt_zero) && (rdy_reg && !ena)) rdy_reg <= 1'b0;
		
		
		//
		// Output Register
		//
	reg	[31: 0]	n0_modinv_reg;
	assign n0_modinv = n0_modinv_reg;
	
	
		//
		// Multiplier
		//
	wire	[63: 0]	multiplier_out;
	wire	[31: 0]	multiplier_out_masked = multiplier_out[31: 0] & {mask_reg, 1'b1};
	
	multiplier_s6 dsp_multiplier
	(
		.clk	(clk),
		.a		(n0),
		.b		(n0_modinv_reg),
		.p		(multiplier_out)
	);
	
	
		//
		// Mask and Power
		//
	reg	[30: 0]	mask_reg;
	reg	[31: 0]	power_reg;
	
	always @(posedge clk)
		//
		if (cnt_phase == 2'd1) begin
			//
			if (cnt_cycle == 6'd0) begin
				//
				mask_reg			<= 31'd0;
				power_reg		<= 32'd1;
				//
				n0_modinv_reg	<= 32'd0;
				//
			end else begin
				//
				mask_reg			<= { mask_reg[29:0], 1'b1};
				power_reg		<= {power_reg[30:0], 1'b0};
				//
				if (multiplier_out_masked != 32'd1)
					//
					n0_modinv_reg <= n0_modinv_reg + power_reg;
				//
			end
			//
		end
			
	
endmodule