====== NMK206 - Computer Architecture ====== This course is //Computer Architecture//, offered by the Faculty of Electronics Engineering & Technology (FKTEN) for Electronic Engineering Technology programs. Download [[https://azman.unimap.edu.my/storage/ModelSimSetup-20.1.1.720-windows.exe|ModelSim 20.1.1.720 (Intel FPGA Starter Edition) setup]] ([[https://azman.unimap.edu.my/storage/ModelSimSetup-20.1.1.720-windows.exe.sha1|SHA-1 checksum]]). Linux users can try [[https://azman.unimap.edu.my/storage/ModelSimSetup-20.1.1.720-linux.run|this]] ([[https://azman.unimap.edu.my/storage/ModelSimSetup-20.1.1.720-linux.run.sha1|SHA-1 checksum]]). //**Updated20240322**: This old-er version will be kept for now (just in case :-D)// Download [[https://azman.unimap.edu.my/storage/ModelSimSetup-13.0.1.232.exe|ModelSim 13.0.1 (Altera-Edition) setup]] ([[https://azman.unimap.edu.my/storage/ModelSimSetup-13.0.1.232.exe.md5|MD5 checksum]]). Linux users can try [[https://azman.unimap.edu.my/storage/ModelSimSetup-13.0.1.232.run|this]] ([[https://azman.unimap.edu.my/storage/ModelSimSetup-13.0.1.232.run.md5|MD5 checksum]]). **Video Guide for Installation** {{:archive:pgt206:nmk206_howto_install_modelsim.mp4}} Or, watch this on [[https://youtu.be/DexTcLyyIZo|YouTube]] (Note: the YouTube version is missing details for my incorrect sample code in the video. Refer to the description. The video here has been updated with that info.) ===== Announcements ===== [20240307] Welcome to the new NMK206 info page (for lab sessions only)! ===== Lab Session ===== I am using [[https://en.wikipedia.org/wiki/Takahashi_method|Takahashi Method]] for these slides (Actually, I broke that method by adding diagrams and long codes because I think my students need them). You will find them hard to understand if you do not attend my sessions. So, that is the 'advantage' I gave to those who actually listen in class 8-) * Lab Briefing {{ :archive:pgt206:my1lab00.pdf |Slides}} * Intro to CAD Tools and HDL {{ :archive:pgt206:my1lab01.pdf |Slides}} * Verilog Basics {{ :archive:pgt206:my1lab02.pdf |Slides}} * Combinational Logic {{ :archive:pgt206:my1lab03.pdf |Slides (P1)}} {{ :archive:pgt206:my1lab04.pdf |Slides (P2)}} {{ :archive:pgt206:my1lab05.pdf |Slides (P3)}} {{ :archive:pgt206:my1lab06.pdf |Slides (P4)}} {{ :archive:pgt206:my1lab07.pdf |Slides (P5)}} * Sequential Logic {{ :archive:pgt206:my1lab08.pdf |Slides (P1)}} {{ :archive:pgt206:my1lab08_ext.pdf |Slides (P1x)}} {{ :archive:pgt206:my1lab09.pdf |Slides (P2)}} * State Machine {{ :archive:pgt206:my1lab10.pdf |Slides}} * Simple Digital System {{ :archive:pgt206:my1lab11.pdf |Slides}} **Verilog coding style/rule** This is the coding style/rule that I impose on my students. You will be penalised during assessments if it is not adhered to. - One file for one module * **File name must be the same as module name** - All circuit (module) must have a testbench (tb) * tb is a also module (so, separate file) - Use Verilog95 module declaration * Port list contain names only (separate input/output declaration) - Modules for combinational logic should only use wire/assign statements * reg/always reserved for sequential logic and testbench modules - Assign statements can only have ONE binary operator * Multiple bitwise inverts (~) are ok (they are unary operators) - ALL nets (wire/reg) MUST BE declared. * some compiler may allow using without declaration * for my assessments, they MUST BE declared ===== Base-code for project ===== You should also be able to get these from [[https://azman.unimap.edu.my/files/#nmk206%2F202324s2/|here]]. But please note that the codes over there will most probably use '$finish' instead of '$stop' - so you will have to modify that on your own. ==== Module: dmux21 ==== module dmux21 (iS,iA,iB,oY); parameter BITS = 4; input iS; input[BITS-1:0] iA,iB; output[BITS-1:0] oY; wire[BITS-1:0] oY, tA, tB; assign tA = {BITS{~iS}}&iA; assign tB = {BITS{iS}}&iB; assign oY = tA | tB; endmodule module dmux21_tb (); parameter BITS = 4; reg dS; reg[BITS-1:0] dA,dB; wire[BITS-1:0] mY; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<2**((BITS*2)+1);loop=loop+1) begin {dS,dA,dB} = loop; #5; if (dS===1'b1) begin if (mY!==dB) begin ecnt = ecnt + 1; end end else if (dS==1'b0) begin if (mY!==dA) begin ecnt = ecnt + 1; end end #5; end if (ecnt==0) begin $display("-- Module dmux21 verified!"); end else begin $display("** Module dmux21 with errors! (%d)",ecnt); end $stop; end defparam dut.BITS = BITS; dmux21 dut (iS,iA,iB,oY); // or, dmux21 #(BITS) dut (iS,iA,iB,oY); // verilog2k1 endmodule ==== Module: dmux41 ==== module dmux41 (iS,iA,iB,iC,iD,oY); parameter BITS = 6; input[1:0] iS; input[BITS-1:0] iA,iB,iC,iD; output[BITS-1:0] oY; wire[BITS-1:0] oY,tP,tQ; dmux21 s00 (iS[0],iA,iB,tP); dmux21 s01 (iS[0],iC,iD,tQ); dmux21 s10 (iS[1],tP,tQ,oY); endmodule module dmux41_tb (); parameter BITS = 6; // cannot be >7! reg[1:0] dS; reg[BITS-1:0] dA,dB,dC,dD; wire[BITS-1:0] mY; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<2**((BITS*2)+2);loop=loop+1) begin {dS,dA,dB,dC,dD} = loop; #5; if (dS===2'b00) begin if (mY!==dA) begin ecnt = ecnt + 1; end end else if (dS===2'b01) begin if (mY!==dB) begin ecnt = ecnt + 1; end end else if (dS===2'b10) begin if (mY!==dC) begin ecnt = ecnt + 1; end end else if (dS===2'b11) begin if (mY!==dD) begin ecnt = ecnt + 1; end end #5; end if (ecnt==0) begin $display("-- Module dmux41 verified!"); end else begin $display("** Module dmux41 with errors! (%d)",ecnt); end $stop; end dmux41 dut (dS,dA,dB,dC,dD,mY); endmodule ==== Module: add_1b ==== module add_1b (iC,iP,iQ,oC,oS); input iC,iP,iQ; output oC, oS; wire oC, oS, tP, tG, tP1, tP2, tS1, tS2, tX; // just to show order DOES NOT matter assign oS = tS1 | tS2; // iC ^ tP; assign oC = tG | tX; assign tG = iP & iQ; assign tP1 = iP & ~iQ; assign tP2 = ~iP & iQ; assign tP = tP1 | tP2; // iP ^ iQ; assign tS1 = iC & ~tP; assign tS2 = ~iC & tP; assign tX = iC & tP; endmodule module add_1b_tb (); reg dC,dP,dQ; wire mC,mS; reg cC,cS; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<8;loop=loop+1) begin {dC,dP,dQ} = loop; #5; {cC,cS} = dC+dP+dQ; // or, do a truth table! if (mC!==cC||mS!==cS) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module add_1b verified!"); end else begin $display("** Module add_1b with error(s)! (%d)",ecnt); end $stop; end add_1b dut (dC,dP,dQ,mC,mS); endmodule ==== Module: add_4b ==== module add_4b (iC,iP,iQ,oC,oS); input iC; input[3:0] iP,iQ; output oC; output[3:0] oS; wire oC; wire[3:0] oS; wire[2:0] tC; add_1b bit0 (iC,iP[0],iQ[0],tC[0],oS[0]); add_1b bit1 (tC[0],iP[1],iQ[1],tC[1],oS[1]); add_1b bit2 (tC[1],iP[2],iQ[2],tC[2],oS[2]); add_1b bit3 (tC[2],iP[3],iQ[3],oC,oS[3]); endmodule module add_4b_tb (); reg dC; reg[3:0] dP,dQ; wire mC; wire[3:0] mS; reg cC; reg[3:0] cS; integer loop,ecnt; initial begin ecnt=0; for (loop=0;loop<512;loop=loop+1) begin {dC,dP,dQ} = loop; #5; {cC,cS} = dP + dQ + dC; if (mC!==cC||mS!==cS) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module add_4b verified!"); end else begin $display("** Module add_4b with error(s)! (%d)",ecnt); end $stop; end add_4b dut (dC,dP,dQ,mC,mS); endmodule ==== Module: sub_1b ==== module sub_1b (iB,iP,iQ,oB,oD); input iB,iP,iQ; output oB, oD; wire oB, oD, tP, tG, tP1, tP2, tS1, tS2, tX; assign oD = tS1 | tS2; // iB ^ tP; assign oB = tG | tX; assign tG = tP2; // ~iP & iQ; assign tP1 = iP & ~iQ; assign tP2 = ~iP & iQ; assign tP = tP1 | tP2; // iP ^ iQ; assign tS1 = iB & ~tP; assign tS2 = ~iB & tP; assign tX = tS1; // iB & ~tP; endmodule module sub_1b_tb (); reg dB,dP,dQ; wire mB,mD; reg cB,cD; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<8;loop=loop+1) begin {dB,dP,dQ} = loop; #5; {cB,cD} = dP-dQ-dB; // or, do a truth table! if (mB!==cB||mD!==cD) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module sub_1b verified!"); end else begin $display("** Module sub_1b with error(s)! (%d)",ecnt); end $stop; end sub_1b dut (dB,dP,dQ,mB,mD); endmodule ==== Module: sub_4b ==== module sub_4b (iB,iP,iQ,oB,oD); input iB; input[3:0] iP,iQ; output oB; output[3:0] oD; wire oB; wire[3:0] oD; wire[2:0] tB; sub_1b bit0 (iB,iP[0],iQ[0],tB[0],oD[0]); sub_1b bit1 (tB[0],iP[1],iQ[1],tB[1],oD[1]); sub_1b bit2 (tB[1],iP[2],iQ[2],tB[2],oD[2]); sub_1b bit3 (tB[2],iP[3],iQ[3],oB,oD[3]); endmodule module sub_4b_tb (); reg dB; reg[3:0] dP,dQ; wire mB; wire[3:0] mS; reg cB; reg[3:0] cS; integer loop,ecnt; initial begin ecnt=0; for (loop=0;loop<512;loop=loop+1) begin {dB,dP,dQ} = loop; #5; {cB,cS} = dP - dQ - dB; if (mB!==cB||mS!==cS) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module sub_4b verified!"); end else begin $display("** Module sub_4b with error(s)! (%d)",ecnt); end $stop; end sub_4b dut (dB,dP,dQ,mB,mS); endmodule ==== Module: and_4b ==== module and_4b (iA,iB,oY); input[3:0] iA,iB; output[3:0] oY; wire[3:0] oY; assign oY = iA & iB; endmodule module and_4b_tb (); reg[3:0] dP,dQ; wire[3:0] mY; reg[3:0] cY; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<256;loop=loop+1) begin {dP,dQ} = loop; #5; cY = dP&dQ; if (mY!==cY) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module and_4b verified!"); end else begin $display("** Module and_4b with error(s)! (%d)",ecnt); end $stop; end and_4b dut (dP,dQ,mY); endmodule ==== Module: or_4b ==== module or_4b (iA,iB,oY); input[3:0] iA,iB; output[3:0] oY; wire[3:0] oY; assign oY = iA | iB; endmodule module or_4b_tb (); reg[3:0] dP,dQ; wire[3:0] mY; reg[3:0] cY; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<256;loop=loop+1) begin {dP,dQ} = loop; #5; cY = dP|dQ; if (mY!==cY) begin ecnt = ecnt + 1; end #5; end if (ecnt==0) begin $display("-- Module or_4b verified!"); end else begin $display("** Module or_4b with error(s)! (%d)",ecnt); end $stop; end or_4b dut (dP,dQ,mY); endmodule ==== Module: alu_4b ==== module alu_4b (iS,iA,iB,oY); input[1:0] iS; input[3:0] iA,iB; output[3:0] oY; wire[3:0] oY, tY0, tY1, tY2, tY3; wire tD0, tD1; add_4b a_add (1'b0,iA,iB,tD0,tY0); sub_4b a_sub (1'b0,iA,iB,tD1,tY1); and_4b l_and (iA,iB,tY2); or_4b l_or (iA,iB,tY3); defparam omux.BITS = 4; dmux41 omux (iS,tY0,tY1,tY2,tY3,oY); endmodule module alu_4b_tb (); reg[1:0] dS; reg[3:0] dP,dQ; wire[3:0] mY; integer loop,ecnt; initial begin ecnt=0; for (loop=0;loop<1024;loop=loop+1) begin {dS,dP,dQ} = loop; #5; if (dS===2'b00) begin // test add if (mY!==(dP+dQ)) begin ecnt = ecnt + 1; end end else if (dS===2'b01) begin // test sub if (mY!==(dP-dQ)) begin ecnt = ecnt + 1; end end else if (dS===2'b10) begin // test and if (mY!==(dP&dQ)) begin ecnt = ecnt + 1; end end else if (dS===2'b11) begin // test or if (mY!==(dP|dQ)) begin ecnt = ecnt + 1; end end #5; end if (ecnt==0) begin $display("-- Module alu_4b verified!"); end else begin $display("** Module alu_4b with error(s)! (%d)",ecnt); end $stop; end alu_4b dut (dS,dP,dQ,mY); endmodule ==== Module: cmp_1b ==== module cmp_1b (iA,iB,oGT,oLT,oEQ); input iA,iB; output oGT,oLT,oEQ; wire oGT,oLT,oEQ, tGT, tLT; assign tGT = iA & ~iB; assign tLT = ~iA & iB; assign oLT = tLT; assign oGT = tGT; assign oEQ = ~(tLT | tGT); // ~(iA ^ iB) endmodule module cmp_1b_tb (); reg dA,dB; wire mGT,mLT,mEQ; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<4;loop=loop+1) begin {dA,dB} = loop; #5; if (dA>dB) begin if (mGT!==1'b1||mLT!==1'b0||mEQ!==1'b0) begin ecnt = ecnt + 1; end end else if (dA ==== Module: zbuff ==== module zbuff (iE,iA,oY); parameter BITS = 4; input iE; input[BITS-1:0] iA; output[BITS-1:0] oY; wire[BITS-1:0] oY; assign oY = (iE==1'b1) ? iA : {BITS{1'bz}}; endmodule module zbuff_tb (); parameter BITS = 4; reg dE; reg[BITS-1:0] dA; wire[BITS-1:0] mY; integer loop,ecnt; initial begin ecnt = 0; for (loop=0;loop<2**(BITS+1);loop=loop+1) begin {dE,dA} = loop; #5; if (dE===1'b1) begin if (mY!==dA) begin ecnt = ecnt + 1; end end else if (dE===1'b0) begin if (mY!=={BITS{1'bz}}) begin ecnt = ecnt + 1; end end #5; end if (ecnt==0) begin $display("-- Module zbuff verified"); end else begin $display("** Module zbuff with error(s) (%d)",ecnt); end $stop; end zbuff dut (dE,dA,mY); endmodule ==== Module: decode24 ==== module decode24 (iA,oY); input[1:0] iA; output[3:0] oY; wire[3:0] oY; assign oY[0] = ~iA[1] & ~iA[0]; assign oY[1] = ~iA[1] & iA[0]; assign oY[2] = iA[1] & ~iA[0]; assign oY[3] = iA[1] & iA[0]; endmodule module decode24_tb (); reg[1:0] dA; wire[3:0] mY; reg[3:0] cY; integer loop,ecnt; initial begin ecnt = 0; cY = 4'b0001; for (loop=0;loop<4;loop=loop+1) begin dA = loop; #5; if (mY!==cY) begin ecnt = ecnt + 1; end cY = cY << 1; #5; end if (ecnt==0) begin $display("-- Module decode24 verified"); end else begin $display("** Module decode24 with error(s) (%d)",ecnt); end $stop; end decode24 dut (dA,mY); endmodule ==== Module: dff ==== module dff (iclk,idat,odat); input iclk,idat; output odat; reg odat; always @(iclk) begin if (iclk==1'b1) begin odat = idat; end end endmodule module dff_tb (); parameter CLKP = 10; reg dclk; // clock net always begin #(CLKP/2) dclk = ~dclk; end // assume @+ve edge dff // assume driver net is ddat // should call this @-ve edge reg ddat; // dff input task dff_wr ; input integer dbit; begin ddat = dbit; $display("-- [%g] WR-dff:'%b' ",$time,ddat); #(CLKP/2); // setup time // should latch here #(CLKP/2); // hold time // 1-cycle end endtask // detect dff output // can also use mdat! always @(dut.odat) begin $write("[%05g] dffQ=%b\n",$time,dut.odat); end // 'main' block wire mdat; // output signal initial begin // reset condition dclk = 1'b1; //at tu=0, dclk is 1 ddat = 1'b0; // start test #(CLKP/2); // wait for -ve edge dff_wr(1); #CLKP; // verify here? change ddat? #CLKP; dff_wr(0); #(CLKP*5); $stop; end dff dut (dclk,ddat,mdat); endmodule ==== Module: dreg ==== module dreg (iclk,wenb,renb,idat,odat); parameter BITS = 4; input iclk,wenb,renb; input[BITS-1:0] idat; output[BITS-1:0] odat; wire[BITS-1:0] odat; reg[BITS-1:0] tdat; always @(posedge iclk) begin if (wenb===1'b1) begin tdat = idat; end end defparam oenb.BITS = BITS; zbuff oenb (renb,tdat,odat); endmodule module dreg_tb (); parameter BITS = 4; parameter CLKP = 10; reg dclk; // clock net always begin #(CLKP/2) dclk = ~dclk; end reg dwen; reg[BITS-1:0] ddat; task dreg_write ; input integer dval; begin ddat = dval; // setup data for write dwen = 1'b1; // enable write for 1 clk period $display("-- [%05g] WR-dreg:'%b' ",$time,ddat); #(CLKP/2); // setup time #(CLKP/2); // hold time dwen = 1'b0; // disable write end endtask always @(dut.tdat) begin $write("## [%05g] dregQ=%b\n",$time,dut.tdat); end reg dren; wire[BITS-1:0] mdat; task dreg_read ; begin dren = 1'b1; // enable read for 1 clk period #(CLKP/2); // setup time $display("@@ [%05g] RD-dreg:'%b' ",$time,mdat); #(CLKP/2); // hold time dren = 1'b0; // disable read end endtask initial begin dclk = 1'b1; //ddat = 4'h5; dwen = 1'b0; dren = 1'b0; // start test dreg_read(); #(CLKP/2); // wait for -ve edge dreg_write(4'b1010); #CLKP; dreg_read(); dreg_write(12); #CLKP; dreg_read(); $stop; end defparam dut.BITS = BITS; dreg dut (dclk,dwen,dren,ddat,mdat); endmodule ==== Module: regblock4 ==== module regblock4 (iclk,wenb,renb,r2nb, wadd,radd,r2dd,idat,odat,od2t); parameter BITS=4; input iclk,wenb,renb,r2nb; input[1:0] wadd,radd,r2dd; input[BITS-1:0] idat; output[BITS-1:0] odat,od2t; wire[BITS-1:0] odat,od2t; wire[BITS-1:0] tmp0,tmp1,tmp2,tmp3; wire[3:0] wtmp, rtmp, r2mp; // and gates output wire[3:0] wdec, rdec, r2ec; // decode24 output dreg r0 (iclk,wtmp[0],1'b1,idat,tmp0); dreg r1 (iclk,wtmp[1],1'b1,idat,tmp1); dreg r2 (iclk,wtmp[2],1'b1,idat,tmp2); dreg r3 (iclk,wtmp[3],1'b1,idat,tmp3); decode24 decW (wadd,wdec); decode24 decR (radd,rdec); decode24 decX (r2dd,r2ec); assign wtmp = {4{wenb}} & wdec; assign rtmp = {4{renb}} & rdec; assign r2mp = {4{r2nb}} & r2ec; zbuff out0 (rtmp[0],tmp0,odat); zbuff out1 (rtmp[1],tmp1,odat); zbuff out2 (rtmp[2],tmp2,odat); zbuff out3 (rtmp[3],tmp3,odat); zbuff o2t0 (r2mp[0],tmp0,od2t); zbuff o2t1 (r2mp[1],tmp1,od2t); zbuff o2t2 (r2mp[2],tmp2,od2t); zbuff o2t3 (r2mp[3],tmp3,od2t); endmodule module regblock4_tb (); parameter BITS=4; parameter CLKP = 10; reg dclk; // clock net always begin #(CLKP/2) dclk = ~dclk; end reg renb, r2nb, wenb; reg[1:0] rsel, r2el, wsel; reg[BITS-1:0] ddat; wire[BITS-1:0] mdat, md2t; task reg_move ; // call on -ve edge input[1:0] wadd, radd; // modified to test second port input integer port; begin // read cycle rsel = radd; r2el = radd; // assign both port if (port===0) renb = 1'b1; // enb first port else r2nb = 1'b1; // enb second port #(CLKP); // this is actually a multiplexer! if (port===0) ddat = mdat; // read first port else ddat = md2t; // read second port // write cycle wsel = wadd; wenb = 1'b1; #(CLKP); wenb = 1'b0; renb = 1'b0; r2nb = 1'b0; end endtask task reg_hack; // call on -ve edge input[1:0] hadd; input[BITS-1:0] hdat; begin // write cycle wsel = hadd; wenb = 1'b1; ddat = hdat; #(CLKP); wenb = 1'b0; end endtask always @(posedge dclk) begin if (renb===1'b1) begin $display("[%05g] R%g (%b) read1 value %h@(%b)", $time,rsel,rsel,mdat,mdat); end if (r2nb===1'b1) begin $display("[%05g] R%g (%b) read2 value %h@(%b)", $time,r2el,r2el,md2t,md2t); end if (wenb===1'b1) begin $display("[%05g] R%g (%b) write value %h@(%b)", $time,wsel,wsel,ddat,ddat); end end task reg_showall; begin $write("[%05g] Register Contents => { ",$time); $write("R0:%b ",dut.r0.tdat); $write("R1:%b ",dut.r1.tdat); $write("R2:%b ",dut.r2.tdat); $write("R3:%b }\n",dut.r3.tdat); end endtask // the rest... initial begin dclk = 1'b1; wenb = 1'b0; renb = 1'b0; r2nb = 1'b0; // start test reg_showall(); #(CLKP/2) reg_hack(0,4'ha); #(CLKP) reg_hack(1,4'h5); #(CLKP*2) reg_hack(2,4'h9); #(CLKP) reg_hack(3,4'hd); reg_showall(); #(CLKP) reg_move(2,3,0); // mov r2,r3 #(CLKP) reg_move(1,0,1); // mov r1,r0 reg_showall(); $stop; end defparam dut.BITS = BITS; regblock4 dut (dclk,wenb,renb,r2nb,wsel,rsel,r2el,ddat,mdat,md2t); endmodule ==== Module: dffepc ==== module dffepc (iclk,ienb,ipre,iclr,idat,odat); input iclk,ienb,ipre,iclr; input idat; output odat; reg odat; // synchronous pre/clr always @(posedge iclk) begin if (ipre===1'b1) begin odat = 1'b1; end else if (iclr===1'b1) begin odat = 1'b0; end else if (ienb===1'b1) begin odat = idat; end end endmodule module dffepc_tb (); parameter CLKP = 10; reg dclk; // clock net always begin #(CLKP/2) dclk = ~dclk; end reg denb, dpre, dclr, ddat; task dffepc_reset ; begin dpre = 1'b1; // enable preset for 1 clk period $display("-- [%05g] dffepcPRE ",$time); #(CLKP); dpre = 1'b0; end endtask task dffepc_clear ; begin dclr = 1'b1; // enable clear for 1 clk period $display("-- [%05g] dffepcCLR ",$time); #(CLKP); dclr = 1'b0; end endtask task dffepc_write ; input integer dval; begin ddat = dval; // setup data for write denb = 1'b1; // enable write for 1 clk period $display("-- [%05g] WR-dffepc:'%b' ",$time,ddat); #(CLKP/2); // setup time #(CLKP/2); // hold time denb = 1'b0; // disable write end endtask wire mdat; always @(mdat) begin $write("## [%05g] dffepcQ=%b\n",$time,mdat); end initial begin dclk = 1'b1; denb = 1'b0; dpre = 1'b0; dclr = 1'b0; #(CLKP/2); // wait for -ve edge dffepc_reset(); dffepc_write(0); dffepc_write(1); #(CLKP*2); dffepc_write(4); dffepc_write(5); dffepc_clear(); #(CLKP*1); dffepc_reset; // can leave out the () if no arg $finish; end dffepc dut (dclk,denb,dpre,dclr,ddat,mdat); endmodule ==== Module: ringctr4 ==== module ringctr4 (iclk,irst,ienb,ostt); input iclk,irst,ienb; output[3:0] ostt; wire[3:0] ostt, qout; dffepc s0 (iclk,ienb,irst,1'b0,qout[3],qout[0]); dffepc s1 (iclk,ienb,1'b0,irst,qout[0],qout[1]); dffepc s2 (iclk,ienb,1'b0,irst,qout[1],qout[2]); dffepc s3 (iclk,ienb,1'b0,irst,qout[2],qout[3]); assign ostt = qout; endmodule module ringctr4_tb (); parameter CLKP = 10; reg dclk; // clock net always begin #(CLKP/2) dclk = ~dclk; end reg drst; task state_reset ; input integer clen; integer iter; begin $write("[%05g] Reset state machine ",$time); $display("for %g clock cycles",clen); drst = 1'b1; for (iter=0;iter ==== Testbench with nested loop: alu_4b_tb ==== This is an alternative testbench code for alu_4b module. module alu_4b_tb (); reg[1:0] dS; reg[3:0] dP,dQ; wire[3:0] mY; integer loop1,loop2,ecnt; initial begin ecnt=0; $display("-- Testing add"); dS = 2'b00; // select add for (loop1=0;loop1<16;loop1=loop1+1) begin dP = loop1; for (loop2=0;loop2<16;loop2=loop2+1) begin dQ = loop2; #5; if (mY!==(dP+dQ)) begin ecnt = ecnt + 1; end #5; end end $display("-- Testing sub"); dS = 2'b01; // select sub for (loop1=0;loop1<16;loop1=loop1+1) begin dP = loop1; for (loop2=0;loop2<16;loop2=loop2+1) begin dQ = loop2; #5; if (mY!==(dP-dQ)) begin ecnt = ecnt + 1; end #5; end end $display("-- Testing and"); dS = 2'b10; // select and for (loop1=0;loop1<16;loop1=loop1+1) begin dP = loop1; for (loop2=0;loop2<16;loop2=loop2+1) begin dQ = loop2; #5; if (mY!==(dP&dQ)) begin ecnt = ecnt + 1; end #5; end end $display("-- Testing or"); dS = 2'b11; // select or for (loop1=0;loop1<16;loop1=loop1+1) begin dP = loop1; for (loop2=0;loop2<16;loop2=loop2+1) begin dQ = loop2; #5; if (mY!==(dP|dQ)) begin ecnt = ecnt + 1; end #5; end end if (ecnt==0) begin $display("-- Module alu_4b verified!"); end else begin $display("** Module alu_4b with error(s)! (%d)",ecnt); end $stop; end alu_4b dut (dS,dP,dQ,mY); endmodule ===== Module: template =====