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

Subversion Repositories cdc_ufifo

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/cdc_ufifo/trunk/prim_dffe.v
0,0 → 1,26
module prim_dffe(d, clk, ena, clrn, prn, q);
parameter lpm_width = 1;
parameter lpm_avalue = 0;
 
input clk, ena;
input clrn,prn;
input [lpm_width-1 : 0] d;
output [lpm_width-1 : 0] q;
 
tri1 clrn,prn;
wire i_clr, i_prn;
buf(i_clr, clrn);
buf(i_prn, prn);
 
reg [lpm_width-1 : 0] q;
 
always @(posedge clk or negedge i_clr or negedge i_prn) begin
if (!i_clr)
q <= {lpm_width{1'b0}};
else if (!i_prn)
q <= {lpm_width{1'b1}};
else if (ena)
q <= d;
end
 
endmodule
/cdc_ufifo/trunk/gray2bin.v
0,0 → 1,13
module gray2bin (bin, gray);
 
parameter lpm_size = 4;
 
output [lpm_size-1:0] bin;
input [lpm_size-1:0] gray;
reg [lpm_size-1:0] bin;
 
integer i;
always @(gray)
for (i=0; i<lpm_size; i=i+1)
bin[i] = ^(gray>>i);
endmodule
/cdc_ufifo/trunk/delay_pulse_ff.v
0,0 → 1,57
/*
provides delay on both edges of pulse
1st positive, and 2nd stage negative
*/
module delay_pulse_ff(d
, clock, enable, clrn
, q
);
parameter delay = 1;
parameter lpm_width =1;
 
input wire[lpm_width-1:0] d;
output wire[lpm_width-1:0] q;
input wire clock, enable, clrn;
 
generate
if (delay == 0) begin
assign q = d;
end
else begin
reg [lpm_width-1:0] qt_pos [1:delay];
reg [lpm_width-1:0] qt_neg [1:delay];
integer k;
 
always @(posedge clock or negedge clrn) begin
if (~clrn)
qt_pos[1] <= 0;
else if (enable)
qt_pos[1] <= d;
 
for (k = 1; k < delay; k=k+1) begin : DelayRiseInstance
if (~clrn)
qt_pos[k+1] <= 0;
else if (enable)
qt_pos[k+1] <= qt_neg[k];
end
end
 
always @(negedge clock or negedge clrn) begin
if (~clrn)
qt_neg[1] <= 0;
else if (enable)
qt_neg[1] <= qt_pos[1];
 
for (k = 1; k < delay; k=k+1) begin : DelayFallInstance
if (~clrn)
qt_neg[k+1] <= 0;
else if (enable)
qt_neg[k+1] <= qt_pos[k];
end
end
 
assign q = qt_neg[delay];
end
endgenerate
 
endmodule
/cdc_ufifo/trunk/StdUtils.vh
0,0 → 1,11
/*
standart utils verilog include
*/
 
function integer clog2 (input integer num); // this function calculates ceil(log2(num))
begin
num = num - 1; // without this statement clog2(32) will be 6 but must be 5
for (clog2 = 0; num > 0; clog2 = clog2 + 1)
num = num >> 1;
end
endfunction
/cdc_ufifo/trunk/cdc_ufifo.sv
0,0 → 1,129
/*
Clock Domain Crossing micro FIFO
Copyright (C) 2010 Alexandr Litjagin (aka AlexRayne) AlexRaynePE196@lavabit.com
AlexRaynePE196@hotbox.ru
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
 
/*
cdc_ufifo generate an minimalist fifo. it can be 4 cells minimum.
by default used implementation without ram only standart cells used
, and it can be selected if need. most slowest stage is the output multiplexor.
shadowed outputs - provide an registes after multiplexer to remove data unsynchronized
changes from outputs when skiped some cycles.
 
parameters:
shadowed - "FALSE|TRUE" is buffered output or not
realization - "RAM|REGS" - style of buffer implemented
="RAM" - default implementation of ram
="REGS" (default) - force use registers set for buffer
*/
module cdc_ufifo( d, in_clk, denable, reset
, q, q_clk, qenable, ready
);
 
parameter lpm_width = 8;
parameter lpm_depth = 2;
parameter shadowed = "FALSE";
parameter realization = "REGS";
 
`include "StdUtils.vh"
 
`define lpm_size (lpm_depth*2)
`define ptr_size clog2(`lpm_size)
 
input in_clk, denable, q_clk, qenable, reset;
input [lpm_width-1:0] d;
output logic [lpm_width-1:0] q;
output ready;
 
typedef logic [lpm_width-1:0] data_wire;
typedef logic [`ptr_size-1:0] buf_ptr;
 
data_wire bufer[0:`lpm_size-1];
buf_ptr rd_node_ptr;
buf_ptr rd_next_ptr;
buf_ptr wr_node_ptr;
buf_ptr wr_next_ptr;
 
buf_ptr rd_node_grey;
buf_ptr rd_next_grey;
buf_ptr wr_node_grey;
buf_ptr wr_next_grey;
 
assign rd_node_ptr = rd_node_grey;
assign rd_next_ptr = rd_next_grey;
assign wr_node_ptr = wr_node_grey;
assign wr_next_ptr = wr_next_grey;
 
logic wr_enable;
logic rd_enable;
 
graycntr WrSwitch(.clk(in_clk), .inc(wr_enable), .rst_n(~reset), .gray(wr_node_grey), .gnext(wr_next_grey));
defparam WrSwitch.lpm_width = `ptr_size;
graycntr RdSwitch(.clk(q_clk), .inc(rd_enable), .rst_n(~reset), .gray(rd_node_grey), .gnext(rd_next_grey));
defparam RdSwitch.lpm_width = `ptr_size;
 
buf_ptr rd_cdc_grey;
buf_ptr wr_cdc_grey;
 
delay_pulse_ff cdc_stamp_wr(.clock(q_clk), .d(wr_node_grey), .q(wr_cdc_grey), .enable(1'b1), .clrn(~reset));
defparam cdc_stamp_wr.delay = 1;//lpm_depth;
defparam cdc_stamp_wr.lpm_width = $bits(wr_node_grey);
 
delay_pulse_ff cdc_stamp_rd(.clock(in_clk), .d(rd_node_grey), .q(rd_cdc_grey), .enable(1'b1), .clrn(~reset));
defparam cdc_stamp_rd.delay = 1;//(lpm_depth /2);
defparam cdc_stamp_rd.lpm_width = $bits(rd_node_grey);
 
 
logic data_avail;
logic data_free;
assign data_avail = (wr_cdc_grey != rd_node_grey);
assign data_free = (rd_cdc_grey != wr_next_grey);
assign wr_enable = denable & data_free;
assign rd_enable = data_avail;
 
wire [lpm_width-1:0] selQ;
 
genvar i;
generate
if (realization == "REGS")
for (i = 0; i < `lpm_size; i++) begin : buffer_node
wire WrCellSel = (wr_node_ptr == i);
prim_dffe buf_data( .clk(in_clk), .d(d), .ena( wr_enable & WrCellSel ), .q( bufer[i] ), .clrn(~reset), .prn(1'b1) );
defparam buf_data.lpm_width = lpm_width;
assign selQ = (rd_node_ptr == i)? bufer[i] : {lpm_width{1'bz}};
end
else begin
always @(posedge in_clk) begin : bufer_latch
if (wr_enable)
bufer[wr_node_ptr] <= d;
end
 
assign selQ = bufer[rd_node_ptr];
end
endgenerate
 
 
assign ready = rd_enable;
 
generate if (shadowed == "TRUE") begin
always @(posedge q_clk) if (rd_enable) q <= selQ;
end
else
assign q = selQ;
endgenerate
 
 
endmodule
/cdc_ufifo/trunk/graycntr.v
0,0 → 1,24
module graycntr (gray, clk, inc, rst_n, gnext);
 
parameter lpm_width = 4;
 
output [lpm_width-1:0] gray;
output [lpm_width-1:0] gnext;
input clk, inc, rst_n;
reg [lpm_width-1:0] gnext, gray, bnext, bin;
 
integer i;
always @(posedge clk or negedge rst_n)
if (!rst_n)
gray <= 0;
else if (inc)
gray <= gnext;
 
always @(gray or inc) begin
for (i=0; i<lpm_width; i=i+1)
bin[i] = ^(gray>>i);
bnext = bin+1'b1;
gnext = (bnext>>1) ^ bnext;
end
 
endmodule

powered by: WebSVN 2.1.0

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