Skip to content

Commit

Permalink
Generalized delayed_event code
Browse files Browse the repository at this point in the history
  • Loading branch information
pConst committed May 22, 2023
1 parent 2e35510 commit 23709d8
Showing 1 changed file with 88 additions and 28 deletions.
116 changes: 88 additions & 28 deletions delayed_event.sv
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
//------------------------------------------------------------------------------
// delayed_event.sv
// published as part of https://github.com/pConst/basic_verilog
// Konstantin Pavlov, [email protected]
//------------------------------------------------------------------------------

// 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
Expand Down Expand Up @@ -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
Expand All @@ -56,31 +60,87 @@ module delayed_event #( parameter
);


logic [CNTR_WIDTH-1:0] seq_cntr = CNTR_WIDTH'(DELAY);

logic seq_cntr_is_0;
assign seq_cntr_is_0 = (seq_cntr[CNTR_WIDTH-1:0]=='0);
localparam CNTR_W = $clog2(DELAY+1);

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

0 comments on commit 23709d8

Please sign in to comment.