From d4b6fa72eb3fec872a41dea136a5845d3c6ff1ec Mon Sep 17 00:00:00 2001
From: Ian Buckley <ianb@server2.(none)>
Date: Thu, 19 Aug 2010 12:46:04 -0700
Subject: Regenerated FIFO with lower trigger level for almost full flag to
 reflect logic removed from nobl_fifo.

Improved ext_fifo_tb further, try to simulate more combinations of decomation rates and packet arrival patterns.

Strip out the logic in nobl_fifo that made it look like a Xilinx fall-through FIFO...it is now very simple logic but a propriatory interface that exposes the high inetrnal latency of reads.

Allow the USED size of the external FIFO to be parameterized from the core level. Currently set at only 256

Corrected a bug in vita_tx_deframer.v that can write to a FIFO when its full causing illegal state.
Made further edits that are currently commented becuase simulation indicates they cause problems, however suspect a further bug is in this code.
---
 usrp2/extramfifo/ext_fifo.v    |  29 +++---
 usrp2/extramfifo/ext_fifo_tb.v |  70 +++++++++++--
 usrp2/extramfifo/nobl_fifo.v   | 229 +++++------------------------------------
 3 files changed, 102 insertions(+), 226 deletions(-)

(limited to 'usrp2/extramfifo')

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
-- 
cgit v1.2.3