Files
b210-k7-fpga/lib/rfnoc/fosphor/fifo_srl.v
T
Wade Fife 8220e57a17 rfnoc: Add RFNoC fosphor block
Original-commit: d386c750074f6da4ab86038e2c30a3fe6e0f9d47
2020-04-14 16:37:43 -05:00

170 lines
3.1 KiB
Verilog

/*
* fifo_srl.v
*
* Very small/light-weight FIFO using SRL.
* Only for synchronous design. Has a fixed depth of 15 or 31 entries and
* always work in the so-called first-word-fall-thru mode.
*
* Copyright (C) 2014 Ettus Corporation LLC
* Copyright 2018 Ettus Research, a National Instruments Company
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* vim: ts=4 sw=4
*/
`ifdef SIM
`default_nettype none
`endif
module fifo_srl #(
parameter integer WIDTH = 4,
parameter integer LOG2_DEPTH = 5, // 4 or 5
parameter integer AFULL_LEVEL = -1 // -1 -> No AFULL
)(
input wire [WIDTH-1:0] di,
input wire wren,
output wire full,
output wire afull,
output reg [WIDTH-1:0] do = {WIDTH{1'b0}},
input wire rden,
output reg empty,
input wire clk,
input wire rst
);
genvar i;
// Signals
wire [WIDTH-1:0] srl_q;
reg [LOG2_DEPTH-1:0] srl_addr;
wire srl_addr_ce;
wire srl_write;
wire srl_read;
wire srl_full;
wire srl_afull;
reg srl_empty;
wire srl_aempty;
// Instanciate the SRLs
generate
if (LOG2_DEPTH == 6) begin
wire [WIDTH-1:0] srl0_q31, srl0_q, srl1_q;
for (i=0; i<WIDTH; i=i+1)
begin : srl_64
SRLC32E srl_I0 (
.Q(srl0_q[i]),
.Q31(srl0_q31[i]),
.A(srl_addr[4:0]),
.CE(srl_write),
.CLK(clk),
.D(di[i])
);
SRLC32E srl_I1 (
.Q(srl1_q[i]),
.A(srl_addr[4:0]),
.CE(srl_write),
.CLK(clk),
.D(srl0_q31[i])
);
MUXF7 mux_I (
.O(srl_q[i]),
.I0(srl0_q[i]),
.I1(srl1_q[i]),
.S(srl_addr[5])
);
end
end else if (LOG2_DEPTH == 5) begin
for (i=0; i<WIDTH; i=i+1)
SRLC32E srl_I (
.Q(srl_q[i]),
.A(srl_addr),
.CE(srl_write),
.CLK(clk),
.D(di[i])
);
end else if (LOG2_DEPTH == 4) begin
for (i=0; i<WIDTH; i=i+1)
SRL16E srl_I (
.Q(srl_q[i]),
.A0(srl_addr[0]),
.A1(srl_addr[1]),
.A2(srl_addr[2]),
.A3(srl_addr[3]),
.CE(srl_write),
.CLK(clk),
.D(di[i])
);
end
endgenerate
// Address counter
assign srl_addr_ce = srl_write ^ srl_read;
always @(posedge clk)
begin
if (rst)
srl_addr <= {LOG2_DEPTH{1'b1}};
else if (srl_addr_ce) begin
if (srl_write)
srl_addr <= srl_addr + 1;
else
srl_addr <= srl_addr - 1;
end
end
// SRL status
assign srl_full = srl_addr == {{(LOG2_DEPTH-1){1'b1}}, 1'b0};
generate
if (AFULL_LEVEL != -1) begin
assign srl_afull = (srl_addr >= AFULL_LEVEL) && ~&(srl_addr);
end else begin
assign srl_afull = 1'b0;
end
endgenerate
assign srl_aempty = &(~srl_addr);
always @(posedge clk)
begin
if (rst)
srl_empty <= 1'b1;
else if (srl_addr_ce)
srl_empty <= srl_aempty & srl_read;
end
// Output register (to capture whatever comes out from SRL)
always @(posedge clk)
begin
if (srl_read)
do <= srl_q;
end
// Control and flag generation
// Write/Full is easy
assign srl_write = wren;
assign full = srl_full;
assign afull = srl_afull;
// Read/Empty is tricky
always @(posedge clk)
begin
if (rst)
empty <= 1'b1;
else if (rden | srl_read)
empty <= srl_empty;
end
assign srl_read = (rden | empty) & ~srl_empty;
endmodule // fifo_srl