promach
Advanced Member level 4
As in https://github.com/KastnerRG/riffa/blob/master/fpga/riffa_hdl/async_fifo.v#L76-L79 , could anyone advise on the differences in the context of purpose of the parameters ?
- - - Updated - - -
For lines 103 and 114 in the same verilog code, what is the semantic difference between EMPTY in async_cmp and RD_EMPTY in rd_ptr_empty ? Both are indirectly related by the signal wCmpEmpty.
- - - Updated - - -
Besides, does anyone have any clue why 'rCount < 2' as in https://github.com/KastnerRG/riffa/blob/master/fpga/riffa_hdl/async_fifo_fwft.v#L79 ?
wire [C_DEPTH_BITS-1:0] wWrPtr;
wire [C_DEPTH_BITS-1:0] wRdPtr;
wire [C_DEPTH_BITS-1:0] wWrPtrP1;
wire [C_DEPTH_BITS-1:0] wRdPtrP1;
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 // ---------------------------------------------------------------------- // Copyright (c) 2016, The Regents of the University of California All // rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // * Neither the name of The Regents of the University of California // nor the names of its contributors may be used to endorse or // promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE // UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // ---------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: async_fifo.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Asynchronous capable parameterized FIFO. As with all // traditional FIFOs, the RD_DATA will be valid one cycle following a RD_EN // assertion. RD_EMPTY will remain low until the cycle following the last RD_EN // assertion. Note, that RD_EMPTY may actually be high on the same cycle that // RD_DATA contains valid data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Based on design by CE Cummings in Simulation and // Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer // Comparisons //----------------------------------------------------------------------------- `timescale 1ns/1ns module async_fifo #( parameter C_WIDTH = 32, // Data bus width parameter C_DEPTH = 1024, // Depth of the FIFO // Local parameters parameter C_REAL_DEPTH = 2**clog2(C_DEPTH), parameter C_DEPTH_BITS = clog2(C_REAL_DEPTH), parameter C_DEPTH_P1_BITS = clog2(C_REAL_DEPTH+1) ) ( input RD_CLK, // Read clock input RD_RST, // Read synchronous reset input WR_CLK, // Write clock input WR_RST, // Write synchronous reset input [C_WIDTH-1:0] WR_DATA, // Write data input (WR_CLK) input WR_EN, // Write enable, high active (WR_CLK) output [C_WIDTH-1:0] RD_DATA, // Read data output (RD_CLK) input RD_EN, // Read enable, high active (RD_CLK) output WR_FULL, // Full condition (WR_CLK) output RD_EMPTY // Empty condition (RD_CLK) ); `include "functions.vh" wire wCmpEmpty; wire wCmpFull; wire [C_DEPTH_BITS-1:0] wWrPtr; wire [C_DEPTH_BITS-1:0] wRdPtr; wire [C_DEPTH_BITS-1:0] wWrPtrP1; wire [C_DEPTH_BITS-1:0] wRdPtrP1; // Memory block (synthesis attributes applied to this module will // determine the memory option). ram_2clk_1w_1r #(.C_RAM_WIDTH(C_WIDTH), .C_RAM_DEPTH(C_REAL_DEPTH)) mem ( .CLKA(WR_CLK), .ADDRA(wWrPtr), .WEA(WR_EN & !WR_FULL), .DINA(WR_DATA), .CLKB(RD_CLK), .ADDRB(wRdPtr), .DOUTB(RD_DATA) ); // Compare the pointers. async_cmp #(.C_DEPTH_BITS(C_DEPTH_BITS)) asyncCompare ( .WR_RST(WR_RST), .WR_CLK(WR_CLK), .RD_RST(RD_RST), .RD_CLK(RD_CLK), .RD_VALID(RD_EN & !RD_EMPTY), .WR_VALID(WR_EN & !WR_FULL), .EMPTY(wCmpEmpty), .FULL(wCmpFull), .WR_PTR(wWrPtr), .WR_PTR_P1(wWrPtrP1), .RD_PTR(wRdPtr), .RD_PTR_P1(wRdPtrP1) ); // Calculate empty rd_ptr_empty #(.C_DEPTH_BITS(C_DEPTH_BITS)) rdPtrEmpty ( .RD_EMPTY(RD_EMPTY), .RD_PTR(wRdPtr), .RD_PTR_P1(wRdPtrP1), .CMP_EMPTY(wCmpEmpty), .RD_EN(RD_EN), .RD_CLK(RD_CLK), .RD_RST(RD_RST) ); // Calculate full wr_ptr_full #(.C_DEPTH_BITS(C_DEPTH_BITS)) wrPtrFull ( .WR_CLK(WR_CLK), .WR_RST(WR_RST), .WR_EN(WR_EN), .WR_FULL(WR_FULL), .WR_PTR(wWrPtr), .WR_PTR_P1(wWrPtrP1), .CMP_FULL(wCmpFull) ); endmodule module async_cmp #( parameter C_DEPTH_BITS = 4, // Local parameters parameter N = C_DEPTH_BITS-1 ) ( input WR_RST, input WR_CLK, input RD_RST, input RD_CLK, input RD_VALID, input WR_VALID, output EMPTY, output FULL, input [C_DEPTH_BITS-1:0] WR_PTR, input [C_DEPTH_BITS-1:0] RD_PTR, input [C_DEPTH_BITS-1:0] WR_PTR_P1, input [C_DEPTH_BITS-1:0] RD_PTR_P1 ); reg rDir=0; wire wDirSet = ( (WR_PTR[N]^RD_PTR[N-1]) & ~(WR_PTR[N-1]^RD_PTR[N])); wire wDirClr = ((~(WR_PTR[N]^RD_PTR[N-1]) & (WR_PTR[N-1]^RD_PTR[N])) | WR_RST); reg rRdValid=0; reg rEmpty=1; reg rFull=0; wire wATBEmpty = ((WR_PTR == RD_PTR_P1) && (RD_VALID | rRdValid)); wire wATBFull = ((WR_PTR_P1 == RD_PTR) && WR_VALID); wire wEmpty = ((WR_PTR == RD_PTR) && !rDir); wire wFull = ((WR_PTR == RD_PTR) && rDir); assign EMPTY = wATBEmpty || rEmpty; assign FULL = wATBFull || rFull; always @(posedge wDirSet or posedge wDirClr) if (wDirClr) rDir <= 1'b0; else rDir <= 1'b1; always @(posedge RD_CLK) begin rEmpty <= (RD_RST ? 1'd1 : wEmpty); rRdValid <= (RD_RST ? 1'd0 : RD_VALID); end always @(posedge WR_CLK) begin rFull <= (WR_RST ? 1'd0 : wFull); end endmodule module rd_ptr_empty #( parameter C_DEPTH_BITS = 4 ) ( input RD_CLK, input RD_RST, input RD_EN, output RD_EMPTY, output [C_DEPTH_BITS-1:0] RD_PTR, output [C_DEPTH_BITS-1:0] RD_PTR_P1, input CMP_EMPTY ); reg rEmpty=1; reg rEmpty2=1; reg [C_DEPTH_BITS-1:0] rRdPtr=0; reg [C_DEPTH_BITS-1:0] rRdPtrP1=0; reg [C_DEPTH_BITS-1:0] rBin=0; reg [C_DEPTH_BITS-1:0] rBinP1=1; wire [C_DEPTH_BITS-1:0] wGrayNext; wire [C_DEPTH_BITS-1:0] wGrayNextP1; wire [C_DEPTH_BITS-1:0] wBinNext; wire [C_DEPTH_BITS-1:0] wBinNextP1; assign RD_EMPTY = rEmpty; assign RD_PTR = rRdPtr; assign RD_PTR_P1 = rRdPtrP1; // Gray coded pointer always @(posedge RD_CLK or posedge RD_RST) begin if (RD_RST) begin rBin <= #1 0; rBinP1 <= #1 1; rRdPtr <= #1 0; rRdPtrP1 <= #1 0; end else begin rBin <= #1 wBinNext; rBinP1 <= #1 wBinNextP1; rRdPtr <= #1 wGrayNext; rRdPtrP1 <= #1 wGrayNextP1; end end // Increment the binary count if not empty assign wBinNext = (!rEmpty ? rBin + RD_EN : rBin); assign wBinNextP1 = (!rEmpty ? rBinP1 + RD_EN : rBinP1); assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion always @(posedge RD_CLK) begin if (CMP_EMPTY) {rEmpty, rEmpty2} <= #1 2'b11; else {rEmpty, rEmpty2} <= #1 {rEmpty2, CMP_EMPTY}; end endmodule module wr_ptr_full #( parameter C_DEPTH_BITS = 4 ) ( input WR_CLK, input WR_RST, input WR_EN, output WR_FULL, output [C_DEPTH_BITS-1:0] WR_PTR, output [C_DEPTH_BITS-1:0] WR_PTR_P1, input CMP_FULL ); reg rFull=0; reg rFull2=0; reg [C_DEPTH_BITS-1:0] rPtr=0; reg [C_DEPTH_BITS-1:0] rPtrP1=0; reg [C_DEPTH_BITS-1:0] rBin=0; reg [C_DEPTH_BITS-1:0] rBinP1=1; wire [C_DEPTH_BITS-1:0] wGrayNext; wire [C_DEPTH_BITS-1:0] wGrayNextP1; wire [C_DEPTH_BITS-1:0] wBinNext; wire [C_DEPTH_BITS-1:0] wBinNextP1; assign WR_FULL = rFull; assign WR_PTR = rPtr; assign WR_PTR_P1 = rPtrP1; // Gray coded pointer always @(posedge WR_CLK or posedge WR_RST) begin if (WR_RST) begin rBin <= #1 0; rBinP1 <= #1 1; rPtr <= #1 0; rPtrP1 <= #1 0; end else begin rBin <= #1 wBinNext; rBinP1 <= #1 wBinNextP1; rPtr <= #1 wGrayNext; rPtrP1 <= #1 wGrayNextP1; end end // Increment the binary count if not full assign wBinNext = (!rFull ? rBin + WR_EN : rBin); assign wBinNextP1 = (!rFull ? rBinP1 + WR_EN : rBinP1); assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion always @(posedge WR_CLK) begin if (WR_RST) {rFull, rFull2} <= #1 2'b00; else if (CMP_FULL) {rFull, rFull2} <= #1 2'b11; else {rFull, rFull2} <= #1 {rFull2, CMP_FULL}; end endmodule
- - - Updated - - -
For lines 103 and 114 in the same verilog code, what is the semantic difference between EMPTY in async_cmp and RD_EMPTY in rd_ptr_empty ? Both are indirectly related by the signal wCmpEmpty.
.EMPTY(wCmpEmpty),
.RD_EMPTY(RD_EMPTY),
- - - Updated - - -
Besides, does anyone have any clue why 'rCount < 2' as in https://github.com/KastnerRG/riffa/blob/master/fpga/riffa_hdl/async_fifo_fwft.v#L79 ?
wire wRen = RD_EN || (rCount < 2'd2);
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 // ---------------------------------------------------------------------- // Copyright (c) 2016, The Regents of the University of California All // rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // * Neither the name of The Regents of the University of California // nor the names of its contributors may be used to endorse or // promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE // UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // ---------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: async_fifo_fwft.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: An asynchronous capable parameterized FIFO. As with all // first word fall through FIFOs, the RD_DATA will be valid when RD_EMPTY is // low. Asserting RD_EN will consume the current RD_DATA value and cause the // next value (if it exists) to appear on RD_DATA on the following cycle. Be sure // to check if RD_EMPTY is low each cycle to determine if RD_DATA is valid. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `timescale 1ns/1ns module async_fifo_fwft #( parameter C_WIDTH = 32, // Data bus width parameter C_DEPTH = 1024, // Depth of the FIFO // Local parameters parameter C_REAL_DEPTH = 2**clog2(C_DEPTH), parameter C_DEPTH_BITS = clog2s(C_REAL_DEPTH), parameter C_DEPTH_P1_BITS = clog2s(C_REAL_DEPTH+1) ) ( input RD_CLK, // Read clock input RD_RST, // Read synchronous reset input WR_CLK, // Write clock input WR_RST, // Write synchronous reset input [C_WIDTH-1:0] WR_DATA, // Write data input (WR_CLK) input WR_EN, // Write enable, high active (WR_CLK) output [C_WIDTH-1:0] RD_DATA, // Read data output (RD_CLK) input RD_EN, // Read enable, high active (RD_CLK) output WR_FULL, // Full condition (WR_CLK) output RD_EMPTY // Empty condition (RD_CLK) ); `include "functions.vh" reg [C_WIDTH-1:0] rData=0; reg [C_WIDTH-1:0] rCache=0; reg [1:0] rCount=0; reg rFifoDataValid=0; reg rDataValid=0; reg rCacheValid=0; wire [C_WIDTH-1:0] wData; wire wEmpty; wire wRen = RD_EN || (rCount < 2'd2); assign RD_DATA = rData; assign RD_EMPTY = !rDataValid; // Wrapped non-FWFT FIFO (synthesis attributes applied to this module will // determine the memory option). async_fifo #(.C_WIDTH(C_WIDTH), .C_DEPTH(C_DEPTH)) fifo ( .WR_CLK(WR_CLK), .WR_RST(WR_RST), .RD_CLK(RD_CLK), .RD_RST(RD_RST), .WR_EN(WR_EN), .WR_DATA(WR_DATA), .WR_FULL(WR_FULL), .RD_EN(wRen), .RD_DATA(wData), .RD_EMPTY(wEmpty) ); always @ (posedge RD_CLK) begin if (RD_RST) begin rCount <= #1 0; rDataValid <= #1 0; rCacheValid <= #1 0; rFifoDataValid <= #1 0; end else begin // Keep track of the count rCount <= #1 rCount + (wRen & !wEmpty) - (!RD_EMPTY & RD_EN); // Signals when wData from FIFO is valid rFifoDataValid <= #1 (wRen & !wEmpty); // Keep rData up to date if (rFifoDataValid) begin if (RD_EN | !rDataValid) begin rData <= #1 wData; rDataValid <= #1 1'd1; rCacheValid <= #1 1'd0; end else begin rCacheValid <= #1 1'd1; end rCache <= #1 wData; end else begin if (RD_EN | !rDataValid) begin rData <= #1 rCache; rDataValid <= #1 rCacheValid; rCacheValid <= #1 1'd0; end end end end endmodule