|
| 1 | +/* |
| 2 | + Fully connected layer |
| 3 | +*/ |
| 4 | +module layer_4(clk, rst_n, strt, din, tx_done, dout, rdy); |
| 5 | +input clk, rst_n; |
| 6 | +input strt; |
| 7 | +input tx_done; |
| 8 | +input signed [17:0] din; |
| 9 | +output [17:0] dout[15:0]; |
| 10 | +output rdy; |
| 11 | + |
| 12 | +reg wr; |
| 13 | +reg [1:0] addr_wr; |
| 14 | +wire [1:0] addr_rd; |
| 15 | +wire [1:0] addr_rd_ram; |
| 16 | +wire [35:0] din_ram[15:0]; |
| 17 | +wire [35:0] dout_ram[15:0]; |
| 18 | + |
| 19 | +genvar a; |
| 20 | +generate |
| 21 | + for (a = 0; a < 16; a = a + 1) begin: l4_ram |
| 22 | + ram #(.ADDR_WIDTH(2), .DATA_WIDTH(36)) l4_ram(.clk(clk), .wr(wr) |
| 23 | + , .addr_wr(addr_wr), .addr_rd(addr_rd), .din(din_ram[a]) |
| 24 | + , .dout(dout_ram[a])); |
| 25 | + end |
| 26 | +endgenerate |
| 27 | + |
| 28 | +genvar n; |
| 29 | +generate |
| 30 | + for (n = 0; n < 16; n = n + 1) begin: dout_g |
| 31 | + assign dout[n] = dout_ram[n][17:0]; |
| 32 | + end |
| 33 | +endgenerate |
| 34 | + |
| 35 | +wire [8:0] dout_rom[15:0]; |
| 36 | +reg [8:0] addr_rd_rom; |
| 37 | +rom #(.file("./ml_params/l4_weight_0.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w0(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[0])); |
| 38 | +rom #(.file("./ml_params/l4_weight_1.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w1(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[1])); |
| 39 | +rom #(.file("./ml_params/l4_weight_2.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w2(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[2])); |
| 40 | +rom #(.file("./ml_params/l4_weight_3.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w3(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[3])); |
| 41 | +rom #(.file("./ml_params/l4_weight_4.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w4(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[4])); |
| 42 | +rom #(.file("./ml_params/l4_weight_5.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w5(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[5])); |
| 43 | +rom #(.file("./ml_params/l4_weight_6.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w6(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[6])); |
| 44 | +rom #(.file("./ml_params/l4_weight_7.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w7(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[7])); |
| 45 | +rom #(.file("./ml_params/l4_weight_8.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w8(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[8])); |
| 46 | +rom #(.file("./ml_params/l4_weight_9.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w9(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[9])); |
| 47 | +rom #(.file("./ml_params/l4_weight_10.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w10(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[10])); |
| 48 | +rom #(.file("./ml_params/l4_weight_11.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w11(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[11])); |
| 49 | +rom #(.file("./ml_params/l4_weight_12.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w12(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[12])); |
| 50 | +rom #(.file("./ml_params/l4_weight_13.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w13(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[13])); |
| 51 | +rom #(.file("./ml_params/l4_weight_14.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w14(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[14])); |
| 52 | +rom #(.file("./ml_params/l4_weight_15.txt"), .ADDR_WIDTH(9), .DATA_WIDTH(9)) l4_rom_w15(.clk(clk), .addr_rd(addr_rd_rom), .dout(dout_rom[15])); |
| 53 | + |
| 54 | +reg addr_rom_inc; |
| 55 | +always @(posedge clk, negedge rst_n) begin |
| 56 | + if (!rst_n) |
| 57 | + addr_rd_rom <= 9'h0; |
| 58 | + else if (tx_done) |
| 59 | + addr_rd_rom <= 9'h0; |
| 60 | + else if (addr_rom_inc) |
| 61 | + addr_rd_rom <= addr_rd_rom + 9'h1; |
| 62 | +end |
| 63 | + |
| 64 | +wire signed [17:0] dout_rom_ex[15:0]; |
| 65 | +genvar i; |
| 66 | +generate |
| 67 | + for (i = 0; i < 16; i = i + 1) begin: dout_rom_ex_g |
| 68 | + assign dout_rom_ex[i] = {{9{dout_rom[i][8]}}, dout_rom[i][8:0]}; |
| 69 | + end |
| 70 | +endgenerate |
| 71 | + |
| 72 | +reg cnt_100_inc; |
| 73 | +reg [6:0] cnt_100; |
| 74 | +always @(posedge clk, negedge rst_n) begin |
| 75 | + if (!rst_n) |
| 76 | + cnt_100 <= 7'h0; |
| 77 | + else if (tx_done) |
| 78 | + cnt_100 <= 7'h0; |
| 79 | + else if (cnt_100_inc) |
| 80 | + cnt_100 <= cnt_100 + 7'h1; |
| 81 | +end |
| 82 | + |
| 83 | + |
| 84 | +wire signed [35:0] mult[15:0]; |
| 85 | +wire [35:0] accum[15:0]; |
| 86 | +genvar j; |
| 87 | +generate |
| 88 | + for (j = 0; j < 16; j = j + 1) begin: mult_g |
| 89 | + assign mult[j] = din * dout_rom_ex[j]; |
| 90 | + assign accum[j] = cnt_100 == 7'h0 ? mult[j] : mult[j] + dout_ram[j]; |
| 91 | + end |
| 92 | +endgenerate |
| 93 | + |
| 94 | +reg [1:0] addr_rd_bias; |
| 95 | +wire [8:0] dout_bias[15:0]; |
| 96 | +rom #(.file("./ml_params/l4_bias_0.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b0(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[0])); |
| 97 | +rom #(.file("./ml_params/l4_bias_1.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b1(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[1])); |
| 98 | +rom #(.file("./ml_params/l4_bias_2.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b2(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[2])); |
| 99 | +rom #(.file("./ml_params/l4_bias_3.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b3(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[3])); |
| 100 | +rom #(.file("./ml_params/l4_bias_4.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b4(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[4])); |
| 101 | +rom #(.file("./ml_params/l4_bias_5.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b5(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[5])); |
| 102 | +rom #(.file("./ml_params/l4_bias_6.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b6(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[6])); |
| 103 | +rom #(.file("./ml_params/l4_bias_7.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b7(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[7])); |
| 104 | +rom #(.file("./ml_params/l4_bias_8.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b8(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[8])); |
| 105 | +rom #(.file("./ml_params/l4_bias_9.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b9(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[9])); |
| 106 | +rom #(.file("./ml_params/l4_bias_10.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b10(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[10])); |
| 107 | +rom #(.file("./ml_params/l4_bias_11.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b11(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[11])); |
| 108 | +rom #(.file("./ml_params/l4_bias_12.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b12(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[12])); |
| 109 | +rom #(.file("./ml_params/l4_bias_13.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b13(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[13])); |
| 110 | +rom #(.file("./ml_params/l4_bias_14.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b14(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[14])); |
| 111 | +rom #(.file("./ml_params/l4_bias_15.txt"), .ADDR_WIDTH(2), .DATA_WIDTH(9)) l4_rom_b15(.clk(clk), .addr_rd(addr_rd_bias), .dout(dout_bias[15])); |
| 112 | + |
| 113 | +wire signed [35:0] bias[15:0]; |
| 114 | +wire [35:0] relu[15:0]; |
| 115 | +genvar k; |
| 116 | +generate |
| 117 | + for (k = 0; k < 16; k = k + 1) begin: bias_g |
| 118 | + assign bias[k] = accum[k] + {{27{dout_bias[k][8]}}, dout_bias[k][8:0]}; |
| 119 | + assign relu[k] = bias[k] > 0 ? bias[k] : 36'h0; |
| 120 | + end |
| 121 | +endgenerate |
| 122 | + |
| 123 | +genvar m; |
| 124 | +generate |
| 125 | + for (m = 0; m < 16; m = m + 1) begin: din_ram_g |
| 126 | + assign din_ram[m] = cnt_100 == 7'h63 ? relu[m] : accum[m]; |
| 127 | + end |
| 128 | +endgenerate |
| 129 | + |
| 130 | +typedef enum reg [2:0] {INI, ONE, TWO, THREE, FOUR} state_wr_t; |
| 131 | +state_wr_t state_wr, nxt_state_wr; |
| 132 | +always @(posedge clk, negedge rst_n) begin |
| 133 | + if (!rst_n) |
| 134 | + state_wr <= INI; |
| 135 | + else if (tx_done) |
| 136 | + state_wr <= INI; |
| 137 | + else |
| 138 | + state_wr <= nxt_state_wr; |
| 139 | +end |
| 140 | + |
| 141 | +reg [1:0] addr_rd_pre; |
| 142 | +always_comb begin |
| 143 | + nxt_state_wr = INI; |
| 144 | + addr_wr = 2'h0; |
| 145 | + addr_rd_pre = 2'h0; |
| 146 | + addr_rd_bias = 2'h0; |
| 147 | + addr_rom_inc = 0; |
| 148 | + cnt_100_inc = 0; |
| 149 | + wr = 0; |
| 150 | + |
| 151 | + case(state_wr) |
| 152 | + INI: begin |
| 153 | + if (strt) begin |
| 154 | + nxt_state_wr = ONE; |
| 155 | + addr_rd_bias = 2'h0; |
| 156 | + addr_rom_inc = 1; |
| 157 | + addr_rd_pre = 2'h0; |
| 158 | + end |
| 159 | + end |
| 160 | + ONE: begin |
| 161 | + nxt_state_wr = TWO; |
| 162 | + addr_rd_bias = 2'h1; |
| 163 | + addr_rom_inc = 1; |
| 164 | + addr_wr = 2'h0; |
| 165 | + addr_rd_pre = 2'h1; |
| 166 | + wr = 1; |
| 167 | + end |
| 168 | + TWO: begin |
| 169 | + nxt_state_wr = THREE; |
| 170 | + addr_rd_bias = 2'h2; |
| 171 | + addr_rom_inc = 1; |
| 172 | + addr_wr = 2'h1; |
| 173 | + addr_rd_pre = 2'h2; |
| 174 | + wr = 1; |
| 175 | + end |
| 176 | + THREE: begin |
| 177 | + nxt_state_wr = FOUR; |
| 178 | + addr_rd_bias = 2'h3; |
| 179 | + addr_rom_inc = 1; |
| 180 | + addr_wr = 2'h2; |
| 181 | + addr_rd_pre = 2'h3; |
| 182 | + wr = 1; |
| 183 | + end |
| 184 | + default: begin |
| 185 | + cnt_100_inc = 1; |
| 186 | + addr_wr = 2'h3; |
| 187 | + wr = 1; |
| 188 | + end |
| 189 | + endcase |
| 190 | +end |
| 191 | + |
| 192 | + |
| 193 | +// Read DATA |
| 194 | +assign rdy = cnt_100 == 7'h64; |
| 195 | + |
| 196 | +typedef enum reg [2:0] {I, O, TW, TH, F} state_rd_t; |
| 197 | +state_rd_t state_rd, nxt_state_rd; |
| 198 | +always @(posedge clk, negedge rst_n) begin |
| 199 | + if (!rst_n) |
| 200 | + state_rd <= I; |
| 201 | + else if (tx_done) |
| 202 | + state_rd <= I; |
| 203 | + else |
| 204 | + state_rd <= nxt_state_rd; |
| 205 | +end |
| 206 | + |
| 207 | +reg [1:0]addr_rd_suc; |
| 208 | +always_comb begin |
| 209 | + nxt_state_rd = I; |
| 210 | + addr_rd_suc = 2'h0; |
| 211 | + |
| 212 | + case(state_rd) |
| 213 | + I: begin |
| 214 | + if (rdy) begin |
| 215 | + nxt_state_rd = O; |
| 216 | + addr_rd_suc = 2'h0; |
| 217 | + end |
| 218 | + end |
| 219 | + O: begin |
| 220 | + nxt_state_rd = TW; |
| 221 | + addr_rd_suc = 2'h1; |
| 222 | + end |
| 223 | + TW:begin |
| 224 | + nxt_state_rd = TH; |
| 225 | + addr_rd_suc = 2'h2; |
| 226 | + |
| 227 | + end |
| 228 | + TH: begin |
| 229 | + nxt_state_rd = F; |
| 230 | + addr_rd_suc = 2'h3; |
| 231 | + end |
| 232 | + default: begin |
| 233 | + nxt_state_rd = I; |
| 234 | + end |
| 235 | + endcase |
| 236 | +end |
| 237 | + |
| 238 | +assign addr_rd = cnt_100 >= 7'h64 ? addr_rd_suc : addr_rd_pre; |
| 239 | + |
| 240 | + |
| 241 | +endmodule |
0 commit comments