summaryrefslogtreecommitdiffstats
path: root/usrp2/extramfifo
diff options
context:
space:
mode:
Diffstat (limited to 'usrp2/extramfifo')
-rw-r--r--usrp2/extramfifo/ext_fifo.v29
-rw-r--r--usrp2/extramfifo/ext_fifo_tb.v70
-rw-r--r--usrp2/extramfifo/nobl_fifo.v229
3 files changed, 102 insertions, 226 deletions
diff --git a/usrp2/extramfifo/ext_fifo.v b/usrp2/extramfifo/ext_fifo.v
index 398e5ef81..c6a64fc65 100644
--- a/usrp2/extramfifo/ext_fifo.v
+++ b/usrp2/extramfifo/ext_fifo.v
@@ -15,8 +15,10 @@
// packed into the IO ring.
//
+ //`define NO_EXT_FIFO
+
module ext_fifo
- #(parameter INT_WIDTH=36,EXT_WIDTH=18,DEPTH=19)
+ #(parameter INT_WIDTH=36,EXT_WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
(
input int_clk,
input ext_clk,
@@ -24,7 +26,7 @@ module ext_fifo
input [EXT_WIDTH-1:0] RAM_D_pi,
output [EXT_WIDTH-1:0] RAM_D_po,
output RAM_D_poe,
- output [DEPTH-1:0] RAM_A,
+ output [RAM_DEPTH-1:0] RAM_A,
output RAM_WEn,
output RAM_CENn,
output RAM_LDn,
@@ -59,16 +61,15 @@ module ext_fifo
.empty(empty1));
assign dst_rdy_o = ~full1;
-
-/* -----\/----- EXCLUDED -----\/-----
+
+`ifdef NO_EXT_FIFO
assign space_avail = ~full2;
assign data_avail = ~empty1;
assign read_data = write_data;
- -----/\----- EXCLUDED -----/\----- */
+`else
-
// External FIFO running at ext clock rate and 18 bit width.
- nobl_fifo #(.WIDTH(EXT_WIDTH),.DEPTH(DEPTH),.FDEPTH(DEPTH))
+ nobl_fifo #(.WIDTH(EXT_WIDTH),.RAM_DEPTH(RAM_DEPTH),.FIFO_DEPTH(FIFO_DEPTH))
nobl_fifo_i1
(
.clk(ext_clk),
@@ -83,14 +84,14 @@ module ext_fifo
.RAM_OEn(RAM_OEn),
.RAM_CE1n(RAM_CE1n),
.write_data(write_data),
- .write_strobe(space_avail & ~empty1 ),
+ .write_strobe(~empty1 ),
.space_avail(space_avail),
.read_data(read_data),
- .read_strobe(data_avail & ~full2),
- .data_avail(data_avail),
- .upstream_full(almost_full2)
+ .read_strobe(~almost_full2),
+ .data_avail(data_avail)
);
-
+`endif // !`ifdef NO_EXT_FIFO
+
// FIFO buffers data read from external FIFO into DSP clk domain and to TX DSP.
fifo_xlnx_512x36_2clk_18to36 fifo_xlnx_512x36_2clk_18to36_i1 (
@@ -98,7 +99,7 @@ module ext_fifo
.wr_clk(ext_clk),
.rd_clk(int_clk),
.din(read_data), // Bus [17 : 0]
- .wr_en(data_avail & ~full2 ),
+ .wr_en(data_avail),
.rd_en(dst_rdy_i),
.dout(dataout), // Bus [35 : 0]
.full(full2),
@@ -106,5 +107,5 @@ module ext_fifo
.empty(empty2));
assign src_rdy_o = ~empty2;
-
+
endmodule // ext_fifo
diff --git a/usrp2/extramfifo/ext_fifo_tb.v b/usrp2/extramfifo/ext_fifo_tb.v
index a93d524d5..db5f31a9d 100644
--- a/usrp2/extramfifo/ext_fifo_tb.v
+++ b/usrp2/extramfifo/ext_fifo_tb.v
@@ -1,7 +1,8 @@
`timescale 1ns / 1ps
`define INT_WIDTH 36
`define EXT_WIDTH 18
-`define DEPTH 19
+`define RAM_DEPTH 19
+`define FIFO_DEPTH 8
`define DUMP_VCD_FULL
module ext_fifo_tb();
@@ -17,7 +18,7 @@ module ext_fifo_tb();
wire [`EXT_WIDTH-1:0] RAM_D_po;
wire [`EXT_WIDTH-1:0] RAM_D;
wire RAM_D_poe;
- wire [`DEPTH-1:0] RAM_A;
+ wire [`RAM_DEPTH-1:0] RAM_A;
wire RAM_WEn;
wire RAM_CENn;
wire RAM_LDn;
@@ -30,6 +31,7 @@ module ext_fifo_tb();
reg [`INT_WIDTH-1:0] ref_dataout;
wire src_rdy_o; // not EMPTY
reg dst_rdy_i;
+ integer ether_frame;
// Clocks
@@ -39,7 +41,6 @@ module ext_fifo_tb();
begin
int_clk <= 0;
ext_clk <= 0;
- datain <= 0;
ref_dataout <= 1;
src_rdy_i <= 0;
dst_rdy_i <= 0;
@@ -53,6 +54,9 @@ module ext_fifo_tb();
initial
begin
+ datain <= 0;
+ ether_frame <= 0;
+
rst <= 1;
repeat (5) @(negedge int_clk);
rst <= 0;
@@ -62,6 +66,18 @@ module ext_fifo_tb();
@(negedge int_clk);
datain <= datain + dst_rdy_o;
src_rdy_i <= dst_rdy_o;
+ // Simulate inter-frame time
+ if (ether_frame == 1500)
+ begin
+ ether_frame <= 0;
+ repeat(1600)
+ begin
+ @(negedge int_clk);
+ src_rdy_i <= 0;
+ end
+ end
+ else
+ ether_frame <= ether_frame + dst_rdy_o;
end
end // initial begin
@@ -73,8 +89,20 @@ module ext_fifo_tb();
// Fall through fifo, first output already valid
if (dataout !== ref_dataout)
$display("Error: Expected %x, got %x",ref_dataout, dataout);
-
- while (ref_dataout < 10000)
+ // Decimate by 16 rate
+ while (ref_dataout < 2000)
+ begin
+ @(negedge int_clk);
+ ref_dataout <= ref_dataout + src_rdy_o ;
+ dst_rdy_i <= src_rdy_o;
+ if ((dataout !== ref_dataout) && src_rdy_o)
+ $display("Error: Expected %x, got %x",ref_dataout, dataout);
+ @(negedge int_clk);
+ dst_rdy_i <= 0;
+ repeat(14) @(negedge int_clk);
+ end // while (ref_dataout < 10000)
+ // Decimate by 8 rate
+ while (ref_dataout < 4000)
begin
@(negedge int_clk);
ref_dataout <= ref_dataout + src_rdy_o ;
@@ -84,7 +112,33 @@ module ext_fifo_tb();
@(negedge int_clk);
dst_rdy_i <= 0;
repeat(6) @(negedge int_clk);
- end
+ end // while (ref_dataout < 10000)
+ // Decimate by 4 rate
+ while (ref_dataout < 6000)
+ begin
+ @(negedge int_clk);
+ ref_dataout <= ref_dataout + src_rdy_o ;
+ dst_rdy_i <= src_rdy_o;
+ if ((dataout !== ref_dataout) && src_rdy_o)
+ $display("Error: Expected %x, got %x",ref_dataout, dataout);
+ @(negedge int_clk);
+ dst_rdy_i <= 0;
+ repeat(2) @(negedge int_clk);
+ end // while (ref_dataout < 10000)
+ // Max rate
+ while (ref_dataout < 10000)
+ begin
+ @(negedge int_clk);
+ ref_dataout <= ref_dataout + src_rdy_o ;
+ dst_rdy_i <= src_rdy_o;
+ if ((dataout !== ref_dataout) && src_rdy_o)
+ $display("Error: Expected %x, got %x",ref_dataout, dataout);
+
+ end // while (ref_dataout < 10000)
+
+ @(negedge int_clk);
+ $finish;
+
end
@@ -228,7 +282,7 @@ module ext_fifo_tb();
endgenerate
- wire [`DEPTH-1:0] RAM_A_ext;
+ wire [`RAM_DEPTH-1:0] RAM_A_ext;
wire RAM_WEn_ext,RAM_LDn_ext,RAM_CE1n_ext,RAM_OEn_ext,RAM_CENn_ext;
assign #1 RAM_D_pi = RAM_D_pi_ext;
@@ -292,7 +346,7 @@ module ext_fifo_tb();
ext_fifo
- #(.INT_WIDTH(`INT_WIDTH),.EXT_WIDTH(`EXT_WIDTH),.DEPTH(`DEPTH))
+ #(.INT_WIDTH(`INT_WIDTH),.EXT_WIDTH(`EXT_WIDTH),.RAM_DEPTH(`RAM_DEPTH),.FIFO_DEPTH(`FIFO_DEPTH))
ext_fifo_i1
(
.int_clk(int_clk),
diff --git a/usrp2/extramfifo/nobl_fifo.v b/usrp2/extramfifo/nobl_fifo.v
index 03e3f5223..19f5fb84e 100644
--- a/usrp2/extramfifo/nobl_fifo.v
+++ b/usrp2/extramfifo/nobl_fifo.v
@@ -1,18 +1,19 @@
// Since this FIFO uses a ZBT/NoBL SRAM for its storage which is a since port
// device it can only sustain data throughput at half the RAM clock rate.
// Fair arbitration to ensure this occurs is included in this logic and
-// requests for transactions that can not be completed are held off by (re)using the
-// "full" and "empty" flags.
+// requests for transactions that can not be completed are held off.
+// This FIFO requires a an external signal driving read_strobe that assures space for at least 6
+// reads since this the theopretical maximum number in flight due to pipeling.
module nobl_fifo
- #(parameter WIDTH=18,DEPTH=19,FDEPTH=10)
+ #(parameter WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
(
input clk,
input rst,
input [WIDTH-1:0] RAM_D_pi,
output [WIDTH-1:0] RAM_D_po,
output RAM_D_poe,
- output [DEPTH-1:0] RAM_A,
+ output [RAM_DEPTH-1:0] RAM_A,
output RAM_WEn,
output RAM_CENn,
output RAM_LDn,
@@ -21,42 +22,32 @@ module nobl_fifo
input [WIDTH-1:0] write_data,
input write_strobe,
output reg space_avail,
- output reg [WIDTH-1:0] read_data,
- input read_strobe,
- output reg data_avail,
- input upstream_full // (Connect to almost full flag upstream)
+ output [WIDTH-1:0] read_data,
+ input read_strobe, // Triggers a read, result in approximately 6 cycles.
+ output data_avail // Qulaifys read data available this cycle on read_data.
);
- reg [FDEPTH-1:0] capacity;
- reg [FDEPTH-1:0] wr_pointer;
- reg [FDEPTH-1:0] rd_pointer;
- wire [DEPTH-1:0] address;
- reg supress;
- reg data_avail_int; // Data available with high latency from ext FIFO flag
- wire [WIDTH-1:0] data_in;
- wire data_in_valid;
- reg [WIDTH-1:0] read_data_pending;
- reg pending_avail;
- wire read_strobe_int;
+ reg [FIFO_DEPTH-1:0] capacity;
+ reg [FIFO_DEPTH-1:0] wr_pointer;
+ reg [FIFO_DEPTH-1:0] rd_pointer;
+ wire [RAM_DEPTH-1:0] address;
+ reg data_avail_int; // Internal not empty flag.
-
-
- assign read = read_strobe_int && data_avail_int;
- assign write = write_strobe && space_avail;
+ assign read = read_strobe && data_avail_int;
+ assign write = write_strobe && space_avail;
- // When a read and write collision occur, supress the availability flags next cycle
+ // When a read and write collision occur, supress the space_avail flag next cycle
// and complete write followed by read over 2 cycles. This forces balanced arbitration
// and makes for a simple logic design.
always @(posedge clk)
if (rst)
begin
- capacity <= 1 << (FDEPTH-1);
+ capacity <= 1 << (FIFO_DEPTH-1);
wr_pointer <= 0;
rd_pointer <= 0;
space_avail <= 0;
data_avail_int <= 0;
- supress <= 0;
end
else
begin
@@ -64,187 +55,15 @@ module nobl_fifo
// Capacity is already zero; Capacity is 1 and write is asserted (lookahead); both read and write are asserted (collision)
space_avail <= ~((capacity == 0) || (read&&write) || ((capacity == 1) && write) );
// Capacity has 1 cycle delay so look ahead here for corner case of read of last item in FIFO.
- data_avail_int <= ~((capacity == (1 << (FDEPTH-1))) || (read&&write) || ((capacity == ((1 << (FDEPTH-1))-1)) && read) );
- supress <= read && write;
+ data_avail_int <= ~((capacity == (1 << (FIFO_DEPTH-1))) || ((capacity == ((1 << (FIFO_DEPTH-1))-1)) && read) );
wr_pointer <= wr_pointer + write;
- rd_pointer <= rd_pointer + ((~write && read) || supress);
- capacity <= capacity - write + ((~write && read) || supress); // REVISIT
+ rd_pointer <= rd_pointer + (~write && read);
+ capacity <= capacity - write + (~write && read) ;
end // else: !if(rst)
assign address = write ? wr_pointer : rd_pointer;
- assign enable = write || read || supress;
-
- //
- // Need to have first item in external FIFO moved into local registers for single cycle latency and throughput on read.
- // 2 local registers are provided so that a read every other clock cycle can be sustained.
- // No fowarding logic is provided to bypass the external FIFO as latency is of no concern.
- //
- always @(posedge clk)
- if (rst)
- begin
- read_data <= 0;
- data_avail <= 0;
- read_data_pending <= 0;
- pending_avail <= 0;
- end
- else
- begin
- case({read_strobe,data_in_valid})
- // No read externally, no new data arriving from external FIFO
- 2'b00: begin
- case({data_avail,pending_avail})
- // Start Data empty, Pending empty.
- //
- // End Data full, Pending empty
- 2'b00: begin
- read_data <= read_data;
- data_avail <= data_avail;
- read_data_pending <= read_data_pending ;
- pending_avail <= pending_avail;
- end
- // Start Data empty, Pending full.
- // Data <= Pending,
- // End Data full, Penidng empty.
- 2'b01: begin
- read_data <= read_data_pending;
- data_avail <= 1'b1;
- read_data_pending <= read_data_pending ;
- pending_avail <= 1'b0;
- end
- // Start Data full, Pending empty.
- //
- // End Data full, Pending empty
- 2'b10: begin
- read_data <= read_data;
- data_avail <= data_avail;
- read_data_pending <= read_data_pending ;
- pending_avail <= pending_avail;
- end
- // Start Data full, Pending full.
- //
- // End Data full, Pending full.
- 2'b11: begin
- read_data <= read_data;
- data_avail <= data_avail;
- read_data_pending <= read_data_pending ;
- pending_avail <= pending_avail;
- end
- endcase
- end
- // No read externally, new data arriving from external FIFO
- 2'b01: begin
- case({data_avail,pending_avail})
- // Start Data empty, Pending empty.
- // Data <= FIFO
- // End Data full, Pending empty
- 2'b00: begin
- read_data <= data_in;
- data_avail <= 1'b1;
- read_data_pending <= read_data_pending ;
- pending_avail <= 1'b0;
- end
- // Start Data empty, Pending full.
- // Data <= Pending, Pending <= FIFO
- // End Data full, Penidng full.
- 2'b01: begin
- read_data <= read_data_pending;
- data_avail <= 1'b1;
- read_data_pending <= data_in ;
- pending_avail <= 1'b1;
- end
- // Start Data full, Pending empty.
- // Pending <= FIFO
- // End Data full, Pending full
- 2'b10: begin
- read_data <= read_data;
- data_avail <= 1'b1;
- read_data_pending <= data_in ;
- pending_avail <= 1'b1;
- end
- // Data full, Pending full.
- // *ILLEGAL STATE*
- 2'b11: begin
-
- end
- endcase
- end
- // Read externally, no new data arriving from external FIFO
- 2'b10: begin
- case({data_avail,pending_avail})
- // Start Data empty, Pending empty.
- // *ILLEGAL STATE*
- 2'b00: begin
-
- end
- // Start Data empty, Pending full.
- // *ILLEGAL STATE*
- 2'b01: begin
-
- end
- // Start Data full, Pending empty.
- // Out <= Data
- // End Data empty, Pending empty.
- 2'b10: begin
- read_data <= read_data;
- data_avail <= 1'b0;
- read_data_pending <= read_data_pending ;
- pending_avail <= 1'b0;
- end
- // Start Data full, Pending full.
- // Out <= Data,
- // End Data full, Pending empty
- 2'b11: begin
- read_data <= read_data_pending;
- data_avail <= 1'b1;
- read_data_pending <= read_data_pending ;
- pending_avail <= 1'b0;
- end
- endcase
- end
- // Read externally, new data arriving from external FIFO
- 2'b11: begin
- case({data_avail,pending_avail})
- // Start Data empty, Pending empty.
- // *ILLEGAL STATE*
- 2'b00: begin
-
- end
- // Start Data empty, Pending full.
- // *ILLEGAL STATE*
- 2'b01: begin
-
- end
- // Start Data full, Pending empty.
- // Out <= Data, Data <= FIFO
- // End Data full, Pending empty.
- 2'b10: begin
- read_data <= data_in;
- data_avail <= 1'b1;
- read_data_pending <= read_data_pending ;
- pending_avail <= 1'b0;
- end
- // Start Data full, Pending full.
- // Out <= Data, Data <= Pending, Pending <= FIFO
- // End Data full, Pending full
- 2'b11: begin
- read_data <= read_data_pending;
- data_avail <= 1'b1;
- read_data_pending <= data_in ;
- pending_avail <= 1'b1;
- end
- endcase
- end
- endcase
- end
+ assign enable = write || read;
- // Start an external FIFO read as soon as a read of the buffer reg is strobed to minimise refill latency.
- // If the buffer reg or the pending buffer reg is already empty also pre-emptively start a read.
- // However there must be something in the main external FIFO to read for this to occur!.
- // Pay special attention to upstream devices signalling full due to the number of potential in-flight reads\ that need
- // to be stalled and stored somewhere.
- // This means that there can be 3 outstanding reads to the ext FIFO active at any time helping to hide latency.
- assign read_strobe_int = (read_strobe && data_avail && ~pending_avail && ~upstream_full) || (~data_avail && ~pending_avail && ~upstream_full);
-
//
// Simple NoBL SRAM interface, 4 cycle read latency.
@@ -265,10 +84,12 @@ module nobl_fifo
.RAM_CE1n(RAM_CE1n),
.address(address),
.data_out(write_data),
- .data_in(data_in),
- .data_in_valid(data_in_valid),
+ .data_in(read_data),
+ .data_in_valid(data_avail),
.write(write),
.enable(enable)
);
+
+
endmodule // nobl_fifo