mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
52 lines
1.9 KiB
Systemverilog
52 lines
1.9 KiB
Systemverilog
module spi_fifo #(parameter M=3, N=8)( // 2^M entries of N bits each
|
|
input logic PCLK, wen, ren, PRESETn,
|
|
input logic winc, rinc,
|
|
input logic [N-1:0] wdata,
|
|
input logic [M-1:0] wwatermarklevel, rwatermarklevel,
|
|
output logic [N-1:0] rdata,
|
|
output logic wfull, rempty,
|
|
output logic wwatermark, rwatermark);
|
|
|
|
/* Pointer FIFO using design elements from "Simulation and Synthesis Techniques
|
|
for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers
|
|
are an extra bit larger than address size to determine full/empty conditions.
|
|
Watermark comparisons use 2's complement subtraction between the M-1 bit pointers,
|
|
which are also used to address memory
|
|
*/
|
|
|
|
logic [N-1:0] mem[2**M];
|
|
logic [M:0] rptr, wptr;
|
|
logic [M:0] rptrnext, wptrnext;
|
|
logic [M-1:0] raddr;
|
|
logic [M-1:0] waddr;
|
|
|
|
assign rdata = mem[raddr];
|
|
always_ff @(posedge PCLK)
|
|
if (winc & ~wfull) mem[waddr] <= wdata;
|
|
|
|
// write and read are enabled
|
|
always_ff @(posedge PCLK)
|
|
if (~PRESETn) begin
|
|
rptr <= '0;
|
|
wptr <= '0;
|
|
wfull <= 1'b0;
|
|
rempty <= 1'b1;
|
|
end else begin
|
|
if (wen) begin
|
|
wfull <= ({~wptrnext[M], wptrnext[M-1:0]} == rptr);
|
|
wptr <= wptrnext;
|
|
end
|
|
if (ren) begin
|
|
rptr <= rptrnext;
|
|
rempty <= (wptr == rptrnext);
|
|
end
|
|
end
|
|
|
|
assign raddr = rptr[M-1:0];
|
|
assign rptrnext = rptr + {{(M){1'b0}}, (rinc & ~rempty)};
|
|
assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull;
|
|
assign waddr = wptr[M-1:0];
|
|
assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull;
|
|
assign wptrnext = wptr + {{(M){1'b0}}, (winc & ~wfull)};
|
|
endmodule
|