User Tools

Site Tools


archive:nmk206

NMK206 - Computer Architecture

This course is Computer Architecture, offered by the Faculty of Electronics Engineering & Technology (FKTEN) for Electronic Engineering Technology programs.

Download ModelSim 20.1.1.720 (Intel FPGA Starter Edition) setup (SHA-1 checksum). Linux users can try this (SHA-1 checksum).

Updated20240322: This old-er version will be kept for now (just in case :-D)

Download ModelSim 13.0.1 (Altera-Edition) setup (MD5 checksum). Linux users can try this (MD5 checksum).

Video Guide for Installation

Or, watch this on 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 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-)

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.

  1. One file for one module
    • File name must be the same as module name
  2. All circuit (module) must have a testbench (tb)
    • tb is a also module (so, separate file)
  3. Use Verilog95 module declaration
    • Port list contain names only (separate input/output declaration)
  4. Modules for combinational logic should only use wire/assign statements
    • reg/always reserved for sequential logic and testbench modules
  5. Assign statements can only have ONE binary operator
    • Multiple bitwise inverts (~) are ok (they are unary operators)
  6. 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 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

dmux21.v
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
dmux21_tb.v
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

dmux41.v
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
dmux41_tb.v
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

add_1b.v
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
add_1b_tb.v
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

add_4b.v
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
add_4b_tb.v
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

sub_1b.v
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
sub_1b_tb.v
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

sub_4b.v
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
sub_4b_tb.v
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

and_4b.v
module and_4b (iA,iB,oY);
input[3:0] iA,iB;
output[3:0] oY;
wire[3:0] oY;
assign oY = iA & iB;
endmodule
and_4b_tb.v
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

or_4b.v
module or_4b (iA,iB,oY);
input[3:0] iA,iB;
output[3:0] oY;
wire[3:0] oY;
assign oY = iA | iB;
endmodule
or_4b_tb.v
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

alu_4b.v
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
alu_4b_tb.v
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

cmp_1b.v
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
cmp_1b_tb.v
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<dB) begin
      if (mGT!==1'b0||mLT!==1'b1||mEQ!==1'b0) begin
        ecnt = ecnt + 1;
      end
    end
    else begin //if (dA==dB)
      if (mGT!==1'b0||mLT!==1'b0||mEQ!==1'b1) begin
        ecnt = ecnt + 1;
      end
    end
    #5;
  end
  if (ecnt==0) begin
    $display("-- Module cmp_1b verified");
  end
  else begin
    $display("** Module cmp_1b with error(s) (%d)",ecnt);
  end
  $stop;
end
cmp_1b dut (dA,dB,mGT,mLT,mEQ);
endmodule

Module: zbuff

zbuff.v
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
zbuff_tb.v
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

decode24.v
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
decode24_tb.v
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

dff.v
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
dff_tb.v
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

dreg.v
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
dreg_tb.v
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

regblock4.v
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
regblock4_tb.v
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

dffepc.v
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
dffepc_tb.v
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

ringctr4.v
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
ringctr4_tb.v
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<clen;iter=iter+1) begin
    #(CLKP);
  end
  drst = 1'b0;
  end
endtask
reg denb;
wire[3:0] mstt;
task state_cycle ;
  reg[3:0] curr;
  begin
    $display("[%05g] Running a cycle",$time);
    curr = mstt; denb = 1'b1;
    while (mstt==curr) #(CLKP);
    while (mstt!=curr) #(CLKP);
    denb = 1'b0;
    $display("[%05g] Completed cycle",$time);
  end
endtask
always @(mstt) begin // check changes in state
  case (mstt)
    4'b0001: $display("[%05g] STATE0",$time);
    4'b0010: $display("[%05g] STATE1",$time);
    4'b0100: $display("[%05g] STATE2",$time);
    4'b1000: $display("[%05g] STATE3",$time);
    default:
      $display("[%05g] STATEX (%04b)",$time,mstt);
  endcase
end
initial begin
  // reset code
  dclk = 1'b1; denb = 1'b0; drst = 1'b0;
  $display("[%05g] CurrentState:%b",$time,mstt);
  #(CLKP/2) state_reset(2);
  #(CLKP);
  #(CLKP) state_cycle();
  #(CLKP);
  #(CLKP) state_cycle();
  #(CLKP);
  $stop;
end
ringctr4 dut (dclk,drst,denb,mstt);
endmodule

Testbench with nested loop: alu_4b_tb

This is an alternative testbench code for alu_4b module.

alu_4b_tb.v
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

archive/nmk206.txt · Last modified: 2024/06/27 18:15 by azman