-
Notifications
You must be signed in to change notification settings - Fork 0
/
convolver.v
168 lines (155 loc) · 4.28 KB
/
convolver.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
`timescale 1ns / 1ps
`define FIXED_POINT 1
module convolver #(
parameter n = 9'h00a, // activation map size
parameter k = 9'h003, // kernel size
parameter s = 1, // value of stride (horizontal and vertical stride are equal)
parameter N = 16, //total bit width
parameter Q = 12 //number of fractional bits in case of fixed point representation.
)(
input clk,
input ce,
input global_rst,
input [N-1:0] activation,
input [(k*k)*16-1:0] weight1,
output[N-1:0] conv_op,
output valid_conv,
output end_conv
);
wire [N-1:0] weight [0:k*k-1];
wire [N-1:0] tmp [k*k+1:0];
wire conv_vld;
reg conv_vld_d1;
generate
genvar l;
for(l=0;l<k*k;l=l+1)
begin
assign weight [l][N-1:0] = weight1[N*l +: N];
end
endgenerate
assign tmp[0] = 'd0;
generate
genvar i;
for(i = 0;i<k*k;i=i+1)
begin: MAC
if((i+1)%k ==0) //end of the row
begin
if(i==k*k-1) //end of convolver
begin
mac_manual #(.N(N)) mac( //implements a*b+c
.clk(clk), // input clk
.ce(ce), // input ce
.sclr(global_rst), // input sclr
.a(activation), // activation input [N-1 : 0] a
.b(weight[i]), // weight input [N-1 : 0] b
.c(tmp[i]), // previous mac sum input [N-1 : 0] c
.p(conv_op) // output [N-1 : 0] p
);
end
else
begin
wire [N-1:0] tmp2;
//make a mac unit
mac_manual #(.N(N)) mac(
.clk(clk),
.ce(ce),
.sclr(global_rst),
.a(activation),
.b(weight[i]),
.c(tmp[i]),
.p(tmp2)
);
variable_shift_reg #(.WIDTH(N),.SIZE(n-k)) SR (
.d(tmp2), // input [32 : 0] d
.clk(clk), // input clk
.ce(ce), // input ce
.rst(global_rst), // input sclr
.out(tmp[i+1]) // output [32 : 0] q
);
end
end
else
begin
mac_manual #(.N(N),.Q(Q)) mac2(
.clk(clk),
.ce(ce),
.sclr(global_rst),
.a(activation),
.b(weight[i]),
.c(tmp[i]),
.p(tmp[i+1])
);
end
end
endgenerate
reg [31:0] count,count2,count3,row_count;
reg en1,en2,en3;
always@(posedge clk)
begin
if(global_rst)
begin
count <=0; //master counter: counts the clock cycles
count2<=0; //counts the valid convolution outputs
count3<=0; // counts the number of invalid onvolutions where the kernel wraps around the next row of inputs.
row_count <= 0; //counts the number of rows of the output.
en1<=0;
en2<=1;
en3<=0;
end
else if(ce)
begin
if(count == (k-1)*n+k-1) // time taken for the pipeline to fill up is (k-1)*n+k-1
begin
en1 <= 1'b1;
count <= count+1'b1;
end
else
begin
count<= count+1'b1;
end
end
if(en1 && en2)
begin
if(count2 == n-k)
begin
count2 <= 0;
en2 <= 0 ;
row_count <= row_count + 1'b1;
end
else
begin
count2 <= count2 + 1'b1;
end
end
if(~en2)
begin
if(count3 == k-2)
begin
count3<=0;
en2 <= 1'b1;
end
else
count3 <= count3 + 1'b1;
end
if((((count2 + 1) % s == 0) && (row_count % s == 0))||(count3 == k-2)&&(row_count % s == 0)||(count == (k-1)*n+k-1))
begin //one in every s convolutions becomes valid
en3 <= 1; //some exceptional cases handled for high when count2 = 0
end
else
en3 <= 0;
end
assign conv_vld = (en1 && en2 && en3);
assign end_conv = (count>= n*n+2) ? 1'b1 : 1'b0;
always@(posedge clk or posedge global_rst)
begin
if(global_rst)
conv_vld_d1<= 0;
else
conv_vld_d1 <= conv_vld;
end
`ifdef FIXED_POINT
assign valid_conv = conv_vld_d1;
`else
assign valid_conv = conv_vld;
`endif
endmodule