+++ /dev/null
-
-module cascadefifo_2clock
- #(parameter DWIDTH=32, AWIDTH=9)
- (input wclk, input [DWIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output [AWIDTH-1:0] level_wclk,
- input rclk, output [DWIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output [AWIDTH-1:0] level_rclk,
- input arst);
-
- wire [DWIDTH-1:0] data_int1, data_int2;
- wire src_rdy_int1, src_rdy_int2, dst_rdy_int1, dst_rdy_int2;
-
- fifo_short #(.WIDTH(DWIDTH)) shortfifo
- (.clk(wclk), .reset(arst), .clear(0),
- .datain(datain), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
- .dataout(data_int1), .src_rdy_o(src_rdy_int1), .dst_rdy_i(dst_rdy_int1) );
-
- newfifo_2clock #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) fifo_2clock
- (.wclk(wclk), .datain(data_int1), .src_rdy_i(src_rdy_int1), .dst_rdy_o(dst_rdy_int1), .level_wclk(level_wclk),
- .rclk(rclk), .dataout(data_int2), .src_rdy_o(src_rdy_int2), .dst_rdy_i(dst_rdy_int2), .level_rclk(level_rclk),
- .arst(arst) );
-
- fifo_short #(.WIDTH(DWIDTH)) shortfifo2
- (.clk(rclk), .reset(arst), .clear(0),
- .datain(data_int2), .src_rdy_i(src_rdy_int2), .dst_rdy_o(dst_rdy_int2),
- .dataout(dataout), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i) );
-
-endmodule // fifo_2clock_casc
-
--- /dev/null
+
+module newfifo_2clock
+ #(parameter DWIDTH=32, AWIDTH=9)
+ (input wclk, input [DWIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output reg [AWIDTH-1:0] level_wclk,
+ input rclk, output [DWIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output reg [AWIDTH-1:0] level_rclk,
+ input arst);
+
+ wire full, empty, write, read;
+
+ assign dst_rdy_o = ~full;
+ assign src_rdy_o = ~empty;
+ assign write = src_rdy_i & dst_rdy_o;
+ assign read = src_rdy_o & dst_rdy_i;
+
+//`define USE_XLNX_FIFO 1
+`ifdef USE_XLNX_FIFO
+ fifo_xlnx_512x36_2clk mac_tx_fifo_2clk
+ (.rst(rst),
+ .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(fifo_occupied[8:0]),
+ .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count() );
+`else
+ // ISE sucks, so the following doesn't work properly
+
+ reg [AWIDTH-1:0] wr_addr, rd_addr;
+ wire [AWIDTH-1:0] wr_addr_rclk, rd_addr_wclk;
+ wire [AWIDTH-1:0] next_rd_addr;
+ wire enb_read;
+
+ // Write side management
+ wire [AWIDTH-1:0] next_wr_addr = wr_addr + 1;
+ always @(posedge wclk or posedge arst)
+ if(arst)
+ wr_addr <= 0;
+ else if(write)
+ wr_addr <= next_wr_addr;
+ assign full = (next_wr_addr == rd_addr_wclk);
+
+ // RAM for data storage. Data out is registered, complicating the
+ // read side logic
+ ram_2port #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) mac_rx_ff_ram
+ (.clka(wclk),.ena(1'b1),.wea(write),.addra(wr_addr),.dia(datain),.doa(),
+ .clkb(rclk),.enb(enb_read),.web(1'b0),.addrb(next_rd_addr),.dib(0),.dob(dataout) );
+
+ // Read side management
+ reg data_valid;
+ assign empty = ~data_valid;
+ assign next_rd_addr = rd_addr + data_valid;
+ assign enb_read = read | ~data_valid;
+
+ always @(posedge rclk or posedge arst)
+ if(arst)
+ rd_addr <= 0;
+ else if(read)
+ rd_addr <= rd_addr + 1;
+
+ always @(posedge rclk or posedge arst)
+ if(arst)
+ data_valid <= 0;
+ else
+ if(read & (next_rd_addr == wr_addr_rclk))
+ data_valid <= 0;
+ else if(next_rd_addr != wr_addr_rclk)
+ data_valid <= 1;
+
+ // Send pointers across clock domains via gray code
+ gray_send #(.WIDTH(AWIDTH)) send_wr_addr
+ (.clk_in(wclk),.addr_in(wr_addr),
+ .clk_out(rclk),.addr_out(wr_addr_rclk) );
+
+ gray_send #(.WIDTH(AWIDTH)) send_rd_addr
+ (.clk_in(rclk),.addr_in(rd_addr),
+ .clk_out(wclk),.addr_out(rd_addr_wclk) );
+
+ // Generate fullness info, these are approximate and may be delayed
+ // and are only for higher-level flow control.
+ // Only full and empty are guaranteed exact.
+ always @(posedge wclk)
+ level_wclk <= wr_addr - rd_addr_wclk;
+ always @(posedge rclk)
+ level_rclk <= wr_addr_rclk - rd_addr;
+`endif
+endmodule // fifo_2clock
--- /dev/null
+
+module cascadefifo_2clock
+ #(parameter DWIDTH=32, AWIDTH=9)
+ (input wclk, input [DWIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output [AWIDTH-1:0] level_wclk,
+ input rclk, output [DWIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output [AWIDTH-1:0] level_rclk,
+ input arst);
+
+ wire [DWIDTH-1:0] data_int1, data_int2;
+ wire src_rdy_int1, src_rdy_int2, dst_rdy_int1, dst_rdy_int2;
+
+ fifo_short #(.WIDTH(DWIDTH)) shortfifo
+ (.clk(wclk), .reset(arst), .clear(0),
+ .datain(datain), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
+ .dataout(data_int1), .src_rdy_o(src_rdy_int1), .dst_rdy_i(dst_rdy_int1) );
+
+ newfifo_2clock #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) fifo_2clock
+ (.wclk(wclk), .datain(data_int1), .src_rdy_i(src_rdy_int1), .dst_rdy_o(dst_rdy_int1), .level_wclk(level_wclk),
+ .rclk(rclk), .dataout(data_int2), .src_rdy_o(src_rdy_int2), .dst_rdy_i(dst_rdy_int2), .level_rclk(level_rclk),
+ .arst(arst) );
+
+ fifo_short #(.WIDTH(DWIDTH)) shortfifo2
+ (.clk(rclk), .reset(arst), .clear(0),
+ .datain(data_int2), .src_rdy_i(src_rdy_int2), .dst_rdy_o(dst_rdy_int2),
+ .dataout(dataout), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i) );
+
+endmodule // fifo_2clock_casc
+
+++ /dev/null
-module fifo_tb();
-
- reg clk, rst;
- wire short_full, short_empty, long_full, long_empty;
- wire casc_full, casc_empty, casc2_full, casc2_empty;
- reg read, write;
-
- wire [7:0] short_do, long_do;
- wire [7:0] casc_do, casc2_do;
- reg [7:0] di;
-
- reg clear = 0;
-
- shortfifo #(.WIDTH(8)) shortfifo
- (.clk(clk),.rst(rst),.datain(di),.dataout(short_do),.clear(clear),
- .read(read),.write(write),.full(short_full),.empty(short_empty));
-
- longfifo #(.WIDTH(8), .SIZE(4)) longfifo
- (.clk(clk),.rst(rst),.datain(di),.dataout(long_do),.clear(clear),
- .read(read),.write(write),.full(long_full),.empty(long_empty));
-
- cascadefifo #(.WIDTH(8), .SIZE(4)) cascadefifo
- (.clk(clk),.rst(rst),.datain(di),.dataout(casc_do),.clear(clear),
- .read(read),.write(write),.full(casc_full),.empty(casc_empty));
-
- cascadefifo2 #(.WIDTH(8), .SIZE(4)) cascadefifo2
- (.clk(clk),.rst(rst),.datain(di),.dataout(casc2_do),.clear(clear),
- .read(read),.write(write),.full(casc2_full),.empty(casc2_empty));
-
- initial rst = 1;
- initial #1000 rst = 0;
- initial clk = 0;
- always #50 clk = ~clk;
-
- initial di = 8'hAE;
- initial read = 0;
- initial write = 0;
-
- always @(posedge clk)
- if(write)
- di <= di + 1;
-
- always @(posedge clk)
- begin
- if(short_full != long_full)
- $display("Error: FULL mismatch");
- if(short_empty != long_empty)
- $display("Note: EMPTY mismatch, usually not a problem (longfifo has 2 cycle latency)");
- if(read & (short_do != long_do))
- $display("Error: DATA mismatch");
- end
-
- initial $dumpfile("fifo_tb.vcd");
- initial $dumpvars(0,fifo_tb);
-
- initial
- begin
- @(negedge rst);
- @(posedge clk);
- repeat (10)
- @(posedge clk);
- write <= 1;
- @(posedge clk);
- write <= 0;
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- read <= 1;
- @(posedge clk);
- read <= 0;
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
-
- repeat(10)
- begin
- write <= 1;
- @(posedge clk);
- write <= 0;
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- read <= 1;
- @(posedge clk);
- read <= 0;
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- end // repeat (10)
-
- write <= 1;
- repeat (4)
- @(posedge clk);
- write <= 0;
- @(posedge clk);
- read <= 1;
- repeat (4)
- @(posedge clk);
- read <= 0;
- @(posedge clk);
-
-
- write <= 1;
- repeat (4)
- @(posedge clk);
- write <= 0;
- @(posedge clk);
- repeat (4)
- begin
- read <= 1;
- @(posedge clk);
- read <= 0;
- @(posedge clk);
- end
-
- write <= 1;
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- @(posedge clk);
- read <= 1;
- repeat (5)
- @(posedge clk);
- write <= 0;
- @(posedge clk);
- @(posedge clk);
- read <= 0;
- @(posedge clk);
-
- write <= 1;
- repeat (16)
- @(posedge clk);
- write <= 0;
- @(posedge clk);
-
- read <= 1;
- repeat (16)
- @(posedge clk);
- read <= 0;
- @(posedge clk);
-
- repeat (10)
- @(posedge clk);
- $finish;
- end
-endmodule // longfifo_tb
+++ /dev/null
-
-module newfifo_2clock
- #(parameter DWIDTH=32, AWIDTH=9)
- (input wclk, input [DWIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output reg [AWIDTH-1:0] level_wclk,
- input rclk, output [DWIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output reg [AWIDTH-1:0] level_rclk,
- input arst);
-
- wire full, empty, write, read;
-
- assign dst_rdy_o = ~full;
- assign src_rdy_o = ~empty;
- assign write = src_rdy_i & dst_rdy_o;
- assign read = src_rdy_o & dst_rdy_i;
-
-//`define USE_XLNX_FIFO 1
-`ifdef USE_XLNX_FIFO
- fifo_xlnx_512x36_2clk mac_tx_fifo_2clk
- (.rst(rst),
- .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(fifo_occupied[8:0]),
- .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count() );
-`else
- // ISE sucks, so the following doesn't work properly
-
- reg [AWIDTH-1:0] wr_addr, rd_addr;
- wire [AWIDTH-1:0] wr_addr_rclk, rd_addr_wclk;
- wire [AWIDTH-1:0] next_rd_addr;
- wire enb_read;
-
- // Write side management
- wire [AWIDTH-1:0] next_wr_addr = wr_addr + 1;
- always @(posedge wclk or posedge arst)
- if(arst)
- wr_addr <= 0;
- else if(write)
- wr_addr <= next_wr_addr;
- assign full = (next_wr_addr == rd_addr_wclk);
-
- // RAM for data storage. Data out is registered, complicating the
- // read side logic
- ram_2port #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) mac_rx_ff_ram
- (.clka(wclk),.ena(1'b1),.wea(write),.addra(wr_addr),.dia(datain),.doa(),
- .clkb(rclk),.enb(enb_read),.web(1'b0),.addrb(next_rd_addr),.dib(0),.dob(dataout) );
-
- // Read side management
- reg data_valid;
- assign empty = ~data_valid;
- assign next_rd_addr = rd_addr + data_valid;
- assign enb_read = read | ~data_valid;
-
- always @(posedge rclk or posedge arst)
- if(arst)
- rd_addr <= 0;
- else if(read)
- rd_addr <= rd_addr + 1;
-
- always @(posedge rclk or posedge arst)
- if(arst)
- data_valid <= 0;
- else
- if(read & (next_rd_addr == wr_addr_rclk))
- data_valid <= 0;
- else if(next_rd_addr != wr_addr_rclk)
- data_valid <= 1;
-
- // Send pointers across clock domains via gray code
- gray_send #(.WIDTH(AWIDTH)) send_wr_addr
- (.clk_in(wclk),.addr_in(wr_addr),
- .clk_out(rclk),.addr_out(wr_addr_rclk) );
-
- gray_send #(.WIDTH(AWIDTH)) send_rd_addr
- (.clk_in(rclk),.addr_in(rd_addr),
- .clk_out(wclk),.addr_out(rd_addr_wclk) );
-
- // Generate fullness info, these are approximate and may be delayed
- // and are only for higher-level flow control.
- // Only full and empty are guaranteed exact.
- always @(posedge wclk)
- level_wclk <= wr_addr - rd_addr_wclk;
- always @(posedge rclk)
- level_rclk <= wr_addr_rclk - rd_addr;
-`endif
-endmodule // fifo_2clock