async_fifo_one_deep.sv (1763B)
1 // Copyright 2020, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 `default_nettype none 5 6 // Based on the design described in 7 // "5.8.2 Multi-bit CDC signal passing using 1-deep / 2-register FIFO synchronizer" 8 // Clock Domain Crossing (CDC) Design & Verification Techniques 9 // http://www.sunburst-design.com/papers/CummingsSNUG2008Boston_CDC.pdf 10 11 module async_fifo_one_deep #( 12 parameter WIDTH = 16 13 )( 14 input wire wr_clk, 15 input wire wr_valid, 16 input wire [WIDTH-1:0]wr_data, 17 output wire wr_ready, 18 input wire rd_clk, 19 input wire rd_ready, 20 output wire rd_valid, 21 output wire [WIDTH-1:0]rd_data 22 ); 23 24 // 2 register deep fifo storage 25 reg [WIDTH-1:0]fifo_reg_0 = 0; 26 reg [WIDTH-1:0]fifo_reg_1 = 0; 27 28 // wr domain registers 29 reg wr_ptr = 0; 30 reg wr_rd_ptr = 0; 31 reg wr_rd_ptr_sync = 0; 32 33 // writable (empty) when read and write pointers are the same 34 assign wr_ready = ~(wr_rd_ptr ^ wr_ptr); 35 36 always_ff @(posedge wr_clk) begin 37 // sync rd_ptr into wr_ domain 38 wr_rd_ptr_sync <= rd_ptr; 39 wr_rd_ptr <= wr_rd_ptr_sync; 40 41 // wr_ptr state machine 42 wr_ptr <= (wr_valid & wr_ready) ^ wr_ptr; 43 44 // fifo registers write control 45 if (wr_valid & wr_ready) begin 46 if (wr_ptr) begin 47 fifo_reg_1 <= wr_data; 48 end else begin 49 fifo_reg_0 <= wr_data; 50 end 51 end 52 end 53 54 // fifo registers read control 55 assign rd_data = rd_ptr ? fifo_reg_1 : fifo_reg_0; 56 57 // rd domain registers 58 reg rd_ptr = 0; 59 reg rd_wr_ptr = 0; 60 reg rd_wr_ptr_sync = 0; 61 62 // readable (full) when read and write pointers are different 63 assign rd_valid = (rd_wr_ptr ^ rd_ptr); 64 65 always_ff @(posedge rd_clk) begin 66 // sync wr_ptr into rd_ domain 67 rd_wr_ptr_sync <= wr_ptr; 68 rd_wr_ptr <= rd_wr_ptr_sync; 69 70 // rd_ptr state machine 71 rd_ptr <= (rd_valid & rd_ready) ^ rd_ptr; 72 end 73 74 endmodule