-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontroll.v
254 lines (227 loc) · 7.72 KB
/
controll.v
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
`define L 47
`define N 10
`define RAMDELAY 2
module controll(clk, rst, sum);
parameter L = `L; // WANT_TO_CALC_DIGIT(DEC)=100, L -(100/3 +1)+1+1
parameter N = 10;
input clk;
input rst;
output [L*N-1:0] sum;
reg [L*N-1:0] sum;
parameter INIT = 4'h0,
DIV1 = 4'h1,
DIV2 = 4'h2,
DIV3 = 4'h3,
SUB = 4'h4,
DIV4 = 4'h5,
MERGEPLUS = 4'h6,
MERGEMINUS = 4'h7,
END = 4'h8,
PREINIT = 4'h a;
reg [3:0] state;
wire [9:0] initdiv1,initdiv2, constdiv1,constdiv2;
assign initdiv1 = 10'd 80; //16*5
assign initdiv2 = 10'd 956; //4*239
assign constdiv1 = 10'd 25;
assign constdiv2 = 10'd 239;
reg signed [ 31:0 ] count, endct; // count 0 ~~ L //! 2^bit > L + RAMDELAY
parameter NTIMES = 109; // 3*L/1.4+1 ~= 100/1.4 +1 ??? OVERFLOOOOOOOOOOOOOOOOOOOOOO!!!
wire [N-1:0] sum_dsig,sum_q,div1_dsig,div1_q,div2_dsig,div2_q,sub_dsig,sub_q; // CAUTION!
wire [5:0] sum_rdadd,sum_wradd,div1_rdadd,div1_wradd,div2_rdadd,div2_wradd,sub_rdadd,sub_wradd;
wire [N-1:0] div1dsigtmp,div2dsigtmp;
reg sum_wren, div1_wren, div2_wren, sub_wren;
ram2port ram2p_sum (clk,sum_dsig, sum_rdadd, sum_wradd, sum_wren, sum_q); // reg [L*N-1:0] sum;
ram2port ram2p_div1 (clk,div1dsigtmp, div1_rdadd, div1_wradd, div1_wren, div1_q); // reg [L*N-1:0] div1;
ram2port ram2p_div2 (clk,div2dsigtmp, div2_rdadd, div2_wradd, div2_wren, div2_q); // reg [L*N-1:0] div2;
ram2port ram2p_sub (clk,sub_dsig, sub_rdadd, sub_wradd, sub_wren, sub_q); // reg [L*N-1:0] sub;
assign sum_rdadd = count; assign sub_rdadd = count; assign div1_rdadd = count; assign div2_rdadd = count;
assign sum_wradd = count-`RAMDELAY; assign sub_wradd = (state==DIV4)? count+`RAMDELAY : count-`RAMDELAY;
assign div1_wradd = (state==INIT)? (`L-1): (count+`RAMDELAY);
assign div2_wradd = (state==INIT)? (`L-1): (count+`RAMDELAY);
assign div1dsigtmp = div1_dsig;assign div2dsigtmp = div2_dsig;
wire [N-1:0] div1quo; reg [N-1:0] div1quo_mem;//TODO
wire [10+N-1:0] div1rem;
reg [10+N-1:0] div1remm;
assign div1_dsig = (state==PREINIT)? 0 : (state==INIT) ? initdiv1 : div1quo_mem; //TODO
assign div2_dsig = (state==PREINIT)? 0 : (state==INIT) ? initdiv2 : div1quo_mem;
reg [N-1:0] div3valk;
wire [N-1:0] param2k;
assign param2k = div3valk * 2 - 1 ; //OVERFLOW AND DIE
wire [L*N-1:0] divseln;
wire [N-1:0] div1Nbitn,div1Nbitd;
// divider2(unit) is used at DIV1 and DIV3 ,input differs
assign divseln = (state==DIV1)? div1_q : (state==DIV2 || state==DIV3)? div2_q : sub_q;
assign div1Nbitn = divseln;
assign div1Nbitd = (state==DIV1)? constdiv1 : (state==DIV2 || state==DIV3)? constdiv2 : param2k;
divider10a divider1 ( div1remm, div1Nbitn , div1Nbitd, div1quo,div1rem );
reg subcin;
wire subcoutw;
wire [N-1:0] subNbita,subNbitb, subq; reg[N-1:0] subq_mem;
assign subNbita = (state==SUB) ? div1_q : sum_q;
assign subNbitb = (state==SUB) ? div2_q : sub_q;
sub10bitD subsracter( subNbita,subNbitb, subq, subcin,subcoutw );
// only used at MERGE
reg addcin;
wire addcoutw;
wire [N-1:0] addq; reg[N-1:0] addq_mem;
add10bitD adder10D( sum_q,sub_q, addq, addcin,addcoutw );
assign sum_dsig = (state==PREINIT)? 10'd0 : (state==MERGEMINUS)? subq_mem: (state==MERGEPLUS)? addq_mem : 10'bx;
assign sub_dsig = (state==PREINIT)? 10'd0 : (state==SUB)? subq_mem : (state==DIV4) ? div1quo_mem : 10'bx;
always @(negedge clk) begin //remove or megedge rst
if (!rst) begin
// reset
// note: [MSB:LSB], calc MSB->LSB whe div, LSB->MSB when sub/add
// 2.5 -> [<2>,<.5>, ...]
//div1 <= { initdiv1,{(N*L-10){1'b0}} }; div1remm <= 0;
//div2 <= { initdiv2,{(N*L-10){1'b0}} };
count <= L+ `RAMDELAY +1;
sum_wren<=0;div1_wren<=0;div2_wren<=0;sub_wren<=0;
state <= PREINIT;
div3valk<=0;
end else begin // if (!rst)
// every negedge, below is done
div1quo_mem <= div1quo;
addq_mem <= addq;
subq_mem <= subq;
case(state)
PREINIT: begin
// sum <= { (N*L){1'b0} };
count <= count -1;
sum_wren<=1;div1_wren<=1;div2_wren<=1;sub_wren<=1;
if( count == (32'd0 - `RAMDELAY - 1 ) ) begin
sum_wren<=0;div1_wren<=0;div2_wren<=0;sub_wren<=0;
state <= INIT; count <= 0;
end
end
INIT: begin
div3valk <= 10'd 0;
count <= count -1;
div1_wren <=1;div2_wren<=1;
if(count==0-`RAMDELAY) begin
div1remm<=0;
div1_wren <=0;div2_wren<=0;
count <= L-1; state <= DIV1;
end
end
DIV1: begin // div1 /= divider1, div2 /= divider2, ct:L-1->0
// div1[N*count +:N] <= div1quo;
div1remm <= div1rem;
if(count != 0-`RAMDELAY-1) begin
count <= count-1;
if(count == L-1 -`RAMDELAY+1)div1_wren<=1;
end else begin //ct==0-`ramdelay
count <= L-1;div1_wren<=0;
state <= DIV2; div1remm<=0;
end
end
DIV2: begin // div2 /= divider2, ct:L-1->0
// div2[N*count +:N] <= div1quo;
div1remm <= div1rem;
if(count != 0-`RAMDELAY-1) begin
count <= count-1;
if(count == L-1-`RAMDELAY+1)div2_wren<=1;
end else begin
count <= L-1;div2_wren<=0;
state <= DIV3; div1remm <= 0;
end
end
DIV3: begin // div2 /= divider2, ct:L-1->0
//div2[N*count +:N] <= div1quo;
div1remm <= div1rem;
if(count != 0-`RAMDELAY-1) begin
count <= count-1;
if(count == L-1-`RAMDELAY+1)div2_wren<=1;
end else begin
count <= 0;div2_wren<=0;
state <= SUB; subcin <= 0;
end
end
SUB: begin // sub <- div1- div2, ct:0->L-1
//sub[N*count +:N] <= subq;
subcin <= subcoutw;
if(count != L-1 +`RAMDELAY+1) begin
count <= count +1;
if(count == 0+`RAMDELAY-1)sub_wren<=1;
end else begin
count <= L-1;sub_wren<=0;
div3valk <= div3valk +1;
state <= DIV4; div1remm<=0;
end
end
DIV4: begin // sub /= 2*k-1, ct:L-1->0
//! TODO
//sub[N*count +:N] <= div1quo;
div1remm <= div1rem;
if(count != 0-`RAMDELAY-1) begin
count <= count-1;
if(count == L-1-`RAMDELAY+1)sub_wren<=1;
end else begin
if ( (div3valk[0]) == 1'b0) begin
state <= MERGEMINUS; count <=0; subcin<=0;sub_wren<=0;
end else begin
state <= MERGEPLUS; count <=0; addcin<=0;sub_wren<=0;
end
end
end
MERGEPLUS: begin // sum <- sum + sub
//sum[N*count +:N] <= addq;
addcin <= addcoutw;
count <= count +1;
if(count == 0+`RAMDELAY-1)begin
sum_wren<=1;
end else if(count == L-1 +`RAMDELAY+1 ) begin
if(div3valk == NTIMES)begin
div1remm<=0;
sum_wren<=0;
count<=0;
state <= END;
end else begin
div1remm<=0;
sum_wren<=0;
count<=L-1;
state <= DIV1;
end
end
end
MERGEMINUS: begin // sum <- sum - sub
subcin <= subcoutw;
count <= count +1;
if(count == 0+`RAMDELAY-1)begin
sum_wren<=1;
end else if(count == L-1 +`RAMDELAY+1) begin
if(div3valk == NTIMES) begin
div1remm<=0;
sum_wren<=0;
count<=0;
state <= END;
end else begin
div1remm<=0;
sum_wren<=0;
count<=L-1;
state <= DIV1;
end // else: !if(count == L-1 +`RAMDELAY+1)
end
end
END: begin
if(count == L-1 +`RAMDELAY+1 || (endct == N*L) )begin
count <= 0; endct <= 0;
end else begin
count <= count+1;
if(count >= `RAMDELAY-1)begin
//sum[endct +: N] <= sum_q;
sum[endct +: `N] <= sum_q;
endct <= endct + `N;
end
end
end
endcase // case (state)
end
end
endmodule
module seldigit(in, sel, out); //select digit[10bit]
parameter L = 100, N = 10;
input [L*N-1:0] in;
input [ 7:0 ] sel;
output [N-1:0] out;
assign out = in[ N*(sel) +: N ];
endmodule