diff --git a/.gitignore b/.gitignore index 72fd5f8..c44accf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.out *.vcd +*.lxt diff --git a/sim/test/async_fifo_unit_test.sv b/sim/test/async_fifo_unit_test.sv index 03ab586..32e8612 100644 --- a/sim/test/async_fifo_unit_test.sv +++ b/sim/test/async_fifo_unit_test.sv @@ -15,11 +15,13 @@ module async_fifo_unit_test; reg winc; reg [DSIZE-1:0] wdata; wire wfull; + wire awfull; reg rclk; reg rrst_n; reg rinc; wire [DSIZE-1:0] rdata; wire rempty; + wire arempty; async_fifo #( @@ -33,11 +35,13 @@ module async_fifo_unit_test; winc, wdata, wfull, + awfull, rclk, rrst_n, rinc, rdata, - rempty + rempty, + arempty ); // An example to create a clock @@ -47,10 +51,13 @@ module async_fifo_unit_test; always #3 rclk <= ~rclk; // An example to dump data for visualization - initial $dumpvars(0,async_fifo_unit_test); + initial begin + $dumpvars(0, async_fifo_unit_test); + end task setup(); begin + wrst_n = 1'b0; winc = 1'b0; wdata = 0; @@ -61,6 +68,7 @@ module async_fifo_unit_test; rrst_n = 1; #200; @(posedge wclk); + end endtask @@ -74,7 +82,7 @@ module async_fifo_unit_test; `UNIT_TEST(IDLE) - `INFO("Start IDLE test"); + `INFO("Test: IDLE"); `FAIL_IF(wfull); `FAIL_IF(!rempty); @@ -82,67 +90,106 @@ module async_fifo_unit_test; `UNIT_TEST(SIMPLE_WRITE_AND_READ) - `INFO("Simple write then read"); + `INFO("Test: Simple write then read"); @(posedge wclk) + winc = 1; wdata = 32'hA; + @(posedge wclk) + winc = 0; + @(posedge rclk) - wait (rempty == 0); + + wait (rempty == 1'b0); + `FAIL_IF_NOT_EQUAL(rdata, 32'hA); `UNIT_TEST_END `UNIT_TEST(MULTIPLE_WRITE_AND_READ) - `INFO("Multiple write then read"); + `INFO("Test: Multiple write then read"); - for (i=0; i<20; i = i+1) begin - @(posedge wclk) + for (i=0; i<10; i=i+1) begin + @(negedge wclk); winc = 1; wdata = i; - @(posedge wclk) - winc = 0; - @(posedge rclk) - wait (rempty == 0); + // $display("DEBUG: [%g]: %x", $time, i); + end + @(negedge wclk); + winc = 0; + + #100; + + @(posedge rclk); + + rinc = 1; + for (i=0; i<10; i=i+1) begin + @(posedge rclk); `FAIL_IF_NOT_EQUAL(rdata, i); + // $display("DEBUG: [%g]: %x", $time, rdata); end `UNIT_TEST_END `UNIT_TEST(TEST_FULL_FLAG) - `INFO("Test full flag test"); + `INFO("Test: full flag test"); - for (i=0; i<2**ASIZE; i = i+1) begin - @(posedge wclk) - winc = 1; + winc = 1; + + for (i=0; i<2**ASIZE; i=i+1) begin + @(negedge wclk) wdata = i; end - @(posedge wclk) - @(posedge wclk) + + @(negedge wclk); + winc = 0; + @(posedge wclk) `FAIL_IF_NOT_EQUAL(wfull, 1); + #50; `UNIT_TEST_END `UNIT_TEST(TEST_EMPTY_FLAG) - `INFO("Test empty flag test"); + `INFO("Test: empty flag test"); - for (i=0; i<2**ASIZE; i = i+1) begin + for (i=0; i<2**ASIZE; i=i+1) begin @(posedge wclk) winc = 1; wdata = i; end - `FAIL_IF_NOT_EQUAL(rempty, 1); + `FAIL_IF_NOT_EQUAL(rempty, 0); #50; `UNIT_TEST_END + `UNIT_TEST(TEST_SIMPLE_ALMOST_FULL_FLAG) + + `INFO("Test: Almost full flag simple test"); + + winc = 1; + for (i=0; i<2**ASIZE; i=i+1) begin + @(negedge wclk) + wdata = i; + end + + @(negedge wclk); + winc = 0; + + @(posedge wclk) + `FAIL_IF_NOT_EQUAL(wfull, 1); + + #50; + + `UNIT_TEST_END + `UNIT_TESTS_END endmodule diff --git a/sim/test/wave.gtkw b/sim/test/wave.gtkw index abb6ca5..44783d6 100644 --- a/sim/test/wave.gtkw +++ b/sim/test/wave.gtkw @@ -1,42 +1,96 @@ [*] -[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI -[*] Fri Sep 1 12:55:43 2017 +[*] GTKWave Analyzer v3.3.85 (w)1999-2017 BSI +[*] Wed Oct 4 21:08:19 2017 [*] -[dumpfile] "/home/damien/workspace/async_fifo/sim/test/dump.lxt" -[dumpfile_mtime] "Fri Sep 1 12:55:22 2017" -[dumpfile_size] 3913 -[savefile] "/home/damien/workspace/async_fifo/sim/test/wave.gtkw" -[timestart] 0 -[size] 1000 600 -[pos] -1 -1 -*0.000000 -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 -1 +[dumpfile] "/Users/damien/dev/verilog/async_fifo/sim/test/dump.lxt" +[dumpfile_mtime] "Wed Oct 4 20:53:16 2017" +[dumpfile_size] 3687 +[savefile] "/Users/damien/dev/verilog/async_fifo/sim/test/wave.gtkw" +[timestart] 1089250 +[size] 1920 1056 +[pos] -1 0 +*-13.241215 1077000 -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] async_fifo_unit_test. +[treeopen] async_fifo_unit_test.dut. [sst_width] 196 -[signals_width] 238 +[signals_width] 332 [sst_expanded] 1 -[sst_vpaned_height] 150 +[sst_vpaned_height] 575 +@200 +-TB @22 +async_fifo_unit_test.svut_error[31:0] +async_fifo_unit_test.svut_nb_test[31:0] +async_fifo_unit_test.svut_nb_test_success[31:0] async_fifo_unit_test.i[31:0] @28 +async_fifo_unit_test.wclk[0] +async_fifo_unit_test.wrst_n[0] +async_fifo_unit_test.winc[0] +@22 +async_fifo_unit_test.wdata[31:0] +@28 +async_fifo_unit_test.wfull[0] async_fifo_unit_test.rclk[0] +async_fifo_unit_test.rrst_n[0] +async_fifo_unit_test.rinc[0] @22 async_fifo_unit_test.rdata[31:0] @28 async_fifo_unit_test.rempty[0] -async_fifo_unit_test.rinc[0] -async_fifo_unit_test.rrst_n[0] +@200 +-DUT +@28 +async_fifo_unit_test.dut.rclk[0] +async_fifo_unit_test.dut.rrst_n[0] +async_fifo_unit_test.dut.rinc[0] @22 -async_fifo_unit_test.svut_error[31:0] -async_fifo_unit_test.svut_nb_test[31:0] -async_fifo_unit_test.svut_nb_test_success[31:0] -async_fifo_unit_test.svut_timeout[31:0] -async_fifo_unit_test.svut_timeout_max[31:0] +async_fifo_unit_test.dut.raddr[3:0] +async_fifo_unit_test.dut.rdata[31:0] @28 -async_fifo_unit_test.wclk[0] +async_fifo_unit_test.dut.rempty[0] @22 -async_fifo_unit_test.wdata[31:0] +async_fifo_unit_test.dut.rptr[4:0] +async_fifo_unit_test.dut.rq2_wptr[4:0] @28 -async_fifo_unit_test.wfull[0] -async_fifo_unit_test.winc[0] -async_fifo_unit_test.wrst_n[0] +async_fifo_unit_test.dut.wclk[0] +async_fifo_unit_test.dut.wrst_n[0] +async_fifo_unit_test.dut.winc[0] +async_fifo_unit_test.dut.wfull[0] +@22 +async_fifo_unit_test.dut.wdata[31:0] +async_fifo_unit_test.dut.wptr[4:0] +async_fifo_unit_test.dut.wq2_rptr[4:0] +@200 +-FIFO MEM +@28 +async_fifo_unit_test.dut.fifomem.wclk[0] +async_fifo_unit_test.dut.fifomem.wclken[0] +@22 +async_fifo_unit_test.dut.fifomem.waddr[3:0] +async_fifo_unit_test.dut.fifomem.wdata[31:0] +@28 +async_fifo_unit_test.dut.fifomem.wfull[0] +@22 +async_fifo_unit_test.dut.fifomem.raddr[3:0] +async_fifo_unit_test.dut.fifomem.rdata[31:0] +@200 +-RD PTR EMPTY +@28 +async_fifo_unit_test.dut.rptr_empty.rclk[0] +async_fifo_unit_test.dut.rptr_empty.rrst_n[0] +async_fifo_unit_test.dut.rptr_empty.rinc[0] +async_fifo_unit_test.dut.rptr_empty.rempty[0] +@22 +async_fifo_unit_test.dut.rptr_empty.raddr[3:0] +async_fifo_unit_test.dut.rptr_empty.rbin[4:0] +async_fifo_unit_test.dut.rptr_empty.rbinnext[4:0] +@28 +async_fifo_unit_test.dut.rptr_empty.rempty_val[0] +@22 +async_fifo_unit_test.dut.rptr_empty.rgraynext[4:0] +async_fifo_unit_test.dut.rptr_empty.rptr[4:0] +@23 +async_fifo_unit_test.dut.rptr_empty.rq2_wptr[4:0] [pattern_trace] 1 [pattern_trace] 0 diff --git a/src/vlog/async_fifo.v b/src/vlog/async_fifo.v index 088f567..bb88e5d 100644 --- a/src/vlog/async_fifo.v +++ b/src/vlog/async_fifo.v @@ -1,24 +1,24 @@ //----------------------------------------------------------------------------- // Copyright 2017 Damien Pretet ThotIP -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- `timescale 1 ns / 1 ps `default_nettype none module async_fifo - + #( parameter DSIZE = 8, parameter ASIZE = 4 @@ -28,68 +28,75 @@ module async_fifo input wire winc, input wire [DSIZE-1:0] wdata, output wire wfull, + output wire awfull, input wire rclk, input wire rrst_n, input wire rinc, output wire [DSIZE-1:0] rdata, - output wire rempty + output wire rempty, + output wire arempty ); wire [ASIZE-1:0] waddr, raddr; wire [ ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr; + // The module synchronizing the read point + // from read to write domain sync_r2w sync_r2w ( - .wq2_rptr (wq2_rptr), + .wq2_rptr (wq2_rptr), .rptr (rptr), .wclk (wclk), .wrst_n (wrst_n) ); - + + // The module synchronizing the write point + // from write to read domain sync_w2r sync_w2r ( .rq2_wptr (rq2_wptr), .wptr (wptr), .rclk (rclk), .rrst_n (rrst_n) ); + + // The module handling the write requests + wptr_full + #(ASIZE) + wptr_full ( + .wfull (wfull), + .waddr (waddr), + .wptr (wptr), + .wq2_rptr (wq2_rptr), + .winc (winc), + .wclk (wclk), + .wrst_n (wrst_n) + ); - fifomem - #(DSIZE, ASIZE) + // The DC-RAM + fifomem + #(DSIZE, ASIZE) fifomem ( .rdata (rdata), .wdata (wdata), - .waddr (waddr), + .waddr (waddr), .raddr (raddr), .wclken (winc), .wfull (wfull), .wclk (wclk) ); - rptr_empty - #(ASIZE) + // The module handling read requests + rptr_empty + #(ASIZE) rptr_empty ( .rempty (rempty), .raddr (raddr), - .rptr (rptr), - .rq2_wptr (rq2_wptr), - .rinc (rinc), - .rclk (rclk), + .rptr (rptr), + .rq2_wptr (rq2_wptr), + .rinc (rinc), + .rclk (rclk), .rrst_n (rrst_n) ); - wptr_full - #(ASIZE) - wptr_full ( - .wfull (wfull), - .waddr (waddr), - .wptr (wptr), - .wq2_rptr (wq2_rptr), - .winc (winc), - .wclk (wclk), - .wrst_n (wrst_n) - ); - endmodule `resetall - - diff --git a/src/vlog/fifo_2mem.v b/src/vlog/fifo_2mem.v index 1214920..7c26ece 100644 --- a/src/vlog/fifo_2mem.v +++ b/src/vlog/fifo_2mem.v @@ -23,12 +23,12 @@ module fifomem parameter DATASIZE = 8, // Memory data word width parameter ADDRSIZE = 4 // Number of mem address bits ) ( - input wire [DATASIZE-1:0] wdata, - input wire [ADDRSIZE-1:0] waddr, - input wire [ADDRSIZE-1:0] raddr, + input wire wclk, input wire wclken, + input wire [ADDRSIZE-1:0] waddr, + input wire [DATASIZE-1:0] wdata, input wire wfull, - input wire wclk, + input wire [ADDRSIZE-1:0] raddr, output wire [DATASIZE-1:0] rdata ); @@ -46,5 +46,3 @@ module fifomem endmodule `resetall - - diff --git a/src/vlog/rptr_empty.v b/src/vlog/rptr_empty.v index 141c81d..0dd5a2b 100644 --- a/src/vlog/rptr_empty.v +++ b/src/vlog/rptr_empty.v @@ -27,6 +27,7 @@ module rptr_empty input wire rinc, input wire [ADDRSIZE :0] rq2_wptr, output reg rempty, + output reg arempty, output wire [ADDRSIZE-1:0] raddr, output reg [ADDRSIZE :0] rptr ); @@ -38,12 +39,13 @@ module rptr_empty //------------------- // GRAYSTYLE2 pointer //------------------- - always @(posedge rclk or negedge rrst_n) begin + if (!rrst_n) {rbin, rptr} <= 0; else {rbin, rptr} <= {rbinnext, rgraynext}; + end // Memory read-address pointer (okay to use binary to address memory) @@ -56,15 +58,19 @@ module rptr_empty //--------------------------------------------------------------- assign rempty_val = (rgraynext == rq2_wptr); - always @(posedge rclk or negedge rrst_n) begin - if (!rrst_n) + always @ (posedge rclk or negedge rrst_n) begin + + if (!rrst_n) begin + arempty <= 1'b0; rempty <= 1'b1; - else + end + else begin + arempty <= 1'b0; rempty <= rempty_val; + end + end endmodule `resetall - - diff --git a/src/vlog/sync_r2w.v b/src/vlog/sync_r2w.v index cb6b4f9..0cbdfde 100644 --- a/src/vlog/sync_r2w.v +++ b/src/vlog/sync_r2w.v @@ -1,42 +1,44 @@ //----------------------------------------------------------------------------- // Copyright 2017 Damien Pretet ThotIP -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- `timescale 1 ns / 1 ps `default_nettype none -module sync_r2w - +module sync_r2w + #( parameter ADDRSIZE = 4 )( - input wire wclk, - input wire wrst_n, - input [ADDRSIZE:0] rptr, - output reg [ADDRSIZE:0] wq2_rptr + input wire wclk, + input wire wrst_n, + input wire [ADDRSIZE:0] rptr, + output reg [ADDRSIZE:0] wq2_rptr ); - + reg [ADDRSIZE:0] wq1_rptr; - - always @(posedge wclk or negedge wrst_n) - if (!wrst_n) + + always @(posedge wclk or negedge wrst_n) begin + + if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0; else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr}; + end + endmodule `resetall - diff --git a/src/vlog/sync_w2r.v b/src/vlog/sync_w2r.v index a7f6b1c..b684098 100644 --- a/src/vlog/sync_w2r.v +++ b/src/vlog/sync_w2r.v @@ -22,10 +22,10 @@ module sync_w2r #( parameter ADDRSIZE = 4 )( - input rclk, - input rrst_n, - output reg [ADDRSIZE:0] rq2_wptr, - input [ADDRSIZE:0] wptr + input wire rclk, + input wire rrst_n, + output reg [ADDRSIZE:0] rq2_wptr, + input wire [ADDRSIZE:0] wptr ); reg [ADDRSIZE:0] rq1_wptr; @@ -36,9 +36,9 @@ module sync_w2r {rq2_wptr,rq1_wptr} <= 0; else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr}; + end endmodule `resetall - diff --git a/src/vlog/wptr_full.v b/src/vlog/wptr_full.v index 60e59ed..8e97efc 100644 --- a/src/vlog/wptr_full.v +++ b/src/vlog/wptr_full.v @@ -17,19 +17,19 @@ `timescale 1 ns / 1 ps `default_nettype none - module wptr_full #( parameter ADDRSIZE = 4 )( - input winc, - input wclk, - input wrst_n, - input [ADDRSIZE :0] wq2_rptr, - output reg wfull, - output [ADDRSIZE-1:0] waddr, - output reg [ADDRSIZE :0] wptr + input wire wclk, + input wire wrst_n, + input wire winc, + input wire [ADDRSIZE :0] wq2_rptr, + output reg wfull, + output reg awfull, + output wire [ADDRSIZE-1:0] waddr, + output reg [ADDRSIZE :0] wptr ); reg [ADDRSIZE:0] wbin; @@ -37,11 +37,14 @@ module wptr_full wire wfull_val; // GRAYSTYLE2 pointer - always @(posedge wclk or negedge wrst_n) + always @(posedge wclk or negedge wrst_n) begin + if (!wrst_n) {wbin, wptr} <= 0; else {wbin, wptr} <= {wbinnext, wgraynext}; + + end // Memory write-address pointer (okay to use binary to address memory) assign waddr = wbin[ADDRSIZE-1:0]; @@ -55,13 +58,20 @@ module wptr_full // (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); //------------------------------------------------------------------ - assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]}); + assign wfull_val = (wgraynext == {~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]}); - always @(posedge wclk or negedge wrst_n) - if (!wrst_n) + always @(posedge wclk or negedge wrst_n) begin + + if (!wrst_n) begin + awfull <= 1'b0; wfull <= 1'b0; - else + end + else begin + awfull <= 1'b0; wfull <= wfull_val; + end + + end endmodule