Tutorial #1
Verilog
Simulation
Toolflow
v
vc s mips.
%
imv
% ./s RPP &
–
% vcs
6.884 – Spring 2005 02/09/05 T01 – Verilog 1
6.884 Toolflow For Lab 1 and 2
Assembly
StdCell Verilog
Source
Library Source
Code
Synopsys DC Synopsys VCS SMIPS Assembler
Verilog
StdCell Func Test
Gate
Library Sim Inputs
Level
Cadence Encounter Synopsys VirSim Test Scripts
Timing
Test
Area
Outputs
Power
6.884 – Spring 2005 02/09/05 T01 – Verilog 2
Tour of the 6.884 Athena Locker
To access the locker use setup 6.884
– /mit/6.884/tools
– /mit/6.884/doc
– /mit/6.884/examples
For those with access to the CAG network please
make use of the CAG infrastructure
– Use setup 6.884 (will setup tools needed for the course)
– Locker (partially) mirrored at /projects/assam/6.884
– CAG updates will probably lag a bit behind Athena
6.884 – Spring 2005 02/09/05 T01 – Verilog 3
Three Examples
GCD
Beta
Lab1
6.884 – Spring 2005 02/09/05 T01 – Verilog 4
Greatest Common Divisor
Control Unit
go A A B B out done
mux reg mux reg mux
sel en sel en B=0 A<B sel
zero? lt out
A_in
A
sub
B_in
B
6.884 – Spring 2005 02/09/05 T01 – Verilog 5
GCD Control Logic
out_mux_sel
while ( !done )
A_mux_sel
B_mux_sel
if ( A < B )
A_en
B_en
done
swap( A, B )
else if ( B != 0 ) Load 1 1 0 0 X 0
A=A–B
Swap 1 1 1 1 1 0
else
done = true Sub 1 0 1 X 0 0
endwhile Done 0 0 X X X 1
reg [5:0] ctrl_sig;
assign { A_en, B_en, A_mux_sel, B_mux_sel, out_mux_sel, done } = ctrl_sig;
always @(*)
begin
if ( !running ) ctrl_sig = 6'b11_00x_0; // Latch in A and B values
else if ( A_lt_B ) ctrl_sig = 6'b11_111_0; // A <= B and B <= A
else if ( !B_zero ) ctrl_sig = 6'b10_1x0_0; // A <= A - B and B <= B
else ctrl_sig = 6'b00_xxx_1; // Done
end
6.884 – Spring 2005 02/09/05 T01 – Verilog 6
GCD Test Harness
Control Unit
go A A B B out done
mux reg mux reg mux
sel en sel en B=0 A<B sel
zero? lt out
A_in
A
sub
B_in
B
6.884 – Spring 2005 02/09/05 T01 – Verilog 7
GCD Test
module gcd_test;
reg clock = 0; reg reset = 0; reg go = 0;
reg [15:0] A_in, B_in;
wire done; Harness
wire [15:0] Y;
always #10 clock = ~clock;
gcd_rtl gcd_unit( .clock(clock), .reset(reset), .go(go),
.A_in(A_in), .B_in(B_in), .done(done), .Y(Y) );
initial begin
$vcdpluson(0);
A_in = 27; B_in = 15; // Set defaults
$value$plusargs("a-in=%d",A_in); // Read in cmdline args
$value$plusargs("b-in=%d",B_in);
#5 reset = 1; #20 reset = 0; // Strobe reset signal
#20 go = 1; #20 go = 0; // Strobe go signal
end
always @( done ) begin
if ( done ) begin
#15;
Try to keep the Verilog
$display(" a-in
$display(" b-in
= %d", A_in );
= %d", B_in );
part of the test harness
$display(" gcd-out = %d", Y
$finish;
);
as simple as possible!
end
end
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 8
Building a GCD Simulator with VCS
% setup 6.884
Attaching 6.884 …
Running commands in /mit/6.884/.attachrc …
% vcs –PP +lint=all +v2k gcd_rtl.v
% ./simv
VCD+ Writer 4.4R10 Copyright 1993-2004 Synopsys Inc.
a-in = 27
b-in = 15
gcd-out = 3
$finish at simulation time 245
% ./simv +a-in=49 +b-in=28
VCD+ Writer 4.4R10 Copyright 1993-2004 Synopsys Inc.
a-in = 49
b-in = 28
gcd-out = 7
$finish at simulation time 225
% vcs –RPP &
6.884 – Spring 2005 02/09/05 T01 – Verilog 9
Viewing Waveforms with VirSim
Open up a
waveform
viewer
Browse Select
the signals
module for
hierarchy display
6.884 – Spring 2005 02/09/05 T01 – Verilog 10
Viewing Waveforms with VirSim
6.884 – Spring 2005 02/09/05 T01 – Verilog 11
Using Test Scripts
% vcs –PP +lint=all +v2k gcd_rtl.v
% vmodel-tester.pl –v ./simv gcd-test.dat
* Verilog model = ./simv
* Test data file = gcd-test.dat
* Running tests
+ Testing a-in=27 b-in=15 gcd-out=3
+ Testing a-in=21 b-in=49 gcd-out=7
+ Testing a-in=25 b-in=30 gcd-out=5
+ Testing a-in=19 b-in=27 gcd-out=1
+ Testing a-in=40 b-in=40 gcd-out=40
+ Testing a-in=250 b-in=190 gcd-out=10
+ Testing a-in=5 b-in=250 gcd-out=5
+ Testing a-in=0 b-in=0 gcd-out=0
*** PASSED ***
6.884 – Spring 2005 02/09/05 T01 – Verilog 12
Using the mkasic.pl Script
gcd/ gcd/
mkasic.pl gcd_behavioral/
verilog/ vcs/
gcd_behavioral.v vcstest/
gcd_rtl.v gcd_rtl/
config/ vcs/
gcd_behavioral.cfg vcstest/
gcd_rtl.cfg
tests/
gcd-test.dat
% cp –r /mit/6.884/examples/gcd
% cd gcd
% ./mkasic.pl –v config/gcd_rtl.cfg vcs
% ./mkasic.pl –v config/gcd_behavioral.cfg vcs
% ./mkasic.pl –v config/gcd_rtl.cfg vcstest
% ./mkasic.pl –v config/gcd_behavioral.cfg vcstest
6.884 – Spring 2005 02/09/05 T01 – Verilog 13
Writing Config Files for mkasic.pl
#-------------------------------------------------------------------------
# General configuration options
package general;
$outputDir = "gcd_rtl"; # Dir for all generated product
$verilogSrcDir = "verilog"; # Dir where all verilog source is located
$toplevelSource = "gcd_rtl.v"; # Verilog src file w/ toplevel module
$toplevelModule = "gcd_test"; # Name of toplevel verlog module
#-------------------------------------------------------------------------
# VCS - Synopsys Verilog compiler
package vcs;
$simName = "gcd-rtl"; # Name to use for the VCS simulator
$cmdLineOptions = ""; # Any additional VCS compiler options
#-------------------------------------------------------------------------
# Test
package vcstest;
$inputDir = "tests"; # Dir containing test inputs
@testList = ( "gcd-test.dat" ); # A list of test inputs
$cmdLine = "vmodel-tester.pl -v __SIMNAME__ __TESTINPUT__";
return 1; # Return true for mkasic.pl
6.884 – Spring 2005 02/09/05 T01 – Verilog 14
Beta Micro-Architecture
ILL
XAdr OP JT
PCSEL 4 3 2 1 0 Step 1: identify memories
PC 00
1 Step 2: identify datapaths
A Instruction
Memory
What’s left is random logic …
D
+4
Ra: <20:16> Rb: <15:11> Rc: <25:21>
0 1 RA2SEL
2 + WASEL
XP 1
RA1 Register RA2
WD
1
PC
Rc: <25:21> WA
WA
File
0
RD1 RD2 WE WERF
Z
JT
C: SXT(<15:0>)
PC+4+4*SXT(C)
IRQ Z
ASEL 1 0 1 0 BSEL
Control Logic
PCSEL
RA2SEL A B
ASEL ALU WD R/W Wr
ALUFN
BSEL
WDSEL Data Memory
ALUFN Adr RD
Wr
WERF
WASEL
PC+4 1
0 1 2 WDSEL
2
Main Datapath
6.884 – Spring 2005 02/09/05 T01 – Verilog 15
module pc
PC Dpath
(
input clk,
input reset, // forces PC to 0x80000000
input [2:0] pcsel, // selects source of next PC
input [15:0] offset, // inst[15:0]
input [31:0] jump_addr, // from Reg[RA], used in JMP instruction
output [31:0] branch_addr, // send to datapath for LDR instruction
output [31:0] pc, // used as address for instruction fetch
output [31:0] pc_plus_4 // saved in regfile during branches, JMP, traps
);
reg [31:0] pc;
wire [30:0] pcinc;
wire [31:0] npc;
assign pcinc = pc + 4;
assign pc_plus_4 = {pc[31],pcinc};
// Branch address = PC + 4 + 4*sxt(offset)
assign branch_addr = {1'b0, pcinc + {{13{offset[15]}},offset[15:0],2'b00}};
assign npc = reset ? 32'h80000000 :
(pcsel == 0) ? {pc[31],pcinc} : // normal
(pcsel == 1) ? {pc[31],branch_addr[30:0]} : // branch
(pcsel == 2) ? {pc[31] & jump_addr[31],jump_addr[30:0]} : // jump
(pcsel == 3) ? 32'h80000004 :
(pcsel == 4) ? 32'h80000008 : // illop, trap
32'hXXXXXXXX; // catch errors...
always @( posedge clk )
pc <= npc;
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 16
Beta Register File
module regfile
(
input [4:0] ra1, // address for read port 1 (Reg[RA])
output [31:0] rd1, // read data for port 1
input [4:0] ra2, // address for read port 2 (Reg[RB], Reg[RC] for ST)
output [31:0] rd2, // read data for port 2
input clk,
input werf, // write enable, active high
input [4:0] wa, // address for write port (Reg[RC])
input [31:0] wd // write data
);
// The register file itself
reg [31:0] registers[31:0];
// read paths are combinational, register 31 is always zero register
assign rd1 = (ra1 == 5'b11111) ? 32'h00000000 : registers[ra1];
assign rd2 = (ra2 == 5'b11111) ? 32'h00000000 : registers[ra2];
// write port is active only when WERF is asserted
always @(posedge clk)
begin
if ( werf )
registers[wa] <= wd;
end
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 17
module datapath
(
input [15:0] inst, // constant field from instruction
input [31:0] rd1, // Reg[RA] from register file
input [31:0] rd2, // Reg[RB] from register file (Reg[RC] for ST)
input [31:0] pc_plus_4, // incremented PC
input [31:0] branch_addr, // PC + 4 + 4*sxt(inst[15:0])
input [31:0] mem_rd_data, // memory read data (for LD)
input asel, // select A operand for ALU
input bsel, // select B operand for ALU
input [1:0] wdsel, // select regfile write data
input [5:0] alufn, // operation to be performed by alu
output [31:0] wdata, // regfile write data (output of WDSEL mux)
output [31:0] mem_addr, // alu output, doubles as data memory address
output [31:0] jump_addr, // jump address (from Reg[RA])
output [31:0] mem_wr_data, // data memory write data (from Reg[RC])
output z // true if Reg[RA] is zero, used during branches
);
wire [31:0] alu_a; // A input to ALU
wire [31:0] alu_b; // B input to ALU
// compute A and B inputs into alu, also Z bit for control logic
dp_misc misc(asel,bsel,inst,rd1,rd2,branch_addr,
alu_a,alu_b,jump_addr,mem_wr_data,z);
// where all the heavy-lifting happens
dp_alu alu(alufn,alu_a,alu_b,mem_addr);
// Mux to select regfile write data from PC+4, alu output, and memory data
dp_wdata_mux wdata_mux(wdsel,pc_plus_4,mem_addr,mem_rd_data,wdata);
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 18
Beta Control Signals
ILL
XAdr OP JT
PCSEL 4 3 2 1 0 Step 1: identify memories
PC 00
1 Step 2: identify datapaths
A Instruction
Memory
What’s left is random logic …
D
+4
Ra: <20:16> Rb: <15:11> Rc: <25:21>
0 1 RA2SEL
2 + WASEL
XP 1
RA1 Register RA2
WD
1
PC
Rc: <25:21> WA
WA
File
0
RD1 RD2 WE WERF
Z
JT
C: SXT(<15:0>)
PC+4+4*SXT(C)
IRQ Z
ASEL 1 0 1 0 BSEL
Control Logic
PCSEL
RA2SEL A B
ASEL ALU WD R/W Wr
ALUFN
BSEL
WDSEL Data Memory
ALUFN Adr RD
Wr
WERF
WASEL
PC+4 1
0 1 2 WDSEL
2
Main Datapath
6.884 – Spring 2005 02/09/05 T01 – Verilog 19
Beta Control Signals
6.884 – Spring 2005 02/09/05 T01 – Verilog 20
module control( ... );
// Control ROM
reg [15:0] ctl;
always @(*)
Beta Control Unit
begin
if (interrupt)
ctl = 16'bx_100_1xx_xxxxxx_00_0;
else
case (inst[31:26])
// Label control signal vector here ...
default: ctl = 16'bx_011_1xx_xxxxxx_00_0; // illegal opcode
6'b011000: ctl = 16'bx_000_001_00xxx0_10_0; // LD
6'b011001: ctl = 16'bx_000_x01_00xxx0_10_1; // ST
6'b011011: ctl = 16'bx_010_0xx_xxxxxx_00_0; // JMP
6'b011101: ctl = 16'b1_001_0xx_xxxxxx_00_0; // BEQ
6'b011110: ctl = 16'b0_001_0xx_xxxxxx_00_0; // BNE
6'b011111: ctl = 16'bx_000_010_011010_10_0; // LDR
...
6'b111100: ctl = 16'bx_000_001_10xx00_01_0; // SHLC
6'b111101: ctl = 16'bx_000_001_10xx01_01_0; // SHRC
6'b111110: ctl = 16'bx_000_001_10xx11_01_0; // SRAC
endcase
end
// We now use the local control signal vector to create the
// appropriate named control signals.
assign werf = ~ctl[0];
assign mem_we = !reset & ctl[0];
assign wdsel = ctl[2:1];
assign alufn = ctl[8:3];
assign bsel = ctl[9];
assign asel = ctl[10];
assign wa = ctl[11] ? 5'b11110 : inst[25:21];
assign pcsel = ((ctl[14:12] == 3'b001) & (ctl[15] ^ z)) ? 3'b000 : ctl[14:12];
assign ra2 = ctl[0] ? inst[25:21] : inst[15:11];
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 21
module beta
(
Putting It
input
input
input
clk,
reset,
irq,
All Together
output [31:0] inst_addr, // address of instruction to be fetched
input [31:0] inst_data, // instruction returning from memory
output [31:0] mem_addr, // address of data word to be accessed
input [31:0] mem_rd_data, // read data returning from memory
output mem_we, // memory write enable, active high
output [31:0] mem_wr_data // memory write data
);
// ... declare a bunch of internal signals here ...
// Control logic, reg file address generation
control ctl(reset,irq,inst_addr[31],z,inst_data[31:0],
alufn,asel,bsel,pcsel,ra2,wa,wdsel,werf,mem_we);
// PC Datapath
pc pc(clk,reset,pcsel,inst_data[15:0],jump_addr,branch_addr,
inst_addr,pc_plus_4);
// Register file
regfile regfile(inst_data[20:16],rd1,ra2,rd2,clk,werf,wa,wdata);
// Main datapath
datapath dp(inst_data[15:0],rd1,rd2,pc_plus_4,branch_addr,mem_rd_data,
asel,bsel,wdsel,alufn,
wdata,mem_addr,jump_addr,mem_wr_data,z);
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 22
Building Beta + Running Programs
% setup 6.884
% setup 6.004
% vcs –PP +lint=all +v2k beta.v
% uasm2vmh.pl self_test.uasm self_test.vmh
% ./simv +exe=self_test.vmh
*** PASSED ***
% ./mkasic.pl –v config/beta.cfg vcs
% ./mkasic.pl –v config/beta.cfg mktests
% ./mkasic.pl –v config/beta.cfg vcstest
Use different config files for different design
points – for example, try out different adder
implementations or synthesis constraints and
modular testing
6.884 – Spring 2005 02/09/05 T01 – Verilog 23
Lab1
Implement a 2 stage
pipelined processor
which supports SMIPS
ISA subset
– The SMIPS Processor
Spec is on the website
– Feel free to grab some
code from the Beta
implementation, but then
again the Beta code is not
always the best approach
6.884 – Spring 2005 02/09/05 T01 – Verilog 24
Lab1
Pipelined
Datapath
6.884 – Spring 2005 02/09/05 T01 – Verilog 25
Lab1 Test Harness
iaddr
instr tohost
fromhost
addr
wen mips_cpu
write_data
read_data
clk reset interrupt
6.884 – Spring 2005 02/09/05 T01 – Verilog 26
Lab1 Test Harness
`include "mips_cpu.v"
module mips_tester;
reg clk = 0; // Clock to core.
reg reset = 0; // Reset signal.
reg int_ext = 0; // Interrupt signal.
reg [7:0] fromhost = 8'b0; // Control reg to CPU.
wire [7:0] tohost; // Control reg from CPU.
wire [31:0] addr; // Data address.
wire wen; // Write enable.
wire [31:0] read_data; // Read data back to CPU.
wire [31:0] write_data; // Write data from CPU.
wire [31:0] iaddr; // Fetch address.
wire [31:0] inst; // Instruction.
always #5 clk = ~clk; // Clock generator (10ns clock period)
reg [ 1023:0 ] exe_filename;
mips_cpu mips(clk, reset, int_ext, fromhost, tohost,
addr, wen, write_data, read_data, iaddr, inst);
memory mem(clk, addr, wen, write_data, read_data, iaddr, inst);
...
6.884 – Spring 2005 02/09/05 T01 – Verilog 27
Lab1 Test Harness
...
initial
begin
$vcdpluson(0);
if( $value$plusargs( "exe=%s", exe_filename ) )
$readmemh( exe_filename, mem.m );
else begin
$display( "ERROR: No executable specified! (use +exe=<filename>)" );
$finish;
end
#0 reset = 1; #16 reset = 0; // Strobe reset
#10000; // Safety net to catch infinite loops
$display("*** FAILED ***");
$finish;
end
// Stop running when tohost changes.
always @(tohost) begin
case (tohost)
8'd0: ;
8'd1: begin $display("*** PASSED ***"); #20 $finish; end
default: begin $display("*** FAILED ***"); #20 $stop; end
endcase
end
endmodule
6.884 – Spring 2005 02/09/05 T01 – Verilog 28
Building Tests with smips-testbuild
SMIPS SMIPS SMIPS Verilog
Assembly gcc Object ld Elf
elf2vmh Memory
File File Binary Dump
(.S) (.o) (.vmh)
% smips-testbuild –vmh –smips self_test.S –o self_test.vmh
% mips2stage +exe=self_test.vmh
*** PASSED ***
% ./mkasic.pl config/mips2stage.cfg mktests
% ./mkasic.pl config/mips2stage.cfg vcstest
* Running tests on mips2stage/vcs/mips2stage simulator
+ [ PASSED ] simple_test.vmh
+ [ PASSED ] self_test.vmh
6.884 – Spring 2005 02/09/05 T01 – Verilog 29
Final Notes
Tools must be run either on Athena/Linux or CAG
– 38-301 is open 24 hours a day
– smips-testbuild should be working this afternoon
– CAG toolflow not quite setup yet
Lab is due at the start of class on Friday, Feb 18
– Write lots of tests (self_test is not enough!)
– We will email more information on exact collection procedure
Online resources
– Links to various Verilog whitepaper and references
– First chapter of Sutherland’s logical effort book
Office hours
– Tuesday + Thursday, 5:30pm – 7:00pm, 38-301
6.884 – Spring 2005 02/09/05 T01 – Verilog 30