//////////////////////////////////////////////////////////////////////////////// // /// LSU EE 4755 Fall 2019 Homework 2 // /// Assignment https://www.ece.lsu.edu/koppel/v/2019/hw02.pdf /// Instructions: // // (1) Find the undergraduate workstation laboratory, room 2241 Patrick // F. Taylor Hall. Machines to use are in the back. // // (2) Locate your account. If you did not get an account please // E-mail: koppel@ece.lsu.edu // // (3) Log in to a Linux workstation. // // (4) If you haven't already, follow the account setup instructions here: // https://www.ece.lsu.edu/koppel/v/proc.html // // (5) Copy this assignment, local path name // /home/faculty/koppel/pub/ee4755/hw/2019/hw02 // to a directory ~/hw02 in your class account. (~ is your home // directory.) Use this file for your solution. /// BE SURE THAT YOUR FILE IS CORRECTLY NAMED AND IN THE RIGHT PLACE. // // (6) Find the problems in this file and solve them. // // Your entire solution should be in this file. // // Do not change module names. // // (7) Your solution will automatically be copied from your account by // the TA-bot. /// Additional Resources // // Verilog Documentation // The Verilog Standard // https://ieeexplore.ieee.org/document/8299595/ // Introductory Treatment (Warning: Does not include SystemVerilog) // Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed. // // Account Setup and Emacs (Text Editor) Instructions // https://www.ece.lsu.edu/koppel/v/proc.html // To learn Emacs look for Emacs tutorial. // // Unix Help (Very outdated. Alternatives welcome.) // https://www.ece.lsu.edu/koppel/v/4ltrwrd/ `default_nettype none ////////////////////////////////////////////////////////////////////////////// /// Problem 1 // /// Complete clz_tree so that it computes the clz of its input recursively. // // [ ] Split the input between two recursive instantiations .. // .. and properly combine the results. // [ ] Don't forget the terminal case, maybe for w == 1. // [ ] For maximum credit, avoid any use of adders .. // .. by making the width of hi module a power of 2. // // [ ] Make sure that port connections are the correct size .. // .. mismatched ports are Verilog errors in this assignment. // [ ] Do not make port widths larger than needed. // [ ] Make sure that the testbench does not report errors. // [ ] Module must be synthesizable. Use command: genus -files syn.tcl // // [ ] As always, avoid costly, slow, and confusing code. module clz_tree #( int w = 19, int ww = $clog2(w+1) ) ( output uwire [ww-1:0] nlz, input uwire [w-1:0] a ); endmodule /// A Behavioral CLZ Description module clz #( int w = 19, int ww = $clog2(w+1) ) ( output var logic [ww-1:0] nlz, input uwire logic [w-1:0] a ); uwire [w:0] aa = { a, 1'b1 }; always_comb for ( int i=0; i<=w; i++ ) if ( aa[i] ) nlz = w-i; endmodule /// Solution To Homework 1 Using Generate Statements module mult_tree #( int wa = 16, int wb = 16, int wp = wa + wb ) ( output uwire [wp:1] prod, input uwire [wa:1] a, input uwire [wb:1] b ); if ( wa == 1 ) begin assign prod = a ? b : 0; end else begin localparam int wn = wa / 2; localparam int wx = wb + wn; uwire [wx:1] prod_lo, prod_hi; mult_tree #(wn,wb) mlo( prod_lo, a[wn:1], b); mult_tree #(wn,wb) mhi( prod_hi, a[wa:wn+1], b); assign prod = prod_lo + ( prod_hi << wn ); end endmodule ////////////////////////////////////////////////////////////////////////////// /// Testbench Code // cadence translate_off module testbench; // The widths (values of w) at which the modules will be instantiated. // localparam int widths[] = { 1, 2, 5, 8, 13, 15, 17 }; // localparam int nw = widths.size(); localparam int nw = 7; // Cadence, please fix this. initial if ( nw != widths.size() ) $fatal(1,"Constant nw should be %0d.\n",widths.size() ); int t_errs; // Total number of errors. initial t_errs = 0; final $write("Total number of errors: %0d\n",t_errs); uwire d[nw:-1]; // Start / Done signals. assign d[-1] = 1; // Initialize first at true. // Instantiate a testbench at each size. // for ( genvar i=0; i<nw; i++ ) testbench_n #(widths[i]) t2( .done(d[i]), .start(d[i-1]) ); endmodule module testbench_n #( int w = 20 ) ( output logic done, input uwire start ); localparam int ww = $clog2(w+1); localparam int n_tests = w * 10; uwire [ww:1] nlz; logic [w-1:0] a; clz_tree #(w) c0(nlz,a); initial begin automatic int n_errs = 0; wait( start ); $write("** Starting tests for width %0d.\n",w); for ( int t=0; t<n_tests; t++ ) begin automatic int lz = {t} % ( w + 1 ); a = { 1'b1, (w)'({$random}) } >> ( lz + 1 ); #1; if ( nlz !== lz ) begin n_errs++; testbench.t_errs++; if ( testbench.t_errs < 5 || n_errs < 2 ) $write("Error for width %2d: input %h: %d != %0d (correct).\n", w, a, nlz, lz); end end $write("Width %0d, done with %0d tests, %0d errors.\n",w,n_tests,n_errs); done = 1; end endmodule // cadence translate_on