/
la_syncfifo.v
131 lines (109 loc) · 4.26 KB
/
la_syncfifo.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
/*****************************************************************************
* Function: Synchronous FIFO
* Copyright: Lambda Project Authors. All rights Reserved.
* License: MIT (see LICENSE file in Lambda repository)
*
* Docs:
*
* This is a wrapper for selecting from a set of hardened memory macros.
*
****************************************************************************/
module la_syncfifo
#(
parameter DW = 32, // Memory width
parameter DEPTH = 4, // FIFO depth
parameter NS = 1, // Number of power supplies
parameter CHAOS = 1, // generates random full logic when set
parameter CTRLW = 1, // width of asic ctrl interface
parameter TESTW = 1, // width of asic test interface
parameter TYPE = "DEFAULT" // Pass through variable for hard macro
)
(// basic interface
input clk,
input nreset,//async reset
input clear, //clear fifo statemachine (sync)
input vss, // ground signal
input [NS-1:0] vdd, // supplies
input chaosmode, // randomly assert fifo full when set
input [CTRLW-1:0] ctrl, // pass through ASIC control interface
input [TESTW-1:0] test, // pass through ASIC test interface
// write port
input wr_en, // write fifo
input [DW-1:0] wr_din, // data to write
output wr_full, // fifo full
// read port
input rd_en, // read fifo
output [DW-1:0] rd_dout, // output data
output rd_empty // fifo is empty
);
// local params
parameter AW = $clog2(DEPTH);
// local wires
reg [AW:0] wr_addr;
wire [AW:0] wr_addr_nxt;
reg [AW:0] rd_addr;
wire [AW:0] rd_addr_nxt;
wire fifo_read;
wire fifo_write;
wire chaosfull;
wire rd_wrap_around;
wire wr_wrap_around;
//############################
// FIFO Empty/Full
//############################
// support any fifo depth
assign wr_full = (chaosfull & chaosmode) |
{~wr_addr[AW], wr_addr[AW-1:0]} == rd_addr[AW:0];
assign rd_empty = wr_addr[AW:0] == rd_addr[AW:0];
assign fifo_read = rd_en & ~rd_empty;
assign fifo_write = wr_en & ~wr_full;
//############################
// FIFO Pointers - wrap around DEPTH-1
//############################
assign rd_wrap_around = rd_addr[AW-1:0] == (DEPTH[AW-1:0] - 1'b1);
assign wr_wrap_around = wr_addr[AW-1:0] == (DEPTH[AW-1:0] - 1'b1);
assign rd_addr_nxt[AW] = rd_wrap_around ? ~rd_addr[AW] : rd_addr[AW];
assign rd_addr_nxt[AW-1:0] = rd_wrap_around ? 'b0 : (rd_addr[AW-1:0] + 1);
assign wr_addr_nxt[AW] = (wr_addr[AW-1:0] == (DEPTH[AW-1:0]-1'b1)) ? ~wr_addr[AW] : wr_addr[AW];
assign wr_addr_nxt[AW-1:0] = (wr_addr[AW-1:0] == (DEPTH[AW-1:0]-1'b1)) ? 'b0 : (wr_addr[AW-1:0] + 1);
always @(posedge clk or negedge nreset)
if (~nreset) begin
wr_addr[AW:0] <= 'd0;
rd_addr[AW:0] <= 'b0;
end
else if(clear) begin
wr_addr[AW:0] <= 'd0;
rd_addr[AW:0] <= 'b0;
end
else if (fifo_write & fifo_read) begin
wr_addr[AW:0] <= wr_addr_nxt[AW:0];
rd_addr[AW:0] <= rd_addr_nxt[AW:0];
end else if (fifo_write) begin
wr_addr[AW:0] <= wr_addr_nxt[AW:0];
end else if (fifo_read) begin
rd_addr[AW:0] <= rd_addr_nxt[AW:0];
end
//###########################
//# Dual Port Memory
//###########################
reg [DW-1:0] ram[DEPTH-1:0];
// Write port (FIFO input)
always @(posedge clk) if (wr_en & ~wr_full) ram[wr_addr[AW-1:0]] <= wr_din[DW-1:0];
// Read port (FIFO output)
assign rd_dout[DW-1:0] = ram[rd_addr[AW-1:0]];
//############################
// Randomly Asserts FIFO full
//############################
generate
if (CHAOS) begin
// TODO: implement LFSR
reg chaosreg;
always @(posedge clk or negedge nreset)
if (~nreset) chaosreg <= 1'b0;
else chaosreg <= ~chaosreg;
assign chaosfull = chaosreg;
end else begin
assign chaosfull = 1'b0;
end
endgenerate
endmodule