====== 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 =====