From 24312652ab2c0a1cb35dd0d57827cef1069fd0d8 Mon Sep 17 00:00:00 2001 From: "Konstantin Pavlov (fm)" Date: Tue, 4 Dec 2018 12:33:26 +0300 Subject: [PATCH] Combinational implementation of EdgeDetector with zero latency --- ClkDivider.v => 00_obsolete/ClkDivider.v | 0 00_obsolete/EdgeDetect.sv | 57 ++++++++++++++++ EdgeDetect.v => 00_obsolete/EdgeDetect.v | 0 EdgeDetect.sv | 53 +++++++-------- EdgeDetect_tb.sv | 84 ++++++++++++++++++++++++ main_tb.v | 2 +- 6 files changed, 167 insertions(+), 29 deletions(-) rename ClkDivider.v => 00_obsolete/ClkDivider.v (100%) create mode 100644 00_obsolete/EdgeDetect.sv rename EdgeDetect.v => 00_obsolete/EdgeDetect.v (100%) create mode 100644 EdgeDetect_tb.sv diff --git a/ClkDivider.v b/00_obsolete/ClkDivider.v similarity index 100% rename from ClkDivider.v rename to 00_obsolete/ClkDivider.v diff --git a/00_obsolete/EdgeDetect.sv b/00_obsolete/EdgeDetect.sv new file mode 100644 index 0000000..5b725bc --- /dev/null +++ b/00_obsolete/EdgeDetect.sv @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// EdgeDetect.sv +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Variable width edge detector +// Features one tick propagation time + + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +EdgeDetect #( + .WIDTH( 32 ) +) ED1 ( + .clk( clk ), + .nrst( 1'b1 ), + .in( ), + .rising( ), + .falling( ), + .both( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module EdgeDetect #( + WIDTH = 1 +)( + input clk, + input nrst, + + input [(WIDTH-1):0] in, + output logic [(WIDTH-1):0] rising = 0, + output logic [(WIDTH-1):0] falling = 0, + output [(WIDTH-1):0] both +); + + +logic [(WIDTH-1):0] in_prev = 0; + +always_ff @(posedge clk) begin + if ( ~nrst ) begin + in_prev <= 0; + rising <= 0; + falling <= 0; + end + else begin + in_prev <= in; + rising[(WIDTH-1):0] <= in[(WIDTH-1):0] & ~in_prev[(WIDTH-1):0]; + falling[(WIDTH-1):0] <= ~in[(WIDTH-1):0] & in_prev[(WIDTH-1):0]; + end +end + +assign both[(WIDTH-1):0] = rising[(WIDTH-1):0] | falling[(WIDTH-1):0]; + +endmodule diff --git a/EdgeDetect.v b/00_obsolete/EdgeDetect.v similarity index 100% rename from EdgeDetect.v rename to 00_obsolete/EdgeDetect.v diff --git a/EdgeDetect.sv b/EdgeDetect.sv index 5b725bc..07b12a0 100644 --- a/EdgeDetect.sv +++ b/EdgeDetect.sv @@ -4,19 +4,21 @@ //------------------------------------------------------------------------------ // INFO ------------------------------------------------------------------------ -// Variable width edge detector -// Features one tick propagation time +// Edge detector, ver.2 +// Combinational implementation (zero ticks delay) +// +// In case when "in" port has toggle rate 100% (changes every clock period) +// "rising" and "falling" outputs will completely replicate input +// "both" output will be always active in this case /* --- INSTANTIATION TEMPLATE BEGIN --- -EdgeDetect #( - .WIDTH( 32 ) -) ED1 ( - .clk( clk ), - .nrst( 1'b1 ), - .in( ), - .rising( ), +EdgeDetect ED1[31:0] ( + .clk( {32{clk}} ), + .nrst( {32{1'b1}} ), + .in( in[31:0] ), + .rising( out[31:0] ), .falling( ), .both( ) ); @@ -24,34 +26,29 @@ EdgeDetect #( --- INSTANTIATION TEMPLATE END ---*/ -module EdgeDetect #( - WIDTH = 1 -)( +module EdgeDetect( input clk, input nrst, - input [(WIDTH-1):0] in, - output logic [(WIDTH-1):0] rising = 0, - output logic [(WIDTH-1):0] falling = 0, - output [(WIDTH-1):0] both + input in, + output logic rising, + output logic falling, + output logic both ); - -logic [(WIDTH-1):0] in_prev = 0; - +logic in_d = 0; always_ff @(posedge clk) begin if ( ~nrst ) begin - in_prev <= 0; - rising <= 0; - falling <= 0; - end - else begin - in_prev <= in; - rising[(WIDTH-1):0] <= in[(WIDTH-1):0] & ~in_prev[(WIDTH-1):0]; - falling[(WIDTH-1):0] <= ~in[(WIDTH-1):0] & in_prev[(WIDTH-1):0]; + in_d <= 0; + end else begin + in_d <= in; end end -assign both[(WIDTH-1):0] = rising[(WIDTH-1):0] | falling[(WIDTH-1):0]; +always_comb begin + rising = nrst && (in && ~in_d); + falling = nrst && (~in && in_d); + both = nrst && (rising || falling); +end endmodule diff --git a/EdgeDetect_tb.sv b/EdgeDetect_tb.sv new file mode 100644 index 0000000..31006f8 --- /dev/null +++ b/EdgeDetect_tb.sv @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// EdgeDetect_tb.sv +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// + +`timescale 1ns / 1ps + +module EdgeDetect_tb(); + +logic clk200; +initial begin + #0 clk200 = 1; + forever + #2.5 clk200 = ~clk200; +end + +logic rst; +initial begin + #10.2 rst = 1; + #5 rst = 0; + //#10000; + forever begin + #9985 rst = ~rst; + #5 rst = ~rst; + end +end + +logic nrst; +assign nrst = ~rst; + +logic rst_once; +initial begin // initializing non-X data before PLL starts + #10.2 rst_once = 1; + #5 rst_once = 0; +end +initial begin + #510.2 rst_once = 1; // PLL starts at 500ns, clock appears, so doing the reset for modules + #5 rst_once = 0; +end + +logic nrst_once; +assign nrst_once = ~rst_once; + +logic [31:0] DerivedClocks; +ClkDivider #( + .WIDTH( 32 ) +) CD1 ( + .clk( clk200 ), + .nrst( nrst_once ), + .out( DerivedClocks[31:0] ) +); + +logic [15:0] RandomNumber1; +c_rand RNG1 ( + .clk( clk200 ), + .rst( rst_once ), + .reseed( 1'b0 ), + .seed_val( DerivedClocks[31:0] ), + .out( RandomNumber1[15:0] ) +); + +logic start; +initial begin + #0 start = 1'b0; + #100.2 start = 1'b1; + #5 start = 1'b0; +end + +// Module under test ========================================================== + +EdgeDetect ED1[15:0] ( + .clk( {16{clk200}} ), + .nrst( {16{nrst_once}} ), + .in( RandomNumber1[15:0] ), + .rising( ), + .falling( ), + .both( ) +); + + +endmodule diff --git a/main_tb.v b/main_tb.v index 3106034..78728fe 100644 --- a/main_tb.v +++ b/main_tb.v @@ -15,7 +15,7 @@ reg clk200; initial begin #0 clk200 = 1; forever - + #2.5 clk200 = ~clk200; end reg rst;