gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

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