From 23709d82781fec42327f517056cf4bcb1411eb60 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Mon, 22 May 2023 13:41:44 +0300 Subject: [PATCH] Generalized delayed_event code --- delayed_event.sv | 114 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/delayed_event.sv b/delayed_event.sv index ce7c15e..f174316 100644 --- a/delayed_event.sv +++ b/delayed_event.sv @@ -1,14 +1,19 @@ //------------------------------------------------------------------------------ // delayed_event.sv +// published as part of https://github.com/pConst/basic_verilog // Konstantin Pavlov, pavlovconst@gmail.com //------------------------------------------------------------------------------ // INFO ------------------------------------------------------------------------ // Module generates delayed pulse one clock width -// Could be useful for initialization or sequencing some tasks -// Could be easily daisy-chained by connecting "after_event" outputs -// to the subsequent "ena" inputs // +// - Could be useful for initialization or sequencing some tasks +// - Could be easily daisy-chained by connecting "after_event" outputs +// to the subsequent "ena" inputs +// - Only one event can be triggered after every reset +// - Delay operation could be suspended by setting ena to 0 at any time + + // | // |___,___, ,___,___,___,___,___,___,___,___,___,___,___, // | , |___| , , , , , , , , , , , nrst @@ -43,8 +48,7 @@ delayed_event #( --- INSTANTIATION TEMPLATE END ---*/ module delayed_event #( parameter - DELAY = 32, - CNTR_WIDTH = $clog2(DELAY) + DELAY = 32 )( input clk, // system clock input nrst, // negative reset @@ -56,31 +60,87 @@ module delayed_event #( parameter ); -logic [CNTR_WIDTH-1:0] seq_cntr = CNTR_WIDTH'(DELAY); + localparam CNTR_W = $clog2(DELAY+1); -logic seq_cntr_is_0; -assign seq_cntr_is_0 = (seq_cntr[CNTR_WIDTH-1:0]=='0); + generate + //========================================================================== + if ( DELAY == 0 ) begin + + logic ena_rise; + edge_detect event_edge ( + .clk( clk ), + .anrst( nrst ), + .in( ena ), + .rising( ena_rise ) + ); + + assign on_event = ena_rise; + assign before_event = 1'b0; + assign after_event = 1'b1; + + //========================================================================== + end else if ( DELAY == 1 ) begin + + logic ena_d1 = 1'b0; + always_ff @(posedge clk) begin + if( ~nrst ) begin + ena_d1 <= 1'b0; + end else begin + ena_d1 <= ena; + end + end + + logic ena_rise; + edge_detect event_edge ( + .clk( clk ), + .anrst( nrst ), + .in( ena_d1 ), + .rising( ena_rise ) + ); + + logic got_ena = 1'b0; + always_ff @(posedge clk) begin + if( ~nrst ) begin + got_ena <= 1'b0; + end if( on_event ) begin + got_ena <= 1'b1; + end + end + + assign on_event = ena_rise; + assign before_event = !got_ena && !ena_rise; + assign after_event = got_ena || ena_rise; + + //========================================================================== + end else begin + + logic [CNTR_W-1:0] seq_cntr = CNTR_W'(DELAY); + + logic seq_cntr_is_0; + assign seq_cntr_is_0 = (seq_cntr[CNTR_W-1:0]=='0); + + always_ff @(posedge clk) begin + if( ~nrst) begin + seq_cntr[CNTR_W-1:0] <= CNTR_W'(DELAY); + end else begin + if( ena && ~seq_cntr_is_0 ) begin + seq_cntr[CNTR_W-1:0] <= seq_cntr[CNTR_W-1:0] - 1'b1; + end + end // nrst + end + + edge_detect event_edge ( + .clk( clk ), + .anrst( 1'b1 ), + .in( seq_cntr_is_0 ), + .rising( on_event ) + ); + + assign before_event = ~seq_cntr_is_0; + assign after_event = seq_cntr_is_0; -always_ff @(posedge clk) begin - if( ~nrst) begin - seq_cntr[CNTR_WIDTH-1:0] <= DELAY; - end else begin - if( ena && ~seq_cntr_is_0 ) begin - seq_cntr[CNTR_WIDTH-1:0] <= seq_cntr[CNTR_WIDTH-1:0] - 1'b1; end - end // nrst -end - -edge_detect cntr_edge ( - .clk( clk ), - .nrst( 1'b1 ), - .in( seq_cntr_is_0 ), - .rising( on_event ) -); - -assign before_event = ~seq_cntr_is_0; -assign after_event = seq_cntr_is_0; - + endgenerate endmodule