mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
Updated delay module. Added block RAM implementation
This commit is contained in:
parent
d2f436d5dc
commit
b57c3a9ceb
122
delay.sv
122
delay.sv
@ -4,7 +4,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// INFO -------------------------------------------------------------------------
|
// INFO -------------------------------------------------------------------------
|
||||||
// Static Delay for arbitrary signal
|
// Static Delay for arbitrary signal, v2
|
||||||
// Another equivalent names for this module:
|
// Another equivalent names for this module:
|
||||||
// conveyor.sv
|
// conveyor.sv
|
||||||
// synchronizer.sv
|
// synchronizer.sv
|
||||||
@ -14,21 +14,26 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
// CAUTION: delay module is widely used for synchronizing signals across clock
|
// CAUTION: delay module is widely used for synchronizing signals across clock
|
||||||
// domains. To automatically exclude input data paths from timing analisys
|
// domains. When synchronizing, please exclude input data paths from timing
|
||||||
// set_false_path SDC constraint is integrated into this module. Applicable
|
// analisys manually by writing appropriate set_false_path SDC constraint
|
||||||
// only to Intel/Altera Quartus IDE. Xilinx users still should write the
|
|
||||||
// constraints manually
|
|
||||||
//
|
//
|
||||||
|
// Version 2 introduces "ALTERA_BLOCK_RAM" option to implement delays using
|
||||||
|
// block RAM. Quartus can make shifters on block RAM aautomatically
|
||||||
|
// using 'altshift_taps' internal module when "Auto Shift Register
|
||||||
|
// Replacement" option is ON
|
||||||
|
|
||||||
|
|
||||||
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
||||||
|
|
||||||
delay #(
|
delay #(
|
||||||
.LENGTH( 2 )
|
.LENGTH( 2 ),
|
||||||
|
.WIDTH( 1 ),
|
||||||
|
.TYPE( "CELLS" )
|
||||||
) S1 (
|
) S1 (
|
||||||
.clk( clk ),
|
.clk( clk ),
|
||||||
.nrst( 1'b1 ),
|
.nrst( 1'b1 ),
|
||||||
.ena( 1'b1 ),
|
.ena( 1'b1 ),
|
||||||
|
|
||||||
.in( ),
|
.in( ),
|
||||||
.out( )
|
.out( )
|
||||||
);
|
);
|
||||||
@ -37,45 +42,110 @@ delay #(
|
|||||||
|
|
||||||
|
|
||||||
module delay #( parameter
|
module delay #( parameter
|
||||||
LENGTH = 2 // delay/synchronizer chain length
|
LENGTH = 2, // delay/synchronizer chain length
|
||||||
// default length for synchronizer chain is 2
|
WIDTH = 1, // signal width
|
||||||
|
TYPE = "CELLS", // "ALTERA_BLOCK_RAM" infers block ram fifo
|
||||||
|
// all other values infer registers
|
||||||
|
|
||||||
|
CNTR_W = $clog2(LENGTH)
|
||||||
)(
|
)(
|
||||||
input clk,
|
input clk,
|
||||||
input nrst,
|
input nrst,
|
||||||
input ena,
|
input ena,
|
||||||
input in,
|
|
||||||
output out
|
input [WIDTH-1:0] in,
|
||||||
|
output [WIDTH-1:0] out
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
|
|
||||||
if ( LENGTH == 0 ) begin
|
if ( LENGTH == 0 ) begin
|
||||||
assign out = in;
|
|
||||||
|
assign out[WIDTH-1:0] = in[WIDTH-1:0];
|
||||||
|
|
||||||
end else if( LENGTH == 1 ) begin
|
end else if( LENGTH == 1 ) begin
|
||||||
|
|
||||||
logic data = 0;
|
logic [WIDTH-1:0] data = '0;
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (~nrst) begin
|
if( ~nrst ) begin
|
||||||
data <= 0;
|
data[WIDTH-1:0] <= '0;
|
||||||
end else if (ena) begin
|
end else if( ena ) begin
|
||||||
data <= in;
|
data[WIDTH-1:0] <= in[WIDTH-1:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assign out = data;
|
assign out[WIDTH-1:0] = data[WIDTH-1:0];
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
|
if( TYPE=="ALTERA_BLOCK_RAM" && LENGTH>=4 ) begin
|
||||||
|
|
||||||
logic [LENGTH:1] data = 0;
|
logic [CNTR_W-1:0] delay_cntr = '0;
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if (~nrst) begin
|
logic fifo_output_ena;
|
||||||
data[LENGTH:1] <= 0;
|
assign fifo_output_ena = (delay_cntr[CNTR_W-1:0] == LENGTH);
|
||||||
end else if (ena) begin
|
|
||||||
data[LENGTH:1] <= {data[LENGTH-1:1],in};
|
always_ff @(posedge clk) begin
|
||||||
|
if( ~nrst ) begin
|
||||||
|
delay_cntr[CNTR_W-1:0] <= '0;
|
||||||
|
end else begin
|
||||||
|
if( ena && ~fifo_output_ena) begin
|
||||||
|
delay_cntr[CNTR_W-1:0] <= delay_cntr[CNTR_W-1:0] + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
assign out = data[LENGTH];
|
|
||||||
|
|
||||||
end // if
|
logic [WIDTH-1:0] fifo_out;
|
||||||
|
scfifo #(
|
||||||
|
.LPM_WIDTH( WIDTH ),
|
||||||
|
.LPM_NUMWORDS( LENGTH ), // must be at least 4
|
||||||
|
.LPM_WIDTHU( CNTR_W ),
|
||||||
|
.LPM_SHOWAHEAD( "ON" ),
|
||||||
|
.UNDERFLOW_CHECKING( "ON" ),
|
||||||
|
.OVERFLOW_CHECKING( "ON" ),
|
||||||
|
.ALMOST_FULL_VALUE( 0 ),
|
||||||
|
.ALMOST_EMPTY_VALUE( 0 ),
|
||||||
|
.ENABLE_ECC( "FALSE" ),
|
||||||
|
.ALLOW_RWCYCLE_WHEN_FULL( "ON" ),
|
||||||
|
.USE_EAB( "ON" ),
|
||||||
|
.MAXIMIZE_SPEED( 5 ),
|
||||||
|
.DEVICE_FAMILY( "Cyclone V" )
|
||||||
|
) internal_fifo (
|
||||||
|
.clock( clk ),
|
||||||
|
.aclr( 1'b0 ),
|
||||||
|
.sclr( ~nrst ),
|
||||||
|
|
||||||
|
.data( in[WIDTH-1:0] ),
|
||||||
|
.wrreq( ena ),
|
||||||
|
.rdreq( ena && fifo_output_ena ),
|
||||||
|
|
||||||
|
.q( fifo_out[WIDTH-1:0] ),
|
||||||
|
.empty( ),
|
||||||
|
.full( ),
|
||||||
|
.almost_full( ),
|
||||||
|
.almost_empty( ),
|
||||||
|
.usedw( ),
|
||||||
|
.eccstatus( )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign out[WIDTH-1:0] = (fifo_output_ena)?(fifo_out[WIDTH-1:0]):('0);
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
logic [LENGTH:1][WIDTH-1:0] data = '0;
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
integer i;
|
||||||
|
if( ~nrst ) begin
|
||||||
|
data <= '0;
|
||||||
|
end else if( ena ) begin
|
||||||
|
for(i=LENGTH-1; i>0; i--) begin
|
||||||
|
data[i+1][WIDTH-1:0] <= data[i][WIDTH-1:0];
|
||||||
|
end
|
||||||
|
data[1][WIDTH-1:0] <= in[WIDTH-1:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign out[WIDTH-1:0] = data[LENGTH][WIDTH-1:0];
|
||||||
|
|
||||||
|
end // if TYPE
|
||||||
|
end // if LENGTH
|
||||||
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
120
delay_tb.sv
Normal file
120
delay_tb.sv
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// delay_tb.sv
|
||||||
|
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// INFO ------------------------------------------------------------------------
|
||||||
|
// testbench for delay_tb.sv module
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module delay_tb();
|
||||||
|
|
||||||
|
logic clk200;
|
||||||
|
initial begin
|
||||||
|
#0 clk200 = 1'b1;
|
||||||
|
forever
|
||||||
|
#2.5 clk200 = ~clk200;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic clk400;
|
||||||
|
initial begin
|
||||||
|
#0 clk400 = 1'b1;
|
||||||
|
forever
|
||||||
|
#1.25 clk400 = ~clk400;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic clk33;
|
||||||
|
initial begin
|
||||||
|
#0 clk33 = 1'b1;
|
||||||
|
forever
|
||||||
|
#15.151 clk33 = ~clk33;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic rst;
|
||||||
|
initial begin
|
||||||
|
#0 rst = 1'b0;
|
||||||
|
#10.2 rst = 1'b1;
|
||||||
|
#5 rst = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic nrst;
|
||||||
|
assign nrst = ~rst;
|
||||||
|
|
||||||
|
logic rst_once;
|
||||||
|
initial begin
|
||||||
|
#0 rst_once = 1'b0;
|
||||||
|
#10.2 rst_once = 1'b1;
|
||||||
|
#5 rst_once = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic nrst_once;
|
||||||
|
assign nrst_once = ~rst_once;
|
||||||
|
|
||||||
|
logic [31:0] DerivedClocks;
|
||||||
|
clk_divider #(
|
||||||
|
.WIDTH( 32 )
|
||||||
|
) cd1 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( nrst_once ),
|
||||||
|
.ena( 1'b1 ),
|
||||||
|
.out( DerivedClocks[31:0] )
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [31:0] E_DerivedClocks;
|
||||||
|
edge_detect ed1[31:0] (
|
||||||
|
.clk( {32{clk200}} ),
|
||||||
|
.nrst( {32{nrst_once}} ),
|
||||||
|
.in( DerivedClocks[31:0] ),
|
||||||
|
.rising( E_DerivedClocks[31:0] ),
|
||||||
|
.falling( ),
|
||||||
|
.both( )
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [31:0] RandomNumber1;
|
||||||
|
c_rand rng1 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.rst( 1'b0 ),
|
||||||
|
.reseed( rst_once ),
|
||||||
|
.seed_val( DerivedClocks[31:0] ^ (DerivedClocks[31:0] << 1) ),
|
||||||
|
.out( RandomNumber1[15:0] )
|
||||||
|
);
|
||||||
|
|
||||||
|
c_rand rng2 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.rst( 1'b0 ),
|
||||||
|
.reseed( rst_once ),
|
||||||
|
.seed_val( DerivedClocks[31:0] ^ (DerivedClocks[31:0] << 2) ),
|
||||||
|
.out( RandomNumber1[31:16] )
|
||||||
|
);
|
||||||
|
|
||||||
|
// Module under test ==========================================================
|
||||||
|
|
||||||
|
delay #(
|
||||||
|
.LENGTH( 10 ),
|
||||||
|
.WIDTH( 8 )
|
||||||
|
//.TYPE( "CELLS" )
|
||||||
|
) d1 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( ~E_DerivedClocks[8] ),
|
||||||
|
.ena( 1'b1 ),
|
||||||
|
|
||||||
|
.in( RandomNumber1[7:0] ),
|
||||||
|
.out( )
|
||||||
|
);
|
||||||
|
|
||||||
|
delay #(
|
||||||
|
.LENGTH( 10 ),
|
||||||
|
.WIDTH( 8 ),
|
||||||
|
.TYPE( "ALTERA_BLOCK_RAM" )
|
||||||
|
) d2 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( ~E_DerivedClocks[8] ),
|
||||||
|
.ena( 1'b1 ),
|
||||||
|
|
||||||
|
.in( RandomNumber1[7:0] ),
|
||||||
|
.out( )
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
Loading…
x
Reference in New Issue
Block a user