-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcircular_buffer_controller.v
342 lines (308 loc) · 7.67 KB
/
circular_buffer_controller.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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 11:16:53 07/09/2014
// Design Name:
// Module Name: circular_buffer_controller
// Project Name:
// Target Devices:
// Tool versions:
// Description: This is a circular buffer controller, or multiple buffers
// controller.
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module circular_buffer_controller
#(
parameter WRITE_DATA_WIDTH = 8,
parameter WRITE_DATA_DEPTH = 256,
parameter READ_DATA_WIDTH = 8,
parameter READ_DATA_DEPTH = 256,
parameter BUFFER_NUM = 2,
parameter WRITE_ADDR_WIDTH = log2(WRITE_DATA_DEPTH - 1),
parameter READ_ADDR_WIDTH = log2(READ_DATA_DEPTH - 1),
parameter BUFFER_ADDR_WIDTH = log2(BUFFER_NUM - 1)
)
(
input wr_clk_i,
input rd_clk_i,
input rst_i, //active high
//-------Wr interface----------
input wr_req_i,
output wr_req_ack_o,
output wr_req_result_o,
input wr_finish_i,
output wr_finish_ack_o,
input wr_en_i,
input [WRITE_DATA_WIDTH - 1:0] wr_data_i,
input [WRITE_ADDR_WIDTH - 1:0] wr_addr_i,
//------Rd interface----------
input rd_req_i,
output rd_req_ack_o,
output rd_req_result_o,
input rd_finish_i,
output rd_finish_ack_o,
output [READ_DATA_WIDTH - 1:0] rd_data_o,
input [READ_ADDR_WIDTH - 1:0] rd_addr_i,
//-----RAM interface---------
output ram_wr_clk_o,
output ram_rd_clk_o,
output ram_rst_o,
output ram_wr_en_o,
output [WRITE_DATA_WIDTH - 1:0] ram_wr_data_o,
output [WRITE_ADDR_WIDTH + BUFFER_ADDR_WIDTH - 1:0] ram_wr_addr_o,
input [READ_DATA_WIDTH - 1:0] ram_rd_data_i,
output [READ_ADDR_WIDTH + BUFFER_ADDR_WIDTH - 1:0] ram_rd_addr_o
);
function integer log2 (input integer bd);
integer bit_depth;
begin
bit_depth = bd;
for(log2=0; bit_depth>0; log2=log2 + 1)
bit_depth = bit_depth >> 1;
end
endfunction
reg [BUFFER_ADDR_WIDTH - 1:0] wr_cnt = {BUFFER_ADDR_WIDTH{1'b0}};
reg [BUFFER_ADDR_WIDTH - 1:0] rd_cnt = {BUFFER_ADDR_WIDTH{1'b0}};
//-----------reset------------------
reg wr_rst0 = 1'b1;
reg wr_rst1 = 1'b1;
reg rd_rst0 = 1'b1;
reg rd_rst1 = 1'b1;
always@(posedge wr_clk_i or posedge rst_i)
begin
if(rst_i)
begin
wr_rst0 <= 1'b1;
wr_rst1 <= 1'b1;
end
else
begin
wr_rst0 <= 1'b0;
wr_rst1 <= wr_rst0;
end
end
always@(posedge rd_clk_i or posedge rst_i)
begin
if(rst_i)
begin
rd_rst0 <= 1'b1;
rd_rst1 <= 1'b1;
end
else
begin
rd_rst0 <= 1'b0;
rd_rst1 <= rd_rst0;
end
end
//------------------temp signals-------------------
reg tmp_wr_req_ack = 1'b0;
reg tmp_rd_req_ack = 1'b0;
reg tmp_wr_req_result = 1'b1; //有空的码流buffer;
reg tmp_rd_req_result = 1'b0; //没有满的码流buffer;
reg tmp_wr_finish_ack = 1'b0;
reg tmp_rd_finish_ack = 1'b0;
//------------for rd clk synchronizing-----------------
reg [1:0]rd_req;
reg [3:0]rd_req_ack;
reg [1:0]rd_req_result;
reg [1:0]rd_finish;
reg [1:0]rd_finish_ack;
reg [BUFFER_ADDR_WIDTH - 1:0] rd_addr_buf0;
reg [BUFFER_ADDR_WIDTH - 1:0] rd_addr_buf1;
//-------------------requst_fsm--------------------
localparam REQ_IDLE = 3'd0;
localparam REQ_WR_BUF_JUDGE = 3'd1;
localparam REQ_RD_BUF_JUDGE = 3'd2;
localparam REQ_WR_BUF = 3'd3;
localparam REQ_RD_BUF = 3'd4;
reg[2:0] req_state = REQ_IDLE;
localparam BUF_IDLE = 3'd0;
localparam BUF_WR_JUDGE = 3'd1;
localparam BUF_RD_JUDGE = 3'd2;
localparam BUF_WR_WAIT_FINISH_ZERO = 3'd3;
localparam BUF_RD_WAIT_FINISH_ZERO = 3'd4;
reg [2:0] buf_state = BUF_IDLE;
localparam RD = 1'b0,
WR = 1'b1;
reg priority = WR;
reg [BUFFER_ADDR_WIDTH+1:0] full_buf_cnt = 'd0;
always@(posedge wr_clk_i)
begin
if(wr_rst1)
begin
req_state <= REQ_IDLE;
tmp_wr_req_ack <= 1'b0;
tmp_rd_req_ack <= 1'b0;
tmp_wr_req_result <= 1'b1;
tmp_rd_req_result <= 1'b0;
priority <= WR;
end
else
begin
case(req_state)
REQ_IDLE:begin
case(priority)
WR:begin
priority <= RD;
if(wr_req_i) //有写buffer的请求;
req_state <= REQ_WR_BUF_JUDGE;
end
RD:begin
priority <= WR;
if(rd_req[1]) //有写buffer的请求;
req_state <= REQ_RD_BUF_JUDGE;
end
endcase
end
REQ_WR_BUF_JUDGE:begin
tmp_wr_req_ack <= 1'b1;
req_state <= REQ_WR_BUF;
if(full_buf_cnt < BUFFER_NUM) //没有空的buffer了;
tmp_wr_req_result <= 1'b1; //没有空的buffer了;
else
begin
tmp_wr_req_result <= 1'b0; //有空的buffer了;
end
end
REQ_RD_BUF_JUDGE:begin
tmp_rd_req_ack <= 1'b1;
req_state <= REQ_RD_BUF;
if(full_buf_cnt > 'd0) //没有满的buffer
tmp_rd_req_result <= 1'b1; //没有满的buffer了;
else
begin
tmp_rd_req_result <= 1'b0; //有满的buffer了;
end
end
REQ_WR_BUF:begin
if(!wr_req_i)
begin
tmp_wr_req_ack <= 1'b0;
req_state <= REQ_IDLE;
tmp_wr_req_result <= 1'b0;
end
end
REQ_RD_BUF:begin
if(!rd_req[1])
begin
tmp_rd_req_ack <= 1'b0;
req_state <= REQ_IDLE;
tmp_rd_req_result <= 1'b0;
end
end
endcase
end
end
reg buf_priority = WR;
always @(posedge wr_clk_i)
begin
if(wr_rst1)
begin
full_buf_cnt <= 'd0;
buf_state <= BUF_IDLE;
tmp_wr_finish_ack <= 1'b0;
tmp_rd_finish_ack <= 1'b0;
buf_priority <= WR;
end
else
begin
case(buf_state)
BUF_IDLE:begin
case(buf_priority)
WR:begin
buf_priority <= RD;
if(wr_finish_i)
begin //写完一个buffer
buf_state <= BUF_WR_JUDGE;
end
end
RD:begin
buf_priority <= WR;
if(rd_finish[1])
begin //读完一个buffer
buf_state <= BUF_RD_JUDGE;
end
end
endcase
end
BUF_WR_JUDGE: begin
tmp_wr_finish_ack <= 1'b1;
buf_state <= BUF_WR_WAIT_FINISH_ZERO;
full_buf_cnt <= full_buf_cnt + 'd1; //写完一个buffer,
//空buffer数目减1;
if(wr_cnt == BUFFER_NUM)
wr_cnt <= 'd0;
else
wr_cnt <= wr_cnt + 'd1;
end
BUF_RD_JUDGE: begin
tmp_rd_finish_ack <= 1'b1;
buf_state <= BUF_RD_WAIT_FINISH_ZERO;
full_buf_cnt <= full_buf_cnt - 'd1; //读完一个buffer,
//空buffer数目加1;
if(rd_cnt == BUFFER_NUM)
rd_cnt <= 'd0;
else
rd_cnt <= rd_cnt + 'd1;
end
BUF_WR_WAIT_FINISH_ZERO: begin
if(!wr_finish_i)
begin
tmp_wr_finish_ack <= 1'b0;
buf_state <= BUF_IDLE;
end
end
BUF_RD_WAIT_FINISH_ZERO: begin
if(!rd_finish[1])
begin
tmp_rd_finish_ack <= 1'b0;
buf_state <= BUF_IDLE;
end
end
endcase
end
end
//---------------------rd clk domain synchronizer--------------
always@(posedge wr_clk_i)
begin
rd_req[0] <= rd_req_i;
rd_req[1] <= rd_req[0];
rd_finish[0] <= rd_finish_i;
rd_finish[1] <= rd_finish[0];
end
always@(posedge rd_clk_i)
begin
rd_req_ack[0] <= tmp_rd_req_ack;
rd_req_ack[1] <= rd_req_ack[0];
rd_req_ack[2] <= rd_req_ack[1];
rd_req_ack[3] <= rd_req_ack[2];
rd_req_result[0] <= tmp_rd_req_result;
rd_req_result[1] <= rd_req_result[0];
rd_finish_ack[0] <= tmp_rd_finish_ack;
rd_finish_ack[1] <= rd_finish_ack[0];
rd_addr_buf0 <= rd_cnt;
rd_addr_buf1 <= rd_addr_buf0;
end
assign wr_req_ack_o = tmp_wr_req_ack;
assign wr_req_result_o = tmp_wr_req_result;
assign wr_finish_ack_o = tmp_wr_finish_ack;
assign rd_req_ack_o = rd_req_ack[3];
assign rd_req_result_o = rd_req_result[1];
assign rd_finish_ack_o = rd_finish_ack[1];
assign ram_wr_clk_o = wr_clk_i;
assign ram_rd_clk_o = rd_clk_i;
assign ram_rst_o = rst_i;
assign ram_wr_en_o = wr_en_i;
assign ram_wr_data_o = wr_data_i;
assign ram_wr_addr_o = {wr_cnt, wr_addr_i};
assign rd_data_o = ram_rd_data_i;
assign ram_rd_addr_o = {rd_addr_buf1, rd_addr_i};
endmodule