/// EE 4755 - Digital Design Using HDLs // /// Introductory Review // Time-stamp: <31 August 2015, 11:41:51 CDT, koppel@sky.ece.lsu.edu> ////////////////////////////////////////////////////////////////////////////// /// This Note/Demo Set /// Prerequisite // // Some familiarity with Verilog. // Familiarity with digital design. /// Goal // // Refresh your memory of Verilog, Verilog simulation, and synthesis. // Exposure to some SystemVerilog features. ////////////////////////////////////////////////////////////////////////////// /// References // /// Web page with references for this class: // http://www.ece.lsu.edu/v/ref.html /// SystemVerilog -- IEEE Std 1800-2012 // // The current Verilog language standard. // The primary Verilog reference for this course. ////////////////////////////////////////////////////////////////////////////// /// Concepts // /// Module declaration /// Variable v. Net /// Continuous assignment. /// always, initial /// Module Instantiation // Simulation // Testbenches // Synthesis // Synthesis optimization goals. // Scripting ////////////////////////////////////////////////////////////////////////////// /// Synthesis // /// Synthesis Software // // Cadence Encounter(R) RTL Compiler // // /// Elaboration [of a Top-Level Module] // // The process of generating and gathering all the HDL needed for // the top-level module. // // Start with some top-level module (shift_right2) .. // .. gather instantiated modules .. // .. and perform elaboration on them. // // For those who know what "generate statements" are: // Generate statements are executed during elaboration. /// Synthesis Target // // The kind of thing you want to make. For example, // // ASIC // FPGA. /// Inference // // Figuring out what hardware to use for a given piece of Verilog. /// Mapping [of one piece of hardware to another] // // The replacing one piece of hardware (Verilog module or primitive) // with another. /// Generic Target /// Mapped (To Technology) Target /// Area and Timing /// Design Constraints /// Scripting // read_hdl shifter.v // elaborate shift_right2 // gui_show // synthesize -to_generic -effort high // synthesize -to_mapped -effort high // report area // report timing // define_clock -name clk -period 100 // external_delay -clock clk -output 0 [find /designs/*/ports_out/ -port *] // external_delay -clock clk -input 0 [find /designs/*/ports_in/ -port *] // synthesize -to_mapped -effort high // report timing // report area `default_nettype none // Perform Two Possible Shifts: by 0 bits or by fsamt bits. // module shift_right_fixed_amt #( int fsamt = 4 ) // Fixed shift amount. ( output wire [15:0] shifted, input wire [15:0] unshifted, input wire shift ); // If shift is true shift by fsamt, otherwise don't shift. // assign shifted = shift ? unshifted >> fsamt : unshifted; endmodule module shift_right2 ( output wire [15:0] shifted, input wire [15:0] unshifted, input wire [3:0] amt ); // Module interconnections. // uwire [15:0] s8, s4, s2; shift_right_fixed_amt #(8) sm8 ( s8, unshifted, amt[3] ); shift_right_fixed_amt #(4) sm4 ( s4, s8, amt[2] ); shift_right_fixed_amt #(2) sm2 ( s2, s4, amt[1] ); shift_right_fixed_amt #(1) sm1 ( shifted, s2, amt[0] ); endmodule module shift_right3 #( int wid = 16, int awid = $clog2(wid) ) ( output wire [wid:1] shifted, input wire [wid:1] unshifted, input wire [awid-1:0] amt ); // Module interconnections. // uwire [15:0] s8, s4, s2; wire [wid:1] inter_mod[awid:0]; assign inter_mod[awid] = unshifted; assign shifted = inter_mod[0]; for ( genvar i=awid-1; i>=0; i-- ) shift_right_fixed_amt #( 1<<i ) sm ( inter_mod[i], inter_mod[i+1], amt[i] ); endmodule // cadence translate_off module shift_right1 ( output logic [15:0] shifted, input wire [15:0] unshifted, input wire [3:0] amt ); localparam int width = 16; // Old-School Verilog // always @( unshifted or amt ) begin lala; end // Verilog 2000 // always @* begin always_comb begin automatic int limit = width - amt; for ( int i=0; i<limit; i++ ) shifted[i] = unshifted[i+amt]; for ( int i=limit; i<width; i++ ) shifted[i] = 0; end endmodule // cadence translate_on ////////////////////////////////////////////////////////////////////////////// /// Testbench Code // // The code below instantiates shift_right1 and shift_right2, // provides test inputs and verifies the outputs. // // cadence translate_off module testbench(); uwire logic [15:0] sout1, sout2; logic [15:0] sin; logic [3:0] amt; shift_right1 my_sr1(sout1, sin, amt); shift_right3 my_sr2(sout2, sin, amt); // Width of shifters' input and output. // The parameter is used only by this testbench. // localparam int width = 16; // // To keep things simple the shifter modules themselves are written // with a hardcoded width of 16 bits. That's bad style since // changing the width would be tedious and error prone. (The // shifter modules could have used a parameter to specify the width // or a user-defined type.) // Provide names for the modules for use in error messages. // localparam string name[2] = '{"shift_right1", "shift_right2"}; localparam tests_per_sa = 100; localparam num_tests = width * tests_per_sa; initial begin // Count of errors for each module. // automatic int err_count[2] = '{0,0}; // // Note: The automatic qualifier is needed so that the initialization // could appear on the same line as the declaration. // Number of test inputs (stimuli). // automatic int test_count = 0; // Provide one test pattern per shift amount. // for ( int i=0; i<num_tests; i++ ) begin int shadow_sout; test_count++; sin = $random; amt = i / tests_per_sa; shadow_sout = sin >> amt; #1; // Check the output of each Module Under Test. // foreach ( name[ mut ] ) begin automatic logic [15:0] sout = mut == 0 ? sout1 : sout2; if ( shadow_sout !== sout ) begin err_count[mut]++; if ( err_count[mut] < 5 ) $display ("MUT %s wrong result for 0x%h >> %d: 0x%h != 0x%h (correct)\n", name[mut], sin, amt, sout, shadow_sout); end end end $display("Ran %d tests, %d, %d errors found.\n", test_count, err_count[0], err_count[1]); end endmodule // cadence translate_on