forked from aolofsson/oh
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoh_fifo_sync.v
76 lines (70 loc) · 2.56 KB
/
oh_fifo_sync.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
//#############################################################################
//# Function: Synchronous FIFO #
//#############################################################################
//# Author: Andreas Olofsson #
//# License: MIT (see LICENSE file in OH! repository) #
//#############################################################################
module oh_fifo_sync #(parameter DW = 104, //FIFO width
parameter DEPTH = 32, //FIFO depth
parameter PROG_FULL = (DEPTH/2),//prog_full threshold
parameter AW = $clog2(DEPTH) //rd_count width
)
(
input clk, // clock
input nreset, // active high async reset
input [DW-1:0] din, // data to write
input wr_en, // write fifo
input rd_en, // read fifo
output [DW-1:0] dout, // output data (next cycle)
output full, // fifo full
output prog_full, // fifo is almost full
output empty, // fifo is empty
output reg [AW-1:0] rd_count // valid entries in fifo
);
reg [AW-1:0] wr_addr;
reg [AW-1:0] rd_addr;
wire fifo_read;
wire fifo_write;
assign empty = (rd_count[AW-1:0] == 0);
assign prog_full = (rd_count[AW-1:0] >= PROG_FULL);
assign full = (rd_count[AW-1:0] == (DEPTH-1));
assign fifo_read = rd_en & ~empty;
assign fifo_write = wr_en & ~full;
always @ ( posedge clk or negedge nreset)
if(!nreset)
begin
wr_addr[AW-1:0] <= 'd0;
rd_addr[AW-1:0] <= 'b0;
rd_count[AW-1:0] <= 'b0;
end
else if(fifo_write & fifo_read)
begin
wr_addr[AW-1:0] <= wr_addr[AW-1:0] + 'd1;
rd_addr[AW-1:0] <= rd_addr[AW-1:0] + 'd1;
end
else if(fifo_write)
begin
wr_addr[AW-1:0] <= wr_addr[AW-1:0] + 'd1;
rd_count[AW-1:0]<= rd_count[AW-1:0] + 'd1;
end
else if(fifo_read)
begin
rd_addr[AW-1:0] <= rd_addr[AW-1:0] + 'd1;
rd_count[AW-1:0]<= rd_count[AW-1:0] - 'd1;
end
// GENERIC DUAL PORTED MEMORY
oh_memory_dp
#(.DW(DW),
.DEPTH(DEPTH))
mem (// read port
.rd_dout (dout[DW-1:0]),
.rd_clk (clk),
.rd_en (fifo_read),
.rd_addr (rd_addr[AW-1:0]),
// write port
.wr_clk (clk),
.wr_en (fifo_write),
.wr_wem ({(DW){1'b1}}),
.wr_addr (wr_addr[AW-1:0]),
.wr_din (din[DW-1:0]));
endmodule // oh_fifo_sync