OpenCores
URL https://opencores.org/ocsvn/cdc_ufifo/cdc_ufifo/trunk

Subversion Repositories cdc_ufifo

[/] [cdc_ufifo/] [trunk/] [cdc_ufifo.sv] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 AlexRayne
/*
2
    Clock Domain Crossing micro FIFO
3
    Copyright (C) 2010  Alexandr Litjagin (aka AlexRayne) AlexRaynePE196@lavabit.com
4
                                                          AlexRaynePE196@hotbox.ru
5
 
6
   Licensed under the Apache License, Version 2.0 (the "License");
7
   you may not use this file except in compliance with the License.
8
   You may obtain a copy of the License at
9
 
10
       http://www.apache.org/licenses/LICENSE-2.0
11
 
12
   Unless required by applicable law or agreed to in writing, software
13
   distributed under the License is distributed on an "AS IS" BASIS,
14
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
   See the License for the specific language governing permissions and
16
   limitations under the License.
17
*/
18
 
19
/*
20
    cdc_ufifo generate an minimalist fifo. it can be 4 cells minimum.
21
    by default used implementation without ram only standart cells used
22
    , and it can be selected if need. most slowest stage is the output multiplexor.
23
    shadowed outputs - provide an registes after multiplexer to remove data unsynchronized
24
    changes from outputs when skiped some cycles.
25
 
26
    parameters:
27
        shadowed - "FALSE|TRUE" is buffered output or not
28
        realization - "RAM|REGS" - style of buffer implemented
29
            ="RAM" - default implementation of ram
30
            ="REGS" (default) - force use registers set for buffer
31
*/
32
module cdc_ufifo( d, in_clk, denable, reset
33
                    , q, q_clk, qenable, ready
34
                    );
35
 
36
parameter lpm_width = 8;
37
parameter lpm_depth = 2;
38
parameter shadowed = "FALSE";
39
parameter realization = "REGS";
40
 
41
`include "StdUtils.vh"
42
 
43
`define lpm_size (lpm_depth*2)
44
`define ptr_size clog2(`lpm_size)
45
 
46
input in_clk, denable, q_clk, qenable, reset;
47
input [lpm_width-1:0] d;
48
output logic [lpm_width-1:0] q;
49
output ready;
50
 
51
typedef logic [lpm_width-1:0] data_wire;
52
typedef logic [`ptr_size-1:0] buf_ptr;
53
 
54
data_wire bufer[0:`lpm_size-1];
55
buf_ptr rd_node_ptr;
56
buf_ptr rd_next_ptr;
57
buf_ptr wr_node_ptr;
58
buf_ptr wr_next_ptr;
59
 
60
buf_ptr rd_node_grey;
61
buf_ptr rd_next_grey;
62
buf_ptr wr_node_grey;
63
buf_ptr wr_next_grey;
64
 
65
assign rd_node_ptr = rd_node_grey;
66
assign rd_next_ptr = rd_next_grey;
67
assign wr_node_ptr = wr_node_grey;
68
assign wr_next_ptr = wr_next_grey;
69
 
70
logic wr_enable;
71
logic rd_enable;
72
 
73
graycntr WrSwitch(.clk(in_clk), .inc(wr_enable), .rst_n(~reset), .gray(wr_node_grey), .gnext(wr_next_grey));
74
    defparam WrSwitch.lpm_width = `ptr_size;
75
graycntr RdSwitch(.clk(q_clk), .inc(rd_enable), .rst_n(~reset), .gray(rd_node_grey), .gnext(rd_next_grey));
76
    defparam RdSwitch.lpm_width = `ptr_size;
77
 
78
buf_ptr rd_cdc_grey;
79
buf_ptr wr_cdc_grey;
80
 
81
delay_pulse_ff cdc_stamp_wr(.clock(q_clk), .d(wr_node_grey), .q(wr_cdc_grey), .enable(1'b1), .clrn(~reset));
82
    defparam cdc_stamp_wr.delay = 1;//lpm_depth;
83
    defparam cdc_stamp_wr.lpm_width = $bits(wr_node_grey);
84
 
85
delay_pulse_ff cdc_stamp_rd(.clock(in_clk), .d(rd_node_grey), .q(rd_cdc_grey), .enable(1'b1), .clrn(~reset));
86
    defparam cdc_stamp_rd.delay = 1;//(lpm_depth /2);
87
    defparam cdc_stamp_rd.lpm_width = $bits(rd_node_grey);
88
 
89
 
90
logic data_avail;
91
logic data_free;
92
assign data_avail = (wr_cdc_grey != rd_node_grey);
93
assign data_free = (rd_cdc_grey != wr_next_grey);
94
assign wr_enable = denable & data_free;
95
assign rd_enable = data_avail;
96
 
97
wire [lpm_width-1:0] selQ;
98
 
99
genvar i;
100
generate
101
    if (realization == "REGS")
102
    for (i = 0; i < `lpm_size; i++) begin : buffer_node
103
        wire WrCellSel = (wr_node_ptr == i);
104
        prim_dffe buf_data( .clk(in_clk), .d(d), .ena( wr_enable & WrCellSel ), .q( bufer[i] ), .clrn(~reset), .prn(1'b1) );
105
            defparam buf_data.lpm_width = lpm_width;
106
        assign selQ = (rd_node_ptr == i)? bufer[i] : {lpm_width{1'bz}};
107
    end
108
    else begin
109
        always @(posedge in_clk) begin : bufer_latch
110
            if (wr_enable)
111
                bufer[wr_node_ptr] <= d;
112
        end
113
 
114
        assign selQ = bufer[rd_node_ptr];
115
    end
116
endgenerate
117
 
118
 
119
assign ready = rd_enable;
120
 
121
generate if (shadowed == "TRUE") begin
122
        always @(posedge q_clk) if (rd_enable) q <= selQ;
123
    end
124
    else
125
        assign q = selQ;
126
endgenerate
127
 
128
 
129
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.