-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfully_connected.v
145 lines (127 loc) · 4.48 KB
/
fully_connected.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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/03 10:32:26
// Design Name:
// Module Name: fully_connected
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module fully_connected#(
parameter INPUT_NUM = 1 ,
parameter OUTPUT_NUM = 1 ,
parameter NUM_WEIGHT = 25 ,
parameter WEIGHT_INT_WIDTH = 1 ,
parameter DATA_WIDTH = 16 ,
parameter ACT_TYPE = "Relu"
)
(
input clk ,
input rst_n ,
input input_valid ,
input signed [DATA_WIDTH * INPUT_NUM - 1:0] input_data ,
output reg out_valid ,
output reg signed [DATA_WIDTH * OUTPUT_NUM - 1:0] out_data
);
parameter ADDRESS_WIDTH = $clog2(NUM_WEIGHT);
wire work_en_fully_connected ;
reg work_en_w ;
reg work_en_b ;
reg [ADDRESS_WIDTH:0] address ;
reg signed [DATA_WIDTH*2:0] out_data_reg ;
reg signed [DATA_WIDTH - 1:0] out_data_reg_ ;
wire signed [DATA_WIDTH*2:0] out_reg ;
reg signed [2*DATA_WIDTH-1:0] bias ;
reg out_valid_flag ;
assign work_en_conv = input_valid;
always@(posedge clk or negedge rst_n)
if(!rst_n)
work_en_w <= 1'b0;
else if(work_en_fully_connected)
begin
if(address == NUM_WEIGHT)
work_en_w <= 1'b0;
else
work_en_w <= 1'b1;
end
else
work_en_w <= 1'b0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
work_en_b <= 1'b0;
else if(work_en_fully_connected && address == NUM_WEIGHT)
work_en_b <= 1'b1;
else
work_en_b <= 1'b0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
address <= 0;
else if(work_en_w)
address <= address + 1'b1;
else
address <= address;
always@(posedge clk or negedge rst_n)
if(!rst_n)
out_data_reg <= 0;
else if(work_en_w)
out_data_reg <= out_data_reg + out_data;
else if(work_en_b)
out_data_reg <= out_data_reg + bias;
else if(out_valid)
out_data_reg <= 0;
else
out_data_reg <= out_data_reg;
always@(posedge clk or negedge rst_n)
if(!rst_n)
out_valid_flag <= 1'b0;
else if(work_en_b)
out_valid_flag <= 1'b1;
else
out_valid_flag <= 1'b0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
out_valid <= 1'b0;
else if(out_valid_flag)
out_valid <= 1'b1;
else if(out_valid)
out_valid <= 1'b0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
out_data <= 0;
else if(out_valid_flag)
out_data <= out_data_reg_;
else
out_data <= 0;
assign out_reg = output_w * input_data;
/* `ifdef pretrained
initial
begin
$readmemb(biasFile,biasReg);
end
always @(posedge clk)
begin
bias <= {biasReg[0][DATA_WIDTH-1:0],{DATA_WIDTH{1'b0}}};
end
`endif*/
weight_memory weight_memory(
.clk(clk) ,
.address(address) ,
.output_data(output_w)
);
Relu#(.DATA_WIDTH(DATA_WIDTH),.WEIGHT_INT_WIDTH(WEIGHT_INT_WIDTH))
(
.x(out_data_reg),
.y(out_data_reg_)
);
endmodule