summaryrefslogtreecommitdiff
path: root/hdl/fifo.sv
blob: a067914f1d973cbaf7f36d13af645827004d1804 (plain) (blame)
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
module fifo
    #(  WIDTH_BITS  = 1
    ,   DEPTH_BITS  = 10
    )
    (   input   bit     clock_in
    ,   input   bit     clock_out
    ,   input   bit     reset

    ,   output  bit                     in_ready
    ,   input   bit                     in_valid
    ,   input   bit [WIDTH_BITS-1:0]    in_data

    ,   input   bit                     out_ready
    ,   output  bit                     out_valid
    ,   output  bit [WIDTH_BITS-1:0]    out_data
    );

    localparam  DEPTH   = 1<<DEPTH_BITS;

    typedef bit [WIDTH_BITS-1:0]    data_t;
    typedef bit [DEPTH_BITS-1:0]    addr_t;

    data_t  data    [DEPTH-1:0];

    addr_t  oldest, youngest;
    bit     oldest_wrap, youngest_wrap;

    addr_t  oldest_grey, youngest_grey;

    always @(posedge clock_in, posedge reset) begin
        if (reset) begin
            in_ready = 0;
            youngest = 0;
            youngest_wrap = 0;
            youngest_grey = 0;
        end else begin
            if (in_ready && in_valid) begin
                data[youngest] = in_data;
                if (++youngest == 0)
                    ++youngest_wrap;
            end

            youngest_grey = youngest ^ (youngest >> 1);

            in_ready = oldest_grey != youngest_grey || youngest_wrap == oldest_wrap;
        end
    end

    always @(posedge clock_out, posedge reset) begin
        if (reset) begin
            out_valid = 0;
            oldest = 0;
            oldest_wrap = 0;
            oldest_grey = 0;
        end else begin
            if (out_ready && out_valid) begin
                if (++oldest == 0)
                    ++oldest_wrap;
            end

            oldest_grey = oldest ^ (oldest >> 1);

            out_valid = oldest_grey != youngest_grey || youngest_wrap != oldest_wrap;
            out_data = data[oldest];
        end
    end

endmodule