From f9db9f4eed98a7538d73b5463e762441198526c1 Mon Sep 17 00:00:00 2001
From: Matt Ettus <matt@ettus.com>
Date: Wed, 14 Jul 2010 16:46:01 -0700
Subject: moved forward from the old branch

---
 usrp2/extramfifo/fifo_extram.v          | 188 +++++++++++++
 usrp2/extramfifo/fifo_extram36.v        |  47 ++++
 usrp2/extramfifo/fifo_extram36_tb.build |   1 +
 usrp2/extramfifo/fifo_extram36_tb.v     | 475 ++++++++++++++++++++++++++++++++
 usrp2/extramfifo/fifo_extram_tb.build   |   1 +
 usrp2/extramfifo/fifo_extram_tb.v       | 134 +++++++++
 usrp2/fifo/fifo18_to_fifo36.v           |  20 ++
 usrp2/fifo/fifo_2clock_cascade.v        |  14 +-
 8 files changed, 876 insertions(+), 4 deletions(-)
 create mode 100644 usrp2/extramfifo/fifo_extram.v
 create mode 100644 usrp2/extramfifo/fifo_extram36.v
 create mode 100644 usrp2/extramfifo/fifo_extram36_tb.build
 create mode 100644 usrp2/extramfifo/fifo_extram36_tb.v
 create mode 100644 usrp2/extramfifo/fifo_extram_tb.build
 create mode 100644 usrp2/extramfifo/fifo_extram_tb.v
 create mode 100644 usrp2/fifo/fifo18_to_fifo36.v

diff --git a/usrp2/extramfifo/fifo_extram.v b/usrp2/extramfifo/fifo_extram.v
new file mode 100644
index 000000000..4e1f40371
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram.v
@@ -0,0 +1,188 @@
+
+// Everything on sram_clk
+
+module fifo_extram
+  (input reset, input clear,
+   input [17:0] datain, input src_rdy_i, output dst_rdy_o, output [15:0] space, input [15:0] occ_in,
+   output [17:0] dataout, output src_rdy_o, input dst_rdy_i, output [15:0] occupied, input [15:0] space_in,
+   input sram_clk, output [18:0] sram_a, inout [17:0] sram_d, output sram_we,
+   output [1:0] sram_bw, output sram_adv, output sram_ce, output sram_oe, 
+   output sram_mode, output sram_zz);
+
+   localparam AWIDTH   = 19; // 1 MB in x18
+   localparam RAMSIZE  = ((1<<AWIDTH) - 1);
+
+   wire   do_store, do_retrieve;
+   reg [1:0]  do_store_del, do_retr_del;
+   
+   reg [AWIDTH-1:0] addr_retrieve, addr_store;
+   always @(posedge sram_clk)
+     if(reset | clear)
+       addr_retrieve <= 0;
+     else if (do_retrieve)
+       addr_retrieve <= addr_retrieve + 1;
+   
+   always @(posedge sram_clk)
+     if(reset | clear)
+       addr_store    <= 0;
+     else if(do_store)
+       addr_store    <= addr_store + 1;
+
+   //wire [AWIDTH-1:0] fullness = (addr_store - addr_retrieve);
+   reg [AWIDTH-1:0] fullness;
+   always @(posedge sram_clk)
+     if(reset | clear)
+       fullness      <= 0;
+     else if(do_store)
+       fullness      <= fullness + 1;
+     else if(do_retrieve)
+       fullness      <= fullness - 1;
+   
+   //   wire        empty  = (fullness == 0);
+   //wire        full   = (fullness == RAMSIZE); // 19'h7FF);
+   reg 		    empty, full;
+   
+   //  The math in the following functions is 'AWIDTH wide.  Use
+   //  continuous assignments to prevent the numbers from being
+   //  promoted to 32-bit (which would make it wrap wrong).
+   //
+   wire [AWIDTH-1:0] addr_retrieve_p1, addr_store_p2;
+   assign addr_retrieve_p1 = addr_retrieve + 1;
+   assign addr_store_p2 = addr_store + 2;
+
+   always @(posedge sram_clk)
+     if(reset | clear)
+       empty 	     <= 1;
+     else if(do_store)
+       empty 	     <= 0;
+     else if(do_retrieve & (/*(addr_retrieve + 1)*/ addr_retrieve_p1 == addr_store))
+       empty 	     <= 1;
+   
+   always @(posedge sram_clk)
+     if(reset | clear)
+       full 	     <= 0;
+     else if(do_retrieve)
+       full 	     <= 0;
+     else if(do_store & (/*(addr_store+2)*/ addr_store_p2 == addr_retrieve))
+       full <= 1;
+
+   reg 	       can_store;
+   always @*
+     if(full | ~src_rdy_i)
+       can_store 	  <= 0;
+     else if(do_store_del == 0)
+       can_store 	  <= 1;
+     else if((do_store_del == 1) || (do_store_del == 2))
+       can_store 	  <= (occ_in > 1);
+     else
+       can_store 	  <= (occ_in > 2);
+     
+   reg 	       can_retrieve;
+   always @*
+     if(empty | ~dst_rdy_i)
+       can_retrieve 	     <= 0;
+     else if(do_retr_del == 0)
+       can_retrieve 	     <= 1;
+     else if((do_retr_del == 1) || (do_retr_del == 2))
+       can_retrieve 	     <= (space_in > 1);
+     else
+       can_retrieve 	     <= (space_in > 2);
+   
+   reg [1:0]  state;
+   localparam IDLE_STORE_NEXT  = 0;
+   localparam STORE 	       = 1;
+   localparam IDLE_RETR_NEXT   = 2;
+   localparam RETRIEVE 	       = 3;
+   
+   reg [7:0]  countdown;
+   wire       countdown_done 		   = (countdown == 0);
+
+   localparam CYCLE_SIZE 		   = 6;
+   
+   assign        do_store 		   = can_store & (state == STORE);
+   assign        do_retrieve 		   = can_retrieve & (state == RETRIEVE);
+   always @(posedge sram_clk)
+     if(reset)
+       do_store_del 			  <= 0;
+     else
+       do_store_del 			  <= {do_store_del[0],do_store};
+   
+   always @(posedge sram_clk) 
+     if(reset)
+       do_retr_del <= 0;
+     else
+       do_retr_del <= {do_retr_del[0],do_retrieve};
+
+   always @(posedge sram_clk)
+     if(reset | clear)
+       begin
+	  state 			  <= IDLE_STORE_NEXT;
+	  countdown 			  <= 0;
+       end
+     else
+       case(state)
+	 IDLE_STORE_NEXT :
+	   if(can_store)
+	     begin
+		state 	  <= STORE;
+		countdown <= CYCLE_SIZE;
+	     end
+	   else if(can_retrieve)
+	     begin
+		state 	  <= RETRIEVE;
+		countdown <= CYCLE_SIZE;
+	     end
+	 STORE :
+	   if(~can_store | (can_retrieve & countdown_done))
+	     state <= IDLE_RETR_NEXT;
+	   else if(~countdown_done)
+	     countdown <= countdown - 1;
+	 IDLE_RETR_NEXT :
+	   if(can_retrieve)
+	     begin
+		state 	  <= RETRIEVE;
+		countdown <= CYCLE_SIZE;
+	     end
+	   else if(can_store)
+	     begin
+		state 	  <= STORE;
+		countdown <= CYCLE_SIZE;
+	     end
+	 RETRIEVE :
+	   if(~can_retrieve | (can_store & countdown_done))
+	     state <= IDLE_STORE_NEXT;
+	   else if(~countdown_done)
+	     countdown <= countdown - 1;
+       endcase // case (state)
+
+   // RAM wires
+   assign sram_bw      = 0;
+   assign sram_adv     = 0;
+   assign sram_mode    = 0;
+   assign sram_zz      = 0;
+   assign sram_ce      = 0;
+
+   assign sram_a       = (state==STORE) ? addr_store : addr_retrieve;
+   assign sram_we      = ~do_store;
+   assign sram_oe      = ~do_retr_del[1];
+   assign my_oe        = do_store_del[1] & sram_oe;
+   assign sram_d       = my_oe ? datain : 18'bz;
+   
+   // FIFO wires
+   assign dataout      = sram_d;
+   assign src_rdy_o    = do_retr_del[1];
+   assign dst_rdy_o    = do_store_del[1];
+   
+endmodule // fifo_extram
+
+
+   //wire        have_1 		   = (fullness == 1);
+   //wire        have_2 		   = (fullness == 2);
+   //wire        have_atleast_1 	   = ~empty;
+   //wire        have_atleast_2 	   = ~(empty | have_1);
+   //wire        have_atleast_3 	   = ~(empty | have_1 | have_2);   
+   //wire        full_minus_1 	   = (fullness == (RAMSIZE-1)); // 19'h7FE);
+   //wire        full_minus_2 	   = (fullness == (RAMSIZE-2)); // 19'h7FD);
+   //wire        spacefor_atleast_1  = ~full;
+   //wire        spacefor_atleast_2  = ~(full | full_minus_1);
+   //wire        spacefor_atleast_3  = ~(full | full_minus_1 | full_minus_2);
diff --git a/usrp2/extramfifo/fifo_extram36.v b/usrp2/extramfifo/fifo_extram36.v
new file mode 100644
index 000000000..29342fdc4
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram36.v
@@ -0,0 +1,47 @@
+
+// 18 bit interface means we either can't handle errors or can't handle odd lengths
+//   unless we go to heroic measures
+
+module fifo_extram36
+  (input clk, input reset, input clear,
+   input [35:0] datain, input src_rdy_i, output dst_rdy_o, output [15:0] space,
+   output [35:0] dataout, output src_rdy_o, input dst_rdy_i, output [15:0] occupied,
+   input sram_clk, output [18:0] sram_a, inout [17:0] sram_d, output sram_we,
+   output [1:0] sram_bw, output sram_adv, output sram_ce, output sram_oe, output sram_mode,
+   output sram_zz);
+
+   wire [17:0] f18_data_1, f18_data_2, f18_data_3, f18_data_4;
+   wire        f18_src_rdy_1, f18_dst_rdy_1, f18_src_rdy_2, f18_dst_rdy_2;
+   wire        f18_src_rdy_3, f18_dst_rdy_3, f18_src_rdy_4, f18_dst_rdy_4;
+   
+   fifo36_to_fifo18 f36_to_f18
+     (.clk(clk), .reset(reset), .clear(clear),
+      .f36_datain(datain), .f36_src_rdy_i(src_rdy_i), .f36_dst_rdy_o(dst_rdy_o),
+      .f18_dataout(f18_data_1), .f18_src_rdy_o(f18_src_rdy_1), .f18_dst_rdy_i(f18_dst_rdy_1) );
+
+   wire [15:0] f1_occ, f2_space;
+   
+   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) fifo_2clock_in
+     (.wclk(clk), .datain(f18_data_1), .src_rdy_i(f18_src_rdy_1), .dst_rdy_o(f18_dst_rdy_1), .space(),
+      .rclk(sram_clk), .dataout(f18_data_2), .src_rdy_o(f18_src_rdy_2), .dst_rdy_i(f18_dst_rdy_2), .short_occupied(f1_occ),
+      .arst(reset) );
+
+   fifo_extram fifo_extram
+     (.reset(reset), .clear(clear),
+      .datain(f18_data_2), .src_rdy_i(f18_src_rdy_2), .dst_rdy_o(f18_dst_rdy_2), .space(), .occ_in(f1_occ),
+      .dataout(f18_data_3), .src_rdy_o(f18_src_rdy_3), .dst_rdy_i(f18_dst_rdy_3), .occupied(), .space_in(f2_space),
+      .sram_clk(sram_clk), .sram_a(sram_a), .sram_d(sram_d), .sram_we(sram_we),
+      .sram_bw(sram_bw), .sram_adv(sram_adv), .sram_ce(sram_ce), .sram_oe(sram_oe),
+      .sram_mode(sram_mode), .sram_zz(sram_zz));
+   
+   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) fifo_2clock_out
+     (.wclk(sram_clk), .datain(f18_data_3), .src_rdy_i(f18_src_rdy_3), .dst_rdy_o(f18_dst_rdy_3), .short_space(f2_space),
+      .rclk(clk), .dataout(f18_data_4), .src_rdy_o(f18_src_rdy_4), .dst_rdy_i(f18_dst_rdy_4), .occupied(),
+      .arst(reset) );
+
+   fifo18_to_fifo36 f18_to_f36
+     (.clk(clk), .reset(reset), .clear(clear),
+      .f18_datain(f18_data_4), .f18_src_rdy_i(f18_src_rdy_4), .f18_dst_rdy_o(f18_dst_rdy_4),
+      .f36_dataout(dataout), .f36_src_rdy_o(src_rdy_o), .f36_dst_rdy_i(dst_rdy_i) );
+   
+endmodule // fifo_extram36
diff --git a/usrp2/extramfifo/fifo_extram36_tb.build b/usrp2/extramfifo/fifo_extram36_tb.build
new file mode 100644
index 000000000..699591889
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram36_tb.build
@@ -0,0 +1 @@
+iverilog -y ../../models -y ../../models/CY7C1356C -y . -y ../../control_lib/ -y ../../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -o fifo_extram36_tb fifo_extram36_tb.v
diff --git a/usrp2/extramfifo/fifo_extram36_tb.v b/usrp2/extramfifo/fifo_extram36_tb.v
new file mode 100644
index 000000000..f28c35e4f
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram36_tb.v
@@ -0,0 +1,475 @@
+`timescale 1ns/1ns
+
+module fifo_extram36_tb();
+   
+   reg clk 	 = 0;
+   reg sram_clk  = 0;
+   reg rst 	 = 1;
+   reg clear 	 = 0;
+
+   reg Verbose = 0;   // 
+   integer ErrorCount = 0;
+   
+   initial #1000 rst = 0;
+//   always #125 clk = ~clk;
+   task task_CLK;
+      reg [7:0] ran;
+      begin
+	 while (1) begin
+	    ran = $random;
+	    if (ran[1])
+	      #62 clk = ~clk;
+	    else
+	      #63 clk = !clk;
+	 end
+      end
+   endtask // task_CLK
+   initial task_CLK;
+   
+//   always #100 sram_clk = ~sram_clk;
+   task task_SSRAM_clk;
+      reg [7:0] ran;
+      begin
+	 while (1) begin
+	    ran = $random;
+	    if (ran[0])
+	      #49 sram_clk = ~sram_clk;
+	    else
+	      #51 sram_clk = ~sram_clk;
+	 end
+      end
+   endtask // task_SSRAM_clk
+   initial task_SSRAM_clk;
+
+   reg [31:0] f36_data = 32'hX;
+   reg [1:0]  f36_occ = 0;
+   reg 	      f36_sof = 0, f36_eof = 0;
+   
+   wire [35:0] f36_in = {1'b0,f36_occ,f36_eof,f36_sof,f36_data};
+   reg 	       src_rdy_f36i  = 0;
+   wire        dst_rdy_f36i;
+
+   wire [35:0] f36_out;
+   wire        src_rdy_f36o;
+   reg 	       dst_rdy_f36o  = 0;
+
+   wire [17:0] sram_d;
+   wire [18:0] sram_a;
+   wire [1:0]  sram_bw;
+   wire        sram_we, sram_adv, sram_ce, sram_oe, sram_mode, sram_zz;
+
+   reg [31:0]  ScoreBoard [524288:0];
+   reg [18:0] put_index = 0;
+   reg [18:0] get_index = 0;
+   
+//   integer     put_index = 0;
+//   integer     get_index = 0;
+   
+   wire [15:0] DUT_space, DUT_occupied;
+
+   fifo_extram36 fifo_extram36
+     (.clk(clk), .reset(rst), .clear(clear),
+      .datain(f36_in), .src_rdy_i(src_rdy_f36i), .dst_rdy_o(dst_rdy_f36i), .space(DUT_space),
+      .dataout(f36_out), .src_rdy_o(src_rdy_f36o), .dst_rdy_i(dst_rdy_f36o), .occupied(DUT_occupied),
+      .sram_clk(sram_clk), .sram_a(sram_a), .sram_d(sram_d), .sram_we(sram_we),
+      .sram_bw(sram_bw), .sram_adv(sram_adv), .sram_ce(sram_ce), .sram_oe(sram_oe),
+      .sram_mode(sram_mode), .sram_zz(sram_zz));
+
+`define idt 1
+`ifdef idt
+   wire [15:0] dummy16;
+   wire [1:0]  dummy2;
+   
+   idt71v65603s150 
+     ram_model(.A(sram_a[17:0]),
+	       .adv_ld_(sram_adv),                  // advance (high) / load (low)
+               .bw1_(0), .bw2_(0), .bw3_(0), .bw4_(0),   // byte write enables (low)
+               .ce1_(0), .ce2(1), .ce2_(0),          // chip enables
+               .cen_(sram_ce),                     // clock enable (low)
+	       .clk(sram_clk),                      // clock
+	       .IO({dummy16,sram_d[15:0]}), 
+	       .IOP({dummy2,sram_d[17:16]}),                  // data bus
+               .lbo_(sram_mode),                     // linear burst order (low)
+               .oe_(sram_oe),                      // output enable (low)
+               .r_w_(sram_we));                    // read (high) / write (low)
+`else 
+   cy1356 ram_model(.d(sram_d),.clk(~sram_clk),.a(sram_a),
+		    .bws(2'b00),.we_b(sram_we),.adv_lb(sram_adv),
+		    .ce1b(0),.ce2(1),.ce3b(0),
+		    .oeb(sram_oe),.cenb(sram_ce),.mode(sram_mode) );
+`endif
+
+   task task_SSRAMMonitor;
+      reg last_mode;
+      reg last_clock;
+      reg last_load;
+      reg [18:0] sram_addr;
+
+      begin
+	 last_mode = 1'bX;
+	 last_clock = 1'bX;
+	 last_load = 1'bX;
+
+	 @ (posedge Verbose);
+	 $dumpvars(0,fifo_extram36_tb);
+	 
+	 $display("%t:%m\t*** Task Started",$time);
+	 while (1) @ (posedge sram_clk) begin
+	    if (sram_mode !== last_mode) begin
+	       $display("%t:%m\tSSRAM mode:         %b",$time,sram_mode);
+	       last_mode = sram_mode;
+	    end
+	    if (sram_adv !== last_load) begin
+	       $display("%t:%m\tSSRAM adv/load:     %b",$time,sram_adv);
+	       last_load = sram_adv;
+	    end
+	    if (sram_ce !== last_clock) begin
+	       $display("%t:%m\tSSRAM clock enable: %b",$time,sram_ce);
+	       last_clock = sram_ce;
+	    end
+	    if (sram_ce == 1'b0) begin
+	       if (sram_adv == 1'b0) begin
+//		  $display("%t:%m\tSSRAM Address Load A=%h",$time,sram_a);
+		  sram_addr = sram_a;
+	       end else begin
+		  sram_addr = sram_addr + 1;
+	       end
+	       if (sram_oe == 1'b0) begin
+		  $display("%t:%m\tSSRAM Read  Cycle A=%h(%h), D=%o",$time,sram_addr-2,sram_a,sram_d);
+	       end
+	       if (sram_we == 1'b0) begin
+		  $display("%t:%m\tSSRAM Write Cycle A=%h(%h), D=%o",$time,sram_addr-2,sram_a,sram_d);
+	       end
+	       if ((sram_we == 1'b0) && (sram_oe == 1'b0)) begin
+		 $display("%t:%m\t*** ERROR: _oe and _we both active",$time);
+	       end
+	       
+	    end // if (sram_ce == 1'b0)
+	    
+	 end // always @ (posedge sram_clk)
+      end
+   endtask // task_SSRAMMonitor
+   
+   task ReadFromFIFO36;
+      begin
+	 $display("%t: Read from FIFO36",$time);
+	 #1 dst_rdy_f36o <= 1;
+	 while(1)
+	   begin
+	      while(~src_rdy_f36o)
+		@(posedge clk);
+	      $display("%t: Read: %h>",$time,f36_out);
+	      @(posedge clk);
+	   end
+      end
+   endtask // ReadFromFIFO36
+
+   initial dst_rdy_f36o = 0;
+
+   task task_ReadFIFO36;
+      reg [7:0] ran;
+      begin
+      $display("%t:%m\t*** Task Started",$time);
+      while (1) begin
+	 //  Read on one of four clocks
+	 #5 dst_rdy_f36o <= 1;
+	 @(posedge clk);
+	 if (src_rdy_f36o) begin
+	    if (f36_out[31:0] != ScoreBoard[get_index]) begin
+	       $display("%t:%m\tFIFO Get Error: R:%h, E:%h (%h)",$time,f36_out[31:0],ScoreBoard[get_index],get_index);
+	       ErrorCount = ErrorCount + 1;
+	    end else begin
+	       if (Verbose)
+		 $display("%t:%m\t(%5h) %o>",$time,get_index,f36_out);
+	    end
+	    get_index = get_index+1;
+	 end else begin
+	    if (ErrorCount >= 192)
+	      $finish;
+	 end // else: !if(src_rdy_f36o)
+	 
+	 #10;
+	 ran = $random;
+	 if (ran[2:0] != 3'b000) begin
+	    dst_rdy_f36o <= 0;
+	    if (ran[2] != 1'b0) begin
+	       @(posedge clk);
+	       @(posedge clk);
+	       @(posedge clk);
+	    end
+	    if (ran[1] != 1'b0) begin
+	       @(posedge clk);
+	       @(posedge clk);
+	    end
+	    if (ran[0] != 1'b0) begin
+	       @(posedge clk);
+	    end
+	 end
+      end // while (1)
+   end
+      
+   endtask // task_ReadFIFO36
+   
+
+   reg [15:0] count;
+   
+   task PutPacketInFIFO36;
+      input [31:0] data_start;
+      input [31:0] data_len;
+
+      begin
+	 count 	      = 4;
+	 src_rdy_f36i = 1;
+	 f36_data     = data_start;
+	 f36_sof      = 1;
+	 f36_eof      = 0;
+	 f36_occ      = 0;
+	
+	 $display("%t: Put Packet in FIFO36",$time);
+	 while(~dst_rdy_f36i)
+	   #1; //@(posedge clk);
+	 @(posedge clk);
+
+	 $display("%t: <%h PPI_FIFO36: Entered First Line",$time,f36_data);
+	 f36_sof <= 0;
+	 while(count+4 < data_len)
+	   begin
+	      f36_data = f36_data + 32'h01010101;
+	      count    = count + 4;
+	      while(~dst_rdy_f36i)
+		#1; //@(posedge clk);
+	      @(posedge clk);
+	      $display("%t: <%h PPI_FIFO36: Entered New Line",$time,f36_data);
+	   end
+	 f36_data  <= f36_data + 32'h01010101;
+	 f36_eof   <= 1;
+	 if(count + 4 == data_len)
+	   f36_occ <= 0;
+	 else if(count + 3 == data_len)
+	   f36_occ <= 3;
+	 else if(count + 2 == data_len)
+	   f36_occ <= 2;
+	 else
+	   f36_occ <= 1;
+	 while(~dst_rdy_f36i)
+	   @(posedge clk);
+	 @(posedge clk);
+	 f36_occ      <= 0;
+	 f36_eof      <= 0;
+	 f36_data     <= 0;
+	 src_rdy_f36i <= 0;
+	 $display("%t: <%h PPI_FIFO36: Entered Last Line",$time,f36_data);
+      end
+   endtask // PutPacketInFIFO36
+
+   task task_WriteFIFO36;
+      integer i;
+      reg [7:0] ran;
+      
+      begin
+	 f36_data = 32'bX;
+	 if (rst != 1'b0)
+	   @ (negedge rst);
+	 $display("%t:%m\t*** Task Started",$time);
+	 #10;
+	 src_rdy_f36i = 1;
+	 f36_data = $random;
+	 for (i=0; i<64; i=i+0 ) begin
+	    @ (posedge clk) ;
+	    if (dst_rdy_f36i) begin
+	       if (Verbose)
+		 $display("%t:%m\t(%5h) %o<",$time,put_index,f36_in);
+	       ScoreBoard[put_index] = f36_in[31:0];
+	       put_index = put_index + 1;
+	       #5;
+	       f36_data = $random;
+	       i = i + 1;
+	    end
+	    ran = $random;
+	    if (ran[1:0] != 2'b00) begin
+	       @ (negedge clk);
+	       src_rdy_f36i = 0;
+	       #5;
+	       @ (negedge clk) ;
+	       src_rdy_f36i = 1;
+	    end
+	 end
+	 src_rdy_f36i = 0;
+	 f36_data = 32'bX;
+//*	 if (put_index > 19'h3ff00)
+//*	   Verbose = 1'b1;
+	 
+      end
+   endtask // task_WriteFIFO36
+   
+   initial $dumpfile("fifo_extram36_tb.vcd");
+//   initial $dumpvars(0,fifo_extram36_tb);
+   initial $timeformat(-9, 0, " ns", 10);
+   initial task_SSRAMMonitor;
+   
+   initial
+     begin
+	@(negedge rst);
+	#40000;
+	@(posedge clk);
+	@(posedge clk);
+	@(posedge clk);
+	@(posedge clk);
+//	ReadFromFIFO36;
+	task_ReadFIFO36;
+	
+     end
+
+   integer i;
+   
+   initial
+     begin
+	@(negedge rst);
+	@(posedge clk);
+	@(posedge clk);
+	@(posedge clk);
+	task_WriteFIFO36;
+	@(posedge clk);
+	@(posedge clk);
+	@(posedge clk);
+//	PutPacketInFIFO36(32'hA0B0C0D0,12);
+	@(posedge clk);
+	@(posedge clk);
+	#10000;
+	@(posedge clk);
+//	PutPacketInFIFO36(32'hE0F0A0B0,36);
+	@(posedge clk);
+	@(posedge clk);
+	task_WriteFIFO36;
+	@(posedge clk);
+	@(posedge clk);
+	#10000;
+	@(posedge clk);
+	@(posedge clk);
+	task_WriteFIFO36;
+//	@(posedge clk);
+//	#30000;
+//	@(posedge clk);
+//	@(posedge clk);
+	task_WriteFIFO36;
+//	@(posedge clk);
+//	#30000;
+//	@(posedge clk);
+//	@(posedge clk);
+	task_WriteFIFO36;
+//	@(posedge clk);
+//	#30000;
+//	@(posedge clk);
+//	@(posedge clk);
+	task_WriteFIFO36;
+	@(posedge clk);
+	#10000;
+	@(posedge clk);
+	@(posedge clk);
+	task_WriteFIFO36;
+	for (i=0; i<8192; i = i+1) begin
+	   @(posedge clk);
+	   #10000;
+	   @(posedge clk);
+	   @(posedge clk);
+	   task_WriteFIFO36;
+	   @(posedge clk);
+	end
+
+//	$dumpvars(0,fifo_extram36_tb);
+	@(posedge clk);
+	task_WriteFIFO36;
+	@(posedge clk);
+
+	#100000000;
+	$finish;
+	
+     end
+  */
+
+   initial
+     begin
+	@(negedge rst);
+	f36_occ      <= 0;
+	repeat (100)
+	  @(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= 32'h10203040;
+	f36_sof      <= 1;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= f36_data + 32'h01010101;
+	f36_sof      <= 0;
+	f36_eof      <= 0;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 1;
+	f36_data     <= 32'h1F2F3F4F;
+	f36_sof      <= 0;
+	f36_eof      <= 1;
+	@(posedge clk);
+	@(posedge clk);
+	src_rdy_f36i <= 0;
+	
+	
+	
+     end
+   
+//   initial #500000 $finish;
+endmodule // fifo_extram_tb
diff --git a/usrp2/extramfifo/fifo_extram_tb.build b/usrp2/extramfifo/fifo_extram_tb.build
new file mode 100644
index 000000000..e87217e5c
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram_tb.build
@@ -0,0 +1 @@
+iverilog -y ../../models -y ../../models/CY7C1356C -y . -y ../../control_lib/ -y ../../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -o fifo_extram_tb fifo_extram_tb.v
diff --git a/usrp2/extramfifo/fifo_extram_tb.v b/usrp2/extramfifo/fifo_extram_tb.v
new file mode 100644
index 000000000..73550d9ca
--- /dev/null
+++ b/usrp2/extramfifo/fifo_extram_tb.v
@@ -0,0 +1,134 @@
+module fifo_extram_tb();
+   
+   reg clk 	 = 0;
+   reg sram_clk  = 0;
+   reg reset 	 = 1;
+   reg clear 	 = 0;
+   
+   initial #1000 reset = 0;
+   always #125 clk = ~clk;
+   always #100 sram_clk = ~sram_clk;
+   
+   reg [15:0] f18_data = 0;
+   reg f18_sof = 0, f18_eof = 0;
+   
+   wire [17:0] f18_in = {f18_eof,f18_sof,f18_data};
+   reg src_rdy_f18i  = 0;
+   wire dst_rdy_f18i;
+
+   wire [17:0] f18_out;
+   wire src_rdy_f18o;
+   reg dst_rdy_f18o  = 0;
+
+   wire [17:0] f18_int;
+   wire        src_rdy_f18int, dst_rdy_f18int;
+       
+   wire [17:0] sram_d;
+   wire [18:0] sram_a;
+   wire [1:0]  sram_bw;
+   wire        sram_we, sram_adv, sram_ce, sram_oe, sram_mode, sram_zz;
+   wire [15:0] f1_occ;
+   
+   fifo_short #(.WIDTH(18)) fifo_short
+     (.clk(sram_clk), .reset(reset), .clear(clear),
+      .datain(f18_in), .src_rdy_i(src_rdy_f18i), .dst_rdy_o(dst_rdy_f18i), .space(),
+      .dataout(f18_int), .src_rdy_o(src_rdy_f18int), .dst_rdy_i(dst_rdy_f18int), .occupied(f1_occ[4:0]) );
+   
+   assign f1_occ[15:5] = 0;
+   
+   fifo_extram fifo_extram
+     (.reset(reset), .clear(clear),
+      .datain(f18_int), .src_rdy_i(src_rdy_f18int), .dst_rdy_o(dst_rdy_f18int), .space(), .occ_in(f1_occ),
+      .dataout(f18_out), .src_rdy_o(src_rdy_f18o), .dst_rdy_i(dst_rdy_f18o), .occupied(), .space_in(7),
+      .sram_clk(sram_clk), .sram_a(sram_a), .sram_d(sram_d), .sram_we(sram_we),
+      .sram_bw(sram_bw), .sram_adv(sram_adv), .sram_ce(sram_ce), .sram_oe(sram_oe),
+      .sram_mode(sram_mode), .sram_zz(sram_zz));
+
+`define idt 1
+`ifdef idt
+   wire [15:0]  dummy16;
+   wire [1:0] 	dummy2;
+   
+   idt71v65603s150 
+     ram_model(.A(sram_a[17:0]),
+	       .adv_ld_(sram_adv),                  // advance (high) / load (low)
+               .bw1_(0), .bw2_(0), .bw3_(0), .bw4_(0),   // byte write enables (low)
+               .ce1_(0), .ce2(1), .ce2_(0),          // chip enables
+               .cen_(sram_ce),                     // clock enable (low)
+	       .clk(sram_clk),                      // clock
+	       .IO({dummy16,sram_d[15:0]}), 
+	       .IOP({dummy2,sram_d[17:16]}),                  // data bus
+               .lbo_(sram_mode),                     // linear burst order (low)
+               .oe_(sram_oe),                      // output enable (low)
+               .r_w_(sram_we));                    // read (high) / write (low)
+`else
+   cy1356 ram_model(.d(sram_d),.clk(sram_clk),.a(sram_a),
+		    .bws(2'b00),.we_b(sram_we),.adv_lb(sram_adv),
+		    .ce1b(0),.ce2(1),.ce3b(0),
+		    .oeb(sram_oe),.cenb(sram_ce),.mode(sram_mode) );
+`endif // !`ifdef idt
+   
+   always @(posedge sram_clk)
+     if(dst_rdy_f18o & src_rdy_f18o)
+       $display("Read: %h",f18_out);
+
+   always @(posedge sram_clk)
+     if(dst_rdy_f18int & src_rdy_f18int)
+       $display("Write: %h",f18_int);
+
+   initial $dumpfile("fifo_extram_tb.vcd");
+   initial $dumpvars(0,fifo_extram_tb);
+
+   task SendPkt;
+      input [15:0] data_start;
+      input [31:0] data_len;
+      begin
+	 @(posedge sram_clk);
+	 f18_data      = data_start;
+	 f18_sof       = 1;
+	 f18_eof       = 0;
+	 src_rdy_f18i  = 1;
+	 while(~dst_rdy_f18i)
+	   #1;
+	 @(posedge sram_clk);
+	 repeat(data_len - 2)
+	   begin
+	      f18_data 	= f18_data + 16'h0101;
+	      f18_sof 	= 0;
+	      while(~dst_rdy_f18i)
+		@(posedge sram_clk);
+
+	      @(posedge sram_clk);
+	   end
+	 f18_data 	= f18_data + 16'h0101;
+	 f18_eof 	= 1;
+	 while(~dst_rdy_f18i)
+	   #1;
+	 @(posedge sram_clk);
+	 src_rdy_f18i = 0;
+	 f18_data  = 0;
+	 f18_eof   = 0;
+      end
+   endtask // SendPkt
+   
+   initial
+     begin
+	@(negedge reset);
+	@(posedge sram_clk);
+	@(posedge sram_clk);
+	#10000;
+	@(posedge sram_clk);
+	SendPkt(16'hA0B0, 100);
+	#10000;
+	//SendPkt(16'hC0D0, 220);
+     end
+
+   initial
+     begin
+	#20000;
+	dst_rdy_f18o  = 1;
+     end
+   
+   initial #200000 $finish;
+endmodule // fifo_extram_tb
+
diff --git a/usrp2/fifo/fifo18_to_fifo36.v b/usrp2/fifo/fifo18_to_fifo36.v
new file mode 100644
index 000000000..25bb215a1
--- /dev/null
+++ b/usrp2/fifo/fifo18_to_fifo36.v
@@ -0,0 +1,20 @@
+
+// For now just assume FIFO18 is same as FIFO19 without occupancy bit
+
+module fifo18_to_fifo36
+  (input clk, input reset, input clear,
+   input [17:0] f18_datain,
+   input f18_src_rdy_i,
+   output f18_dst_rdy_o,
+
+   output [35:0] f36_dataout,
+   output f36_src_rdy_o,
+   input f36_dst_rdy_i
+   );
+
+   fifo19_to_fifo36 fifo19_to_fifo36
+     (.clk(clk), .reset(reset), .clear(clear),
+      .f19_datain({1'b0,f18_datain}), .f19_src_rdy_i(f18_src_rdy_i), .f19_dst_rdy_o(f18_dst_rdy_o),
+      .f36_dataout(f36_dataout), .f36_src_rdy_o(f36_src_rdy_o), .f36_dst_rdy_i(f36_dst_rdy_i) );
+
+endmodule // fifo18_to_fifo36
diff --git a/usrp2/fifo/fifo_2clock_cascade.v b/usrp2/fifo/fifo_2clock_cascade.v
index 5ce726977..4e8c244c2 100644
--- a/usrp2/fifo/fifo_2clock_cascade.v
+++ b/usrp2/fifo/fifo_2clock_cascade.v
@@ -1,8 +1,10 @@
 
 module fifo_2clock_cascade
   #(parameter WIDTH=32, SIZE=9)
-   (input wclk, input [WIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output [15:0] space,
-    input rclk, output [WIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output [15:0] occupied,
+   (input wclk, input [WIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, 
+    output [15:0] space, output [15:0] short_space,
+    input rclk, output [WIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, 
+    output [15:0] occupied, output [15:0] short_occupied,
     input arst);
    
    wire [WIDTH-1:0] data_int1, data_int2;
@@ -29,7 +31,11 @@ module fifo_2clock_cascade
       .space(s2_space), .occupied(s2_occupied));
 
    // Be conservative -- Only advertise space from input side of fifo, occupied from output side
-   assign 	    space = {11'b0,s1_space} + l_space;
-   assign 	    occupied = {11'b0,s2_occupied} + l_occupied;
+   assign 	    space 	    = {11'b0,s1_space} + l_space;
+   assign 	    occupied 	    = {11'b0,s2_occupied} + l_occupied;
+
+   // For the fifo_extram, we only want to know the immediately adjacent space
+   assign 	    short_space     = {11'b0,s1_space};
+   assign 	    short_occupied  = {11'b0,s2_occupied};
    
 endmodule // fifo_2clock_cascade
-- 
cgit v1.2.3