From 1efbd7c243bec1e35b55a7ebe5ac67fa271ca952 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Fri, 9 Jul 2021 17:24:20 +0300 Subject: [PATCH] Added soft_latch module and testbench --- soft_latch.sv | 88 ++++++++++++++++++++++++++++ soft_latch_tb.sv | 148 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 soft_latch.sv create mode 100644 soft_latch_tb.sv diff --git a/soft_latch.sv b/soft_latch.sv new file mode 100644 index 0000000..65fb5fe --- /dev/null +++ b/soft_latch.sv @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +// soft_latch.sv +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// "Software" latch, aka combinational data hold circuit +// +// Features combinational data latching and combinational resetting +// Zero latency for setting and resetting data +// No hardware latches inferred by means of this circuit +// + +// | | +---+ | | | | | | latch, this module input +// | | | | | | | | | | +// +------------+ +--------------------------------+ +// | | | | | | | | | | +// +----------------------------+ +----------------+ +// | | | | | | | | | | +// | | | | | | +---+ | | nrst, this module input +// | | | | | | | | | | +// +-------------------------------------------------+ +// }{A }{B }{C }{D }{E }{F }{G }{H }{J }{ in, this module data input +// +-------------------------------------------------+ +// | | | | | | | | | | +// | | | +---------------+ | | standard unblocking assignment +// | | | { C | C | C | C } | | +// +----------------+ | | | +----------------+ +// | | | | | | | | | | +// | | +---------------+ | | | out, this module data output +// | | { C | C | C | C } | | | +// +------------+ | | | +--------------------+ +// | | | | | | | | | | +// | | | | | | | | | | + + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +soft_latch #( + .WIDTH( 16 ) +) SL1 ( + .clk( clk ), + .nrst( 1'b1 ), + .latch( ), + .in( ), + .out( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module soft_latch #( parameter + WIDTH = 1 // data width +)( + input clk, // clock + input nrst, // inverted reset + + input latch, // latch strobe + input [WIDTH-1:0] in, // data in + output logic [WIDTH-1:0] out // data out +); + +logic [WIDTH-1:0] in_buf = '0; + +// buffering input data +always_ff @(posedge clk) begin + if( ~nrst ) begin + in_buf[WIDTH-1:0] <= '0; + end else if( latch ) begin + in_buf[WIDTH-1:0] <= in[WIDTH-1:0]; + end +end + +// mixing combinational and buffered data to the output +always_comb begin + if( ~nrst ) begin + out[WIDTH-1:0] <= '0; + end else if( latch ) begin + out[WIDTH-1:0] <= in[WIDTH-1:0]; + end else begin + out[WIDTH-1:0] <= in_buf[WIDTH-1:0]; + end + + +end + +endmodule + diff --git a/soft_latch_tb.sv b/soft_latch_tb.sv new file mode 100644 index 0000000..0009131 --- /dev/null +++ b/soft_latch_tb.sv @@ -0,0 +1,148 @@ +//------------------------------------------------------------------------------ +// soft_latch_tb.sv +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// testbench for soft_latch.sv module +// + +`timescale 1ns / 1ps + +module soft_latch_tb(); + +logic clk200; +initial begin + #0 clk200 = 1'b0; + forever + #2.5 clk200 = ~clk200; +end + +// external device "asynchronous" clock +logic clk33; +initial begin + #0 clk33 = 1'b0; + forever + #15.151 clk33 = ~clk33; +end + +logic rst; +initial begin + #0 rst = 1'b0; + #10.2 rst = 1'b1; + #5 rst = 1'b0; + //#10000; + forever begin + #9985 rst = ~rst; + #5 rst = ~rst; + end +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 [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 start = 1'b1; + #20 start = 1'b0; +end + +// Module under test ========================================================== + +logic set; +assign set = &RandomNumber1[14:12]; + +logic ret; +assign ret = &RandomNumber1[11:9]; + +// verilog hardvare latch +logic [15:0] data1; +always_latch begin + if( ret ) begin + data1[15:0] <= '0; + end else if( set ) begin + data1[15:0] <= RandomNumber1[15:0]; + end +end + +// soft_latch prototype +logic [15:0] data2; +set_reset_comb SR [15:0] ( + .clk( {16{clk200}} ), + .nrst( {16{1'b1}} ), + .s( {16{set}} & RandomNumber1[15:0] ), //set + .r( ({16{set}} & ~RandomNumber1[15:0]) | {16{ret}} ), //rst + .q( data2[15:0] ), + .nq( ) +); + +// genuine soft_latch instance +logic [15:0] data3; +soft_latch #( + .WIDTH( 16 ) +) SL1 ( + .clk( clk200 ), + .nrst( ~ret ), + .latch( set ), + .in( RandomNumber1[15:0] ), + .out( data3[15:0] ) +); + +//============================================================================== + +logic outputs_equal; +assign outputs_equal = ( data1[15:0] == data2[15:0] ) && + ( data1[15:0] == data3[15:0] ); + +logic success = 1'b1; +always_ff @(posedge clk200) begin + if( ~nrst ) begin + success <= 1'b1; + end else begin + if( ~outputs_equal ) begin + success <= 1'b0; + end + end +end + +endmodule