Source / Read the circuit

adc_async_fifo.sv

lessons/adc_digital/rtl/adc_async_fifo.sv

`timescale 1ns/1ps
// AD08: depth8, signed18/F4 payload. Coordinated reset required.
// Read data/valid registered on an accepted pop. Not a physical CDC signoff.
module adc_async_fifo(input wire wclk, wrst_n, push,
    input wire [17:0] wdata, output wire full,
    output reg overflow,
    input wire rclk, rrst_n, pop,
    output reg [17:0] rdata, output reg rvalid, underflow,
    output wire empty);
    reg [17:0] mem[0:7];
    reg [3:0] wb, wg, rb, rg;
    (* async_reg="true" *) reg [3:0] rg1, rg2, wg1, wg2;
    wire [3:0] wb_next=wb+1'b1;
    wire [3:0] wg_next=(wb_next>>1)^wb_next;
    assign full = (wg=={~rg2[3:2],rg2[1:0]});
    assign empty = (rg==wg2);
    always @(posedge wclk) begin
        if(!wrst_n) begin wb<=0; wg<=0; rg1<=0; rg2<=0; overflow<=0; end
        else begin
            rg1<=rg; rg2<=rg1;
            if(push) begin
                if(full) overflow<=1;
                else begin mem[wb[2:0]]<=wdata; wb<=wb_next; wg<=wg_next; end
            end
        end
    end
    always @(posedge rclk) begin
        if(!rrst_n) begin rb<=0; rg<=0; wg1<=0; wg2<=0;
            rdata<=0; rvalid<=0; underflow<=0; end
        else begin
            wg1<=wg; wg2<=wg1; rvalid<=0;
            if(pop) begin
                if(empty) underflow<=1;
                else begin
                    rdata<=mem[rb[2:0]]; rvalid<=1;
                    rb<=rb+1'b1; rg<=((rb+1'b1)>>1)^(rb+1'b1);
                end
            end
        end
    end
endmodule