VLSI DESIGN AUTOMATIONHomework 4Update “Multiplication” functionfor CPU and writing test benchVLSI DESIGN AUTOMATIONVLSI DESIGN AUTOMATIONHomework 4Update “Multiplication” functionfor CPU and writing test benchVLSI DESIGN AUTOMATIONHomework 4Update “Multiplication” functionfor CPU and writing test benchHomework 4Update “Multiplication” functionfor CPU and writing test bench
Trang 1VLSI DESIGN AUTOMATION
Homework #4
Update “Multiplication” function for CPU and writing test bench
Student: Bui Huu Nguyen
Student ID: 2016310539 Submit date: 2016/11/03
Trang 2A Update CPU code that has “Multiplication” function
// Project: Simple CPU
// File : CPU_Defs.sv
package cpu_defs;
parameter WORD_W = 8;
parameter OP_W = 3;
enum logic[2:0]
{
LOAD=3'b000,
STORE=3'b001,
ADD=3'b010,
SUB=3'b011,
BNE=3'b100,
MUL = 3'b101 // add multiply function
} opcodes;
endpackage
// Project: Simple CPU
// File : CPU.sv
//
import cpu_defs::*;
module CPU (input logic clock, n_reset, inout wire [WORD_W-1:0] sysbus);
CPU_bus bus (.*);
sequencer s1 (.*);
IR i1 (.*);
PC p1 (.*);
ALU a1 (.*);
RAM r1 (.*);
endmodule
// Project: Simple CPU
// File : PC.sv
//
import cpu_defs::*;
module PC (CPU_bus.PC_port bus);
logic [WORD_W-OP_W-1:0] count;
assign bus.sysbus = bus.PC_bus ?
{{OP_W{1'b0}},count} : 'z;
always_ff @(posedge bus.clock, negedge
bus.n_reset)
begin
if (!bus.n_reset)
count <= 0;
else
if (bus.load_PC)
if (bus.INC_PC)
count <= count + 1;
else
count <= bus.sysbus;
end
endmodule
// Project: Simple CPU
// File : IR.sv
//
import cpu_defs::*;
module IR (CPU_bus.IR_port bus);
logic [WORD_W-1:0] instr_reg;
assign bus.sysbus = bus.Addr_bus ? {{OP_W{1'b0}},instr_reg[WORD_W-OP_W-1:0]} : 'z;
always_comb bus.op = instr_reg[WORD_W-1:WORD_W-OP_W];
always_ff @(posedge bus.clock, negedge bus.n_reset)
begin
if (!bus.n_reset) instr_reg <= 0;
else
if (bus.load_IR) instr_reg <= bus.sysbus;
end endmodule
Trang 3// Project: Simple CPU
// File : CPU_Bus_IF.sv
//
import cpu_defs::*;
interface CPU_bus (input logic clock, n_reset,
inout wire [WORD_W-1:0] sysbus);
logic ACC_bus, load_ACC, PC_bus, load_PC,
load_IR,
load_MAR, MDR_bus, load_MDR, ALU_ACC,
ALU_add,
ALU_sub,ALU_mul,INC_PC, Addr_bus, CS, R_NW,
z_flag, ov_add_flag, ov_mul_flag;
logic [OP_W-1:0] op;
modport IR_port(
input clock, n_reset, Addr_bus, load_IR,
inout sysbus,
output op);
modport RAM_port (
input clock, n_reset, MDR_bus,
load_MDR, load_MAR, CS, R_NW,
inout sysbus);
modport ALU_port (
input clock, n_reset, ACC_bus,
load_ACC, ALU_ACC, ALU_add, ALU_sub,
ALU_mul,
inout sysbus,
output z_flag, ov_add_flag, ov_mul_flag);
modport PC_port (
input clock, n_reset, PC_bus, load_PC, INC_PC,
inout sysbus);
modport seq_port (input clock, n_reset, z_flag,
ov_add_flag, ov_mul_flag,
input op,
output ACC_bus, load_ACC, PC_bus,
load_PC, load_IR, load_MAR,
MDR_bus, load_MDR, ALU_ACC,
ALU_add, ALU_sub, ALU_mul, INC_PC,
Addr_bus, CS, R_NW);
endinterface
// Project: Simple CPU
// File : ALU.sv
//
import cpu_defs::*;
module ALU (CPU_bus.ALU_port bus);
logic [WORD_W-1:0] acc;
logic [WORD_W-1:0] overflow_add;
logic [WORD_W-1:0] overflow_mul;
assign bus.sysbus = bus.ACC_bus ? acc : 'z; assign bus.z_flag = acc == 0 ? '1 : '0;
assign bus.ov_add_flag = overflow_add != 0 ? '1 : '0;
assign bus.ov_mul_flag = overflow_mul != 0 ? '1 : '0;
always_ff @(posedge bus.clock, negedge bus.n_reset)
begin
if (!bus.n_reset) begin
acc <= 0;
overflow_mul<=0;
overflow_add <=0;
end else
if (bus.load_ACC)
if (bus.ALU_ACC) begin
if (bus.ALU_add)
{overflow_add,acc} <= acc + bus.sysbus;
else if (bus.ALU_sub) acc <= acc - bus.sysbus;
else if (bus.ALU_mul) // multi function
{overflow_mul,acc} <= acc * bus.sysbus; // multiplication function
end else acc <= bus.sysbus;
end // always_ff endmodule
Trang 4// Project: Simple CPU
// File : RAM.sv
//
import cpu_defs::*;
module RAM (CPU_bus.RAM_port bus);
logic [WORD_W-1:0] mdr;
logic [WORD_W-OP_W-1:0] mar;
logic [WORD_W-1:0] mem
[0:(1<<(WORD_W-OP_W))-1];
int i;
assign bus.sysbus = bus.MDR_bus ? mdr : 'z;
always_ff @(posedge bus.clock, negedge
bus.n_reset)
begin
if (!bus.n_reset)
begin
mdr <= 0;
mar <= 0;
mem[0] <= {LOAD, 5'd16};// check add function
mem[1] <= {ADD, 5'd17};
mem[2] <= {STORE, 5'd18};
mem[3] <= {LOAD, 5'd19};// check sub function
mem[4] <= {SUB, 5'd20};
mem[5] <= {STORE, 5'd21};
mem[6] <= {LOAD, 5'd22}; // check mul function
mem[7] <= {MUL, 5'd23};
mem[8] <= {STORE, 5'd24};
mem[9] <= {LOAD, 5'd25}; // check overflow add
mem[10] <= {ADD, 5'd26};
mem[11] <= {STORE, 5'd27};
mem[12] <= {LOAD, 5'd28}; //check overflow mul
mem[13] <= {MUL, 5'd29};
mem[14] <= {STORE,5'd30};
mem[15] <= 0;
mem[16] <= 3;
mem[17] <= 10;
mem[18] <= 0;
mem[19] <= 120;
mem[20] <= 20;
mem[21] <= 0;
mem[22] <= 8;
mem[23] <= 10;
mem[24] <= 0;
mem[25] <= 140;
mem[26] <= 150;
mem[27] <= 0;
mem[28] <= 100;
mem[29] <= 10;
mem[30] <= 0;
mem[31] <= 0;
end // if (!bus.n_reset) else
if (bus.load_MAR) mar <= bus.sysbus[WORD_W-OP_W-1:0]; else if (bus.load_MDR)
mdr <= bus.sysbus;
else if (bus.CS)
if (bus.R_NW) mdr <= mem[mar];
else mem[mar] <= mdr;
end // always_ff endmodule
Trang 5// Project: Simple CPU
// File : Sequencer.sv
//
import cpu_defs::*;
module sequencer (CPU_bus.seq_port bus);
enum {
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10
} state;
always_ff @(posedge bus.clock, negedge
bus.n_reset)
begin: seq
if (!bus.n_reset)
state <= s0;
else
case (state)
s0: state <= s1;
s1: state <= s2;
s2: state <= s3;
s3: if (bus.op == STORE)
state <= s4;
else
state <= s6;
s4: state <= s5;
s5: state <= s0;
s6: if (bus.op == LOAD)
state <= s7;
else if (bus.op == BNE)
if (bus.z_flag)
state <= s9;
else
state <= s10;
else
state <= s8;
s7: state <= s0;
s8: state <= s0;
s9: state <= s0;
s10: state <= s0;
endcase // state
end // always_ff
always_comb
begin: com
// reset all the control signals to default
bus.ACC_bus = '0;
bus.load_ACC = '0;
bus.PC_bus = '0;
bus.load_PC = '0;
bus.load_IR = '0;
bus.load_MAR = '0;
bus.MDR_bus = '0;
bus.load_MDR = '0;
bus.ALU_ACC = '0;
bus.ALU_add = '0;
bus.ALU_sub = '0;
bus.ALU_mul = '0; // bus of multiply bus.INC_PC = '0;
bus.Addr_bus = '0;
bus.CS = '0;
bus.R_NW = '0;
case (state) s0: begin bus.PC_bus = '1;
bus.load_MAR = '1;
bus.INC_PC = '1;
bus.load_PC = '1;
end s1: begin bus.CS = '1;
bus.R_NW = '1;
end s2: begin bus.MDR_bus = '1;
bus.load_IR = '1;
end s3: begin bus.Addr_bus = '1;
bus.load_MAR = '1;
end s4: begin bus.ACC_bus = '1;
bus.load_MDR = '1;
end s5: begin bus.CS = '1;
end s6: begin bus.CS = '1;
bus.R_NW = '1;
end s7: begin bus.load_ACC = '1;
Trang 6s8: begin
bus.MDR_bus = '1;
bus.ALU_ACC = '1;
bus.load_ACC = '1;
if (bus.op == ADD)
bus.ALU_add = '1;
else if (bus.op == SUB)
bus.ALU_sub = '1;
else if (bus.op == MUL) //
bus.ALU_mul = '1; // add multiply
end
s9: begin bus.MDR_bus = '1;
bus.load_PC = '1;
end s10: begin
bus.load_PC = '1; //
bus.INC_PC = '0; //
bus.MDR_bus = '1; // add multiply MUL = 3'b101
end endcase // state end // always_comb endmodule
// Project: Simple CPU
// CPU_test bench.sv
`timescale 1 ns / 100 ps
import cpu_defs::*;
module CPU_tb();
reg clock, n_reset;
wire [WORD_W-1:0] sysbus;
// Clock generator
initial begin
clock=0;
forever #10 clock=~clock;
end
initial begin
n_reset=0;
@(posedge clock)
n_reset=1;
end
CPU CPU_u1(clock, n_reset, sysbus);
endmodule
B Results simulation
1 mem[0] <= {LOAD, 5'd16};// check add
function
mem[1] <= {ADD, 5'd17};
mem[2] <= {STORE, 5'd18};…………
……
mem[16] <= 3;
mem[17] <= 10;
Discussion: Step1, at mem[1] region, CPU load data
from “mem[16]“ region to “acc” register in ALU block Step2, at mem[1], CPU load data from “mem[17]” to
“sysbus” then operate summation between “acc” with
“sysbus” and store in “acc” register Step3, at mem[2], store data in “acc” register into “mem[18]” region
Result: 3+10 = 13 in acc and mem[18]
Trang 72 mem[3] <= {LOAD, 5'd19};// check sub
function
mem[4] <= {SUB, 5'd20};
mem[5] <= {STORE, 5'd21}; ………
……
mem[19] <= 120;
mem[20] <= 20;
Discussion: Step4, at mem[3] region, CPU load data
from “mem[19]“ region to “acc” register in ALU block Step5, at mem[4], CPU load data from “mem[20]” to
“sysbus” then operate subtraction between “acc” with “sysbus” and store in “acc” register Step6, at
mem[5], store data in “acc” register into “mem[21]”
region
Result: 120-20 = 100 in acc and mem[21]
3 mem[6] <= {LOAD, 5'd22}; // check mul
function
mem[7] <= {MUL, 5'd23};
mem[8] <= {STORE, 5'd24};………
……
mem[22] <= 8;
mem[23] <= 10;
Discussion: Step7, at mem[6] region, CPU load data
from “mem[22]“ region to “acc” register in ALU block Step8, at mem[7], CPU load data from “mem[23]” to
“sysbus” then operate multiplication between “acc” with “sysbus” and store in “acc” register Step9, at
mem[8], store data in “acc” register into “mem[24]”
region
Result: 8*10 = 80 in acc and mem[21]
Load data (3) from mem[16] to acc Add
Load data (10) from mem[17] to sysbus Store result in acc
Load data (120) from mem[19] to acc Sub
Load data (20) from mem[20] to sysbus Store result in acc
Trang 84 mem[9] <= {LOAD, 5'd25}; // check
overflow add
mem[10] <= {ADD, 5'd26};
mem[11] <= {STORE, 5'd27};………
……
mem[25] <= 140;
mem[26] <= 150;
Discussion: Step10, at mem[9] region, CPU load data
from “mem[25]“ region to “acc” register in ALU block Step11, at mem[10], CPU load data from “mem[26]”
to “sysbus” then operate summation between “acc” with “sysbus” and store in “acc” register Step12, at
mem[11], store data in “acc” register into “mem[27]”
region
Result: 140*150 = 290 or 8d(290-256) = 8d34 in acc
and mem[21] Due value 290 lager than 256 so ov_add_flag == 1.
5 mem[12] <= {LOAD, 5'd28}; //check
overflow mul
mem[13] <= {MUL, 5'd29};
mem[14] <= {STORE,5'd30};……
……
mem[28] <= 100;
mem[29] <= 10;
Discussion: Step13, at mem[12] region, CPU load data
from “mem[28]“ region to “acc” register in ALU block Step14, at mem[13], CPU load data from “mem[29]”
to “sysbus” then operate multiplication between
“acc” with “sysbus” and store in “acc” register Step15,
at mem[14], store data in “acc” register into
“mem[30]” region
Load data (8) from mem[22] to acc Mul
Load data (10) from mem[23] to sysbus Store result in acc
Load data (140 or -8d116) from mem[25]
to acc
Add
Load data (150 or -8d106 ) from mem[26] to sysbus
Store result in acc
ov_add_flag
Trang 9Result: 100*10 = 1000 or 8d(1000-4*256) = -8d24
in acc and mem[30] Due value 1000 lager than 256 so ov_mul_flag == 1.
Load data (100) from mem[25] to acc Mul
Load data (10) from mem[29] to sysbus Store result in acc
ov_mul_flag