aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/extramfifo
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-10-22 16:13:35 -0700
committerJosh Blum <josh@joshknows.com>2010-10-22 16:13:35 -0700
commitbd06eede24df80940ae93515a71e214c1feb87b8 (patch)
tree628e79254fb670e468ab7a3ff06eb74ab0367055 /fpga/usrp2/extramfifo
parent2ce71ded9dada93ade6f960aac0bd4c25e47456a (diff)
parentf14e7eb89b09e6fc4b1619c9ec255ebad3fa2aed (diff)
downloaduhd-bd06eede24df80940ae93515a71e214c1feb87b8.tar.gz
uhd-bd06eede24df80940ae93515a71e214c1feb87b8.tar.bz2
uhd-bd06eede24df80940ae93515a71e214c1feb87b8.zip
Merge branch 'flow_control_fpga' into flow_ctrl
Diffstat (limited to 'fpga/usrp2/extramfifo')
-rw-r--r--fpga/usrp2/extramfifo/Makefile.srcs1
-rw-r--r--fpga/usrp2/extramfifo/ext_fifo.v125
-rw-r--r--fpga/usrp2/extramfifo/ext_fifo_tb.sav30
-rw-r--r--fpga/usrp2/extramfifo/ext_fifo_tb.v103
-rw-r--r--fpga/usrp2/extramfifo/nobl_if.v8
-rw-r--r--fpga/usrp2/extramfifo/refill_randomizer.v66
6 files changed, 261 insertions, 72 deletions
diff --git a/fpga/usrp2/extramfifo/Makefile.srcs b/fpga/usrp2/extramfifo/Makefile.srcs
index 7cd49f4f6..b255ef916 100644
--- a/fpga/usrp2/extramfifo/Makefile.srcs
+++ b/fpga/usrp2/extramfifo/Makefile.srcs
@@ -13,4 +13,5 @@ icon.v \
icon.xco \
ila.v \
ila.xco \
+refill_randomizer.v \
))
diff --git a/fpga/usrp2/extramfifo/ext_fifo.v b/fpga/usrp2/extramfifo/ext_fifo.v
index 2af59a75d..6888617a7 100644
--- a/fpga/usrp2/extramfifo/ext_fifo.v
+++ b/fpga/usrp2/extramfifo/ext_fifo.v
@@ -18,7 +18,7 @@
//`define NO_EXT_FIFO
module ext_fifo
- #(parameter INT_WIDTH=36,EXT_WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
+ #(parameter INT_WIDTH=36,EXT_WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
(
input int_clk,
input ext_clk,
@@ -44,34 +44,29 @@ module ext_fifo
wire [EXT_WIDTH-1:0] write_data;
wire [EXT_WIDTH-1:0] read_data;
- wire full1, empty1;
- wire almost_full2, full2, empty2;
+ wire full1, empty1;
+ wire almost_full2, full2, empty2;
wire [INT_WIDTH-1:0] data_to_fifo;
wire [INT_WIDTH-1:0] data_from_fifo;
wire [FIFO_DEPTH-1:0] capacity;
-
+ wire space_avail;
+ wire data_avail;
+
+ // These next 2 lines here purely because ICARUS is crap at handling generate statements.
+ // Empirically this has been determined to make simulations work.
+ wire read_input_fifo = space_avail & ~empty1;
+ wire write_output_fifo = data_avail;
- // FIFO buffers data from UDP engine into external FIFO clock domain.
- fifo_xlnx_512x36_2clk_36to18 fifo_xlnx_512x36_2clk_36to18_i1 (
- .rst(rst),
- .wr_clk(int_clk),
- .rd_clk(ext_clk),
- .din(datain), // Bus [35 : 0]
- .wr_en(src_rdy_i),
- .rd_en(space_avail&~empty1),
- .dout(write_data), // Bus [17 : 0]
- .full(full1),
- .empty(empty1));
-
- assign dst_rdy_o = ~full1;
+ assign src_rdy_o = ~empty2;
+ assign dst_rdy_o = ~full1;
`ifdef NO_EXT_FIFO
- assign space_avail = ~full2;
- assign data_avail = ~empty1;
- assign read_data = write_data;
+ assign space_avail = ~full2;
+ assign data_avail = ~empty1;
+ assign read_data = write_data;
`else
- // External FIFO running at ext clock rate and 18 bit width.
+ // External FIFO running at ext clock rate and 18 or 36 bit width.
nobl_fifo #(.WIDTH(EXT_WIDTH),.RAM_DEPTH(RAM_DEPTH),.FIFO_DEPTH(FIFO_DEPTH))
nobl_fifo_i1
(
@@ -90,27 +85,80 @@ module ext_fifo
.write_strobe(~empty1 ),
.space_avail(space_avail),
.read_data(read_data),
- .read_strobe(~almost_full2),
+ .read_strobe(~almost_full2_spread),
.data_avail(data_avail),
.capacity(capacity)
);
`endif // !`ifdef NO_EXT_FIFO
+
+
+ generate
+ if (EXT_WIDTH == 18 && INT_WIDTH == 36) begin: fifo_g1
+ // FIFO buffers data from UDP engine into external FIFO clock domain.
+ fifo_xlnx_512x36_2clk_36to18 fifo_xlnx_512x36_2clk_36to18_i1 (
+ .rst(rst),
+ .wr_clk(int_clk),
+ .rd_clk(ext_clk),
+ .din(datain), // Bus [35 : 0]
+ .wr_en(src_rdy_i),
+ .rd_en(read_input_fifo),
+ .dout(write_data), // Bus [17 : 0]
+ .full(full1),
+ .empty(empty1));
+
+
+ // 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 (
+ .rst(rst),
+ .wr_clk(ext_clk),
+ .rd_clk(int_clk),
+ .din(read_data), // Bus [17 : 0]
+ .wr_en(write_output_fifo),
+ .rd_en(dst_rdy_i),
+ .dout(dataout), // Bus [35 : 0]
+ .full(full2),
+ .prog_full(almost_full2),
+ .empty(empty2));
+ end // block: fifo_g1
+ else if (EXT_WIDTH == 36 && INT_WIDTH == 36) begin: fifo_g1
+ // FIFO buffers data from UDP engine into external FIFO clock domain.
+ fifo_xlnx_32x36_2clk fifo_xlnx_32x36_2clk_i1 (
+ .rst(rst),
+ .wr_clk(int_clk),
+ .rd_clk(ext_clk),
+ .din(datain), // Bus [35 : 0]
+ .wr_en(src_rdy_i),
+ .rd_en(read_input_fifo),
+ .dout(write_data), // Bus [35 : 0]
+ .full(full1),
+ .empty(empty1));
+
+ // FIFO buffers data read from external FIFO into DSP clk domain and to TX DSP.
+ fifo_xlnx_32x36_2clk fifo_xlnx_32x36_2clk_i2 (
+ .rst(rst),
+ .wr_clk(ext_clk),
+ .rd_clk(int_clk),
+ .din(read_data), // Bus [35 : 0]
+ .wr_en(write_output_fifo),
+ .rd_en(dst_rdy_i),
+ .dout(dataout), // Bus [35 : 0]
+ .full(full2),
+ .empty(empty2),
+ .prog_full(almost_full2));
+
+ end
+ endgenerate
-
- // 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 (
- .rst(rst),
- .wr_clk(ext_clk),
- .rd_clk(int_clk),
- .din(read_data), // Bus [17 : 0]
- .wr_en(data_avail),
- .rd_en(dst_rdy_i),
- .dout(dataout), // Bus [35 : 0]
- .full(full2),
- .prog_full(almost_full2),
- .empty(empty2));
- assign src_rdy_o = ~empty2;
+ refill_randomizer #(.BITS(7))
+ refill_randomizer_i1 (
+ .clk(ext_clk),
+ .rst(rst),
+ .full_in(almost_full2),
+ .full_out(almost_full2_spread)
+ );
+
+
always @ (posedge int_clk)
debug[31:28] <= {empty2,full1,dst_rdy_i,src_rdy_i };
@@ -118,6 +166,7 @@ module ext_fifo
debug[27:0] <= {RAM_WEn,RAM_CE1n,RAM_A[3:0],read_data[17:0],empty1,space_avail,data_avail,almost_full2 };
always@ (posedge ext_clk)
-// debug2[31:0] <= {write_data[15:0],read_data[15:0]};
- debug2[31:0] <= 0;
+ // debug2[31:0] <= {write_data[15:0],read_data[15:0]};
+ debug2[31:0] <= 0;
+
endmodule // ext_fifo
diff --git a/fpga/usrp2/extramfifo/ext_fifo_tb.sav b/fpga/usrp2/extramfifo/ext_fifo_tb.sav
new file mode 100644
index 000000000..a54b40fc5
--- /dev/null
+++ b/fpga/usrp2/extramfifo/ext_fifo_tb.sav
@@ -0,0 +1,30 @@
+[timestart] 0
+[size] 1523 832
+[pos] -1 -1
+*-15.000000 66300 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] ext_fifo_tb.
+[treeopen] ext_fifo_tb.ext_fifo_i1.
+[treeopen] ext_fifo_tb.ext_fifo_i1.nobl_fifo_i1.
+@28
+ext_fifo_tb.ext_fifo_i1.src_rdy_i
+ext_fifo_tb.ext_fifo_i1.dst_rdy_o
+@22
+ext_fifo_tb.ext_fifo_i1.datain[35:0]
+@28
+ext_fifo_tb.ext_fifo_i1.src_rdy_o
+ext_fifo_tb.ext_fifo_i1.dst_rdy_i
+@22
+ext_fifo_tb.ext_fifo_i1.dataout[35:0]
+ext_fifo_tb.ext_fifo_i1.RAM_A[17:0]
+@28
+ext_fifo_tb.ext_fifo_i1.RAM_WEn
+ext_fifo_tb.ext_fifo_i1.RAM_CE1n
+@22
+ext_fifo_tb.ext_fifo_i1.RAM_D_pi[35:0]
+ext_fifo_tb.ext_fifo_i1.RAM_D_po[35:0]
+ext_fifo_tb.ext_fifo_i1.write_data[35:0]
+@28
+ext_fifo_tb.ext_fifo_i1.full1
+ext_fifo_tb.ext_fifo_i1.empty1
+@29
+ext_fifo_tb.ext_fifo_i1.space_avail
diff --git a/fpga/usrp2/extramfifo/ext_fifo_tb.v b/fpga/usrp2/extramfifo/ext_fifo_tb.v
index 0eda89769..395ad2884 100644
--- a/fpga/usrp2/extramfifo/ext_fifo_tb.v
+++ b/fpga/usrp2/extramfifo/ext_fifo_tb.v
@@ -1,18 +1,31 @@
`timescale 1ns / 1ps
-`define INT_WIDTH 36
-`define EXT_WIDTH 18
-`define RAM_DEPTH 19
-`define FIFO_DEPTH 8
-`define DUMP_VCD_FULL
-
-module ext_fifo_tb();
+`define USRP2
+//`define USRP2PLUS
+`ifdef USRP2
+ `define INT_WIDTH 36
+ `define EXT_WIDTH 18
+ `define RAM_DEPTH 19
+ `define FIFO_DEPTH 8
+ `define DUMP_VCD_FULL
+ `define INT_CLK_PERIOD 5
+ `define EXT_CLK_PERIOD 4
+`elsif USRP2PLUS
+ `define INT_WIDTH 36
+ `define EXT_WIDTH 36
+ `define RAM_DEPTH 18
+ `define FIFO_DEPTH 8
+ `define DUMP_VCD_FULL
+ `define INT_CLK_PERIOD 5
+ `define EXT_CLK_PERIOD 5
+`endif // `ifdef USRP2
+
+module ext_fifo_tb();
+
reg int_clk;
reg ext_clk;
reg rst;
-
-
wire [`EXT_WIDTH-1:0] RAM_D_pi;
wire [`EXT_WIDTH-1:0] RAM_D_po;
@@ -33,7 +46,6 @@ module ext_fifo_tb();
reg dst_rdy_i;
integer ether_frame;
-
// Clocks
// Int clock is 100MHz
// Ext clock is 125MHz
@@ -47,10 +59,10 @@ module ext_fifo_tb();
end
always
- #5 int_clk <= ~int_clk;
+ #(`INT_CLK_PERIOD/2) int_clk <= ~int_clk;
always
- #4 ext_clk <= ~ext_clk;
+ #(`EXT_CLK_PERIOD/2) ext_clk <= ~ext_clk;
initial
begin
@@ -270,7 +282,7 @@ module ext_fifo_tb();
//
generate
- for (i=0;i<18;i=i+1)
+ for (i=0;i<`EXT_WIDTH;i=i+1)
begin : gen_RAM_D_IO
IOBUF #(
@@ -309,28 +321,53 @@ module ext_fifo_tb();
assign #2 RAM_A_ext = RAM_A;
-
- idt71v65603s150 idt71v65603s150_i1
- (
- .A(RAM_A_ext[17:0]),
- .adv_ld_(RAM_LDn_ext), // advance (high) / load (low)
- .bw1_(1'b0),
- .bw2_(1'b0),
- .bw3_(1'b1),
- .bw4_(1'b1), // byte write enables (low)
- .ce1_(RAM_CE1n_ext),
- .ce2(1'b1),
- .ce2_(1'b0), // chip enables
- .cen_(RAM_CENn_ext), // clock enable (low)
- .clk(ext_clk), // clock
- .IO({RAM_D[16:9],RAM_D[7:0]}),
- .IOP({RAM_D[17],RAM_D[8]}), // data bus
- .lbo_(1'b0), // linear burst order (low)
- .oe_(RAM_OEn_ext), // output enable (low)
- .r_w_(RAM_WEn_ext)
- ); // read (high) / write (low)
+ generate
+ if (`EXT_WIDTH==18) begin: ram_tb_g1
+ idt71v65603s150 idt71v65603s150_i1
+ (
+ .A(RAM_A_ext[17:0]),
+ .adv_ld_(RAM_LDn_ext), // advance (high) / load (low)
+ .bw1_(1'b0),
+ .bw2_(1'b0),
+ .bw3_(1'b1),
+ .bw4_(1'b1), // byte write enables (low)
+ .ce1_(RAM_CE1n_ext),
+ .ce2(1'b1),
+ .ce2_(1'b0), // chip enables
+ .cen_(RAM_CENn_ext), // clock enable (low)
+ .clk(ext_clk), // clock
+ .IO({RAM_D[16:9],RAM_D[7:0]}),
+ .IOP({RAM_D[17],RAM_D[8]}), // data bus
+ .lbo_(1'b0), // linear burst order (low)
+ .oe_(RAM_OEn_ext), // output enable (low)
+ .r_w_(RAM_WEn_ext)
+ ); // read (high) / write (low)
+ end // block: ram_tb_g1
+ else if (`EXT_WIDTH==36) begin: ram_tb_g1
+ idt71v65603s150 idt71v65603s150_i1
+ (
+ .A(RAM_A_ext[17:0]),
+ .adv_ld_(RAM_LDn_ext), // advance (high) / load (low)
+ .bw1_(1'b0),
+ .bw2_(1'b0),
+ .bw3_(1'b0),
+ .bw4_(1'b0), // byte write enables (low)
+ .ce1_(RAM_CE1n_ext),
+ .ce2(1'b1),
+ .ce2_(1'b0), // chip enables
+ .cen_(RAM_CENn_ext), // clock enable (low)
+ .clk(ext_clk), // clock
+ .IO(RAM_D[31:0]),
+ .IOP(RAM_D[35:32]), // data bus
+ .lbo_(1'b0), // linear burst order (low)
+ .oe_(RAM_OEn_ext), // output enable (low)
+ .r_w_(RAM_WEn_ext)
+ ); // read (high) / write (low)
+ end // block: ram_tb_g1
+ endgenerate
+
/* -----\/----- EXCLUDED -----\/-----
diff --git a/fpga/usrp2/extramfifo/nobl_if.v b/fpga/usrp2/extramfifo/nobl_if.v
index 391a841e8..adf9f165b 100644
--- a/fpga/usrp2/extramfifo/nobl_if.v
+++ b/fpga/usrp2/extramfifo/nobl_if.v
@@ -39,6 +39,12 @@ module nobl_if
assign RAM_LDn = 0;
// ZBT/NoBL RAM actually manages its own output enables very well.
assign RAM_OEn = 0;
+
+ // gray code the address to reduce EMI
+ wire [DEPTH-1:0] address_gray;
+
+ bin2gray #(.WIDTH(DEPTH)) bin2gray (.bin(address),.gray(address_gray));
+
//
// Pipeline stage 1
@@ -59,7 +65,7 @@ module nobl_if
if (enable)
begin
- address_pipe1 <= address;
+ address_pipe1 <= address_gray;
write_pipe1 <= write;
RAM_WEn <= ~write; // Creates IOB flob
diff --git a/fpga/usrp2/extramfifo/refill_randomizer.v b/fpga/usrp2/extramfifo/refill_randomizer.v
new file mode 100644
index 000000000..0b30f4049
--- /dev/null
+++ b/fpga/usrp2/extramfifo/refill_randomizer.v
@@ -0,0 +1,66 @@
+//
+// EMI mitigation.
+// Process FULL flag from FIFO so that de-assertion
+// (FIFO now not FULL) is delayed by a pseudo random
+// value, but assertion is passed straight through.
+//
+
+
+module refill_randomizer
+ #(parameter BITS=7)
+ (
+ input clk,
+ input rst,
+ input full_in,
+ output full_out
+ );
+
+ wire feedback;
+ reg full_last;
+ wire full_deasserts;
+ reg [6:0] shift_reg;
+ reg [6:0] count;
+ reg delayed_fall;
+
+
+ always @(posedge clk)
+ full_last <= full_in;
+
+ assign full_deasserts = full_last & ~full_in;
+
+ // 7 bit LFSR
+ always @(posedge clk)
+ if (rst)
+ shift_reg <= 7'b1;
+ else
+ if (full_deasserts)
+ shift_reg <= {shift_reg[5:0],feedback};
+
+ assign feedback = ^(shift_reg & 7'h41);
+
+ always @(posedge clk)
+ if (rst)
+ begin
+ count <= 1;
+ delayed_fall <= 1;
+ end
+ else if (full_deasserts)
+ begin
+ count <= shift_reg;
+ delayed_fall <= 1;
+ end
+ else if (count == 1)
+ begin
+ count <= 1;
+ delayed_fall <= 0;
+ end
+ else
+ begin
+ count <= count - 1;
+ delayed_fall <= 1;
+ end
+
+ // Full_out goes instantly high if full_in does. However its fall is delayed.
+ assign full_out = (full_in == 1) || (full_last == 1) || delayed_fall;
+
+endmodule \ No newline at end of file