Tải bản đầy đủ (.pdf) (9 trang)

Homework 4 Update “Multiplication” function for CPU

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (544.44 KB, 9 trang )

VLSI 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


A. 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 : 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 : 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 : 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_WOP_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


// Project: Simple CPU
// File : CPU_Bus_IF.sv
//
import cpu_defs::*;


// Project: Simple CPU
// File : ALU.sv
//
import cpu_defs::*;

interface CPU_bus (input logic clock, n_reset,
inout wire [WORD_W-1:0] sysbus);

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;

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

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


// 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_WOP_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


// 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.MDR_bus = '1;

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;
end



s8: 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]


Load data (10) from mem[17] to sysbus

Load data (3) from mem[16] to acc

2

mem[3] <= {LOAD, 5'd19};// check sub
function
mem[4] <= {SUB, 5'd20};
mem[5] <= {STORE, 5'd21}; ……….
…….
mem[19] <= 120;
mem[20] <= 20;

Load data (120) from mem[19] to acc

mem[6] <= {LOAD, 5'd22}; // check mul
function
mem[7] <= {MUL, 5'd23};
mem[8] <= {STORE, 5'd24};……….
…….
mem[22] <= 8;
mem[23] <= 10;

Add


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]

Load data (20) from mem[20] to sysbus

3

Store result in acc

Store result in acc

Sub

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 (10) from mem[23] to sysbus

Store result in acc

Mul

Load data (8) from mem[22] to acc

4

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.

Load data (150 or -8d106 ) from mem[26] to

sysbus

Store result in acc

Load data (140 or -8d116) from mem[25]
to acc

Add

ov_add_flag

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.



Result: 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 (10) from mem[29] to sysbus

Store result in acc

Load data (100) from mem[25] to acc

Mul

ov_mul_flag



×