MÃ VERILOG CHO CPU RISC

Một phần của tài liệu Thiết kế CPU RISC đa chu kỳ 32 bit (Trang 60 - 71)

//file mips multi processor.v:

module mips_multi(clk, reset);

input clk, reset;

// instruction bus wire [31:0] instr;

// break out important fields from instruction wire [5:0] opcode, funct;

wire [4:0] rs, rt, rd, shamt;

wire [15:0] immed;

wire [31:0] extend_immed, b_offset;

wire [25:0] j_offset;

wire [31:0] j_addr;

assign opcode = instr[31:26];

assign rs = instr[25:21];

assign rt = instr[20:16];

assign rd = instr[15:11];

assign shamt = instr[10:6];

assign funct = instr[5:0];

assign immed = instr[15:0];

assign j_offset = instr[25:0];

// sign-extender

assign extend_immed = { {16{immed[15]}}, immed };

// branch offset shifter

assign b_offset = extend_immed << 2;

// datapath signals wire [4:0] rfile_wn;

wire [31:0] pc, pc_next, mem_addr, mem_rd, mdr, rfile_wd, rfile_rd1, rfile_rd2, a, b, alu_a, alu_b, aluout_in, aluout;

// jump address

assign j_addr = { pc[31:28], j_offset, 2'b0 };

// control signals

wire PCWriteEnable, PCWriteBr, PCWrite, PCWriteCond, Zero, IRWrite, IorD,

MemRead, MemWrite, MemtoReg, RegWrite, RegDst, ALUSrcA;

wire [1:0] ALUOp, ALUSrcB, PCSource;

wire [2:0] Operation;

// module instantiations

reg32en PC(clk, reset, PCWriteEnable, pc_next, pc);

mux2 MEM_MUX(IorD, pc, aluout, mem_addr);

mem32 MEM(clk, MemRead, MemWrite, mem_addr, b, mem_rd);

reg32en IR(clk, reset, IRWrite, mem_rd, instr);

reg32 MDR(clk, reset, mem_rd, mdr);

reg_file RFILE(clk, RegWrite, rs, rt, rfile_wn, rfile_rd1, rfile_rd2, rfile_wd);

mux2 RFMUX(MemtoReg, aluout, mdr, rfile_wd);

mux2 #(5) RFWNMUX(RegDst, rt, rd, rfile_wn);

reg32 A(clk, reset, rfile_rd1, a);

reg32 B(clk, reset, rfile_rd2, b);

mux2 ALUMUXA(ALUSrcA, pc, a, alu_a);

mux4 ALUMUXB(ALUSrcB, b, 32'd4, extend_immed, b_offset, alu_b);

alu ALU(Operation, alu_a, alu_b, aluout_in, Zero);

reg32 ALUOUT(clk, reset, aluout_in, aluout);

mux3 PCMUX(PCSource, aluout_in, aluout, j_addr, pc_next);

and BR_AND(PCWriteBr, PCWriteCond, Zero);

or PC_OR(PCWriteEnable, PCWriteBr, PCWrite);

control_multi CTL(.clk(clk), .reset(reset), .Op(opcode), .PCWrite(PCWrite), .PCWriteCond(PCWriteCond), .IorD(IorD), .MemRead(MemRead), .MemWrite(MemWrite), .MemtoReg(MemtoReg), .IRWrite(IRWrite), .PCSource(PCSource), .ALUOp(ALUOp), .ALUSrcB(ALUSrcB), .ALUSrcA(ALUSrcA),

.RegWrite(RegWrite), .RegDst(RegDst));

alu_ctl ALUCTL(ALUOp, funct, Operation);

endmodule

//file control-multi.v

module control_multi( clk, reset, Op, PCWrite, PCWriteCond, IorD, MemRead, MemWrite,

MemtoReg, IRWrite, PCSource, ALUOp, ALUSrcB, ALUSrcA, RegWrite, RegDst );

input clk;

input reset;

input [5:0] Op;

output PCWrite;

output PCWriteCond;

output IorD;

output MemRead;

output MemWrite;

output MemtoReg;

output IRWrite;

output [1:0] PCSource;

output [1:0] ALUOp;

output ALUSrcA;

output [1:0] ALUSrcB;

output RegWrite;

output RegDst;

reg PCWrite;

reg PCWriteCond;

reg IorD;

reg MemRead;

reg MemWrite;

reg MemtoReg;

reg IRWrite;

reg [1:0] PCSource;

reg [1:0] ALUOp;

reg ALUSrcA;

reg [1:0] ALUSrcB;

reg RegWrite;

reg RegDst;

// Symbolic constants for Opcodes parameter R_FORMAT = 6'd0;

parameter LW = 6'd35;

parameter SW = 6'd43;

parameter BEQ = 6'd4;

parameter ADDI = 6'd8;

parameter J = 6'd2;

reg [3:0] current_state, next_state;

// State Codes for FSM

parameter S0=4'd0, S1=4'd1, S2=4'd2, S3=4'd3, S4=4'd4,

S5=4'd5, S6=4'd6, S7=4'D7, S8=4'd8, S9=4'd9, ERROR=4'bxxxx;

// State Register

always @(posedge clk)

if (reset) current_state <= S0;

else current_state <= next_state;

// Next-State & Output Logic

always @(current_state or Op or reset) begin

// default values PCWrite = 1'b0;

PCWriteCond = 1'b0;

IorD = 1'bx;

MemRead = 1'b0;

MemWrite = 1'b0;

MemtoReg = 1'bx;

IRWrite = 1'b0;

PCSource = 2'bxx;

ALUOp = 2'bxx;

ALUSrcA = 1'bx;

ALUSrcB = 2'bxx;

RegWrite = 1'b0;

RegDst = 1'bx;

if (reset) next_state = S0;

else case (current_state) S0: begin

MemRead = 1'b1;

ALUSrcA = 1'b0;

IorD = 1'b0;

IRWrite = 1'b1;

ALUSrcB = 2'b01;

ALUOp = 2'b00;

PCWrite = 1'b1;

PCSource = 2'b00;

next_state = S1;

end S1: begin

ALUSrcA = 1'b0;

ALUSrcB = 2'b11;

ALUOp = 2'b00;

case (Op)

LW, SW: next_state = S2;

R_FORMAT: next_state = S6;

BEQ: next_state = S8;

J: next_state = S9;

default: next_state = ERROR;

endcase end S2: begin

ALUSrcA = 1'b1;

ALUSrcB = 2'b10;

ALUOp = 2'b00;

case (Op)

LW: next_state = S3;

SW: next_state = S5;

default: next_state = ERROR;

endcase end S3: begin

MemRead = 1'b1;

IorD = 1'b1;

next_state = S4;

end S4: begin

RegDst = 1'b0;

RegWrite = 1'b1;

MemtoReg = 1'b1;

next_state = S0;

end S5: begin

MemWrite = 1'b1;

IorD = 1'b1;

next_state = S0;

end S6: begin

ALUSrcA = 1'b1;

ALUSrcB = 2'b00;

ALUOp = 2'b10;

next_state = S7;

end S7: begin

RegDst = 1'b1;

RegWrite = 1'b1;

MemtoReg = 1'b0;

next_state = S0;

end S8: begin

ALUSrcA = 1'b1;

ALUSrcB = 2'b00;

ALUOp = 2'b01;

PCWriteCond = 1'b1;

PCSource = 2'b01;

next_state = S0;

end S9: begin

PCWrite = 1'b1;

PCSource = 2'b10;

next_state = S0;

end

default: next_state = S0;

endcase end // always endmodule

//file ALU.v

module alu(ctl, a, b, result, zero);

input [2:0] ctl;

input [31:0] a, b;

output [31:0] result;

output zero;

reg [31:0] result;

reg zero;

always @(a or b or ctl) begin

case (ctl)

3'b000 : result = a & b; // AND 3'b001 : result = a | b; // OR 3'b010 : result = a + b; // ADD

3'b110 : result = a - b; // SUBTRACT 3'b111 : if (a < b) result = 32'd1;

else result = 32'd0; //SLT default : result = 32'hxxxxxxxx;

endcase

if (result == 32'd0) zero = 1;

else zero = 0;

end

endmodule

//file ALU control unit.v

module alu_ctl(ALUOp, Funct, ALUOperation);

input [1:0] ALUOp;

input [5:0] Funct;

output [2:0] ALUOperation;

reg [2:0] ALUOperation;

// symbolic constants for instruction function code parameter F_add = 6'd32;

parameter F_sub = 6'd34;

parameter F_and = 6'd36;

parameter F_or = 6'd37;

parameter F_slt = 6'd42;

// symbolic constants for ALU Operations parameter ALU_add = 3'b010;

parameter ALU_sub = 3'b110;

parameter ALU_and = 3'b000;

parameter ALU_or = 3'b001;

parameter ALU_slt = 3'b111;

always @(ALUOp or Funct) begin

case (ALUOp)

2'b00 : ALUOperation = ALU_add;

2'b01 : ALUOperation = ALU_sub;

2'b10 : case (Funct)

F_add : ALUOperation = ALU_add;

F_sub : ALUOperation = ALU_sub;

F_and : ALUOperation = ALU_and;

F_or : ALUOperation = ALU_or;

F_slt : ALUOperation = ALU_slt;

default ALUOperation = 3'bxxx;

endcase

default ALUOperation = 3'bxxx;

endcase end

endmodule //file mem32.v

module mem32(clk, mem_read, mem_write, address, data_in, data_out);

input clk, mem_read, mem_write;

input [31:0] address, data_in;

output [31:0] data_out;

reg [31:0] data_out;

parameter BASE_ADDRESS = 25'd0; // address that applies to this memory - change if desired

reg [31:0] mem_array [0:31];

wire [4:0] mem_offset;

wire address_select;

assign mem_offset = address[6:2]; // drop 2 LSBs to get word offset

assign address_select = (address[31:7] == BASE_ADDRESS); // address decoding always @(mem_read or address_select or mem_offset or mem_array[mem_offset]) begin

if (mem_read == 1'b1 && address_select == 1'b1) begin

if ((address % 4) != 0)

$display($time, " rom32 error: unaligned address %d", address);

data_out = mem_array[mem_offset];

$display($time, " reading data: Mem[%h] => %h", address, data_out);

end

else data_out = 32'hxxxxxxxx;

end

// for WRITE operations always @(posedge clk) begin

if (mem_write == 1'b1 && address_select == 1'b1) begin

$display($time, " writing data: Mem[%h] <= %h", address,data_in);

mem_array[mem_offset] <= data_in;

end end

// initialize with some arbitrary values integer i;

initial begin

mem_array[0] = { 6'd35, 5'd0, 5'd2, 16'd36 }; // x00 l2 $2, 36($0) r2=1 mem_array[1] = { 6'd35, 5'd0, 5'd3, 16'd40 }; // x04 lw $3, 40($0) r3=2 mem_array[2] = { 6'd35, 5'd0, 5'd4, 16'd52 }; // x08 lw $4, 52($0) r4=5 mem_array[3] = { 6'd0, 5'd0, 5'd0, 5'd5, 5'd0, 6'd32 }; // x0C add $5, $0, $0 r5=0 mem_array[4] = { 6'd0, 5'd5, 5'd2, 5'd5, 5'd0, 6'd32 }; // x10 add $5, $5, $1 r5 = r5 + 1

mem_array[5] = { 6'd0, 5'd4, 5'd5, 5'd6, 5'd0, 6'd42 }; // x14 slt $6, $4, $5 is $5 >

54?

mem_array[6] = { 6'd4, 5'd6, 5'd0, -16'd3 }; // x18 beq $6, $zero, -3 if not, go back 2

mem_array[7] = { 6'd43, 5'd0, 5'd5, 16'd64 }; // x1C sw $5, 0($0) MEM[64] = $5

mem_array[8] = { 6'd2, 26'd0 }; // x20 j 0 goto 0

for (i=1; i<7; i=i+1) mem_array[i+8] = i; // MEM[x24]=1; MEM[x28]=2; , etc.

end endmodule //file reg-file.v

module reg_file(clk, RegWrite, RN1, RN2, WN, RD1, RD2, WD);

input clk;

input RegWrite;

input [4:0] RN1, RN2, WN;

input [31:0] WD;

output [31:0] RD1, RD2;

reg [31:0] RD1, RD2;

reg [31:0] file_array [31:1];

always @(RN1 or file_array[RN1]) begin

if (RN1 == 0) RD1 = 32'd0;

else RD1 = file_array[RN1];

$display($time, " reg_file[%d] => %d (Port 1)", RN1, RD1);

end

always @(RN2 or file_array[RN2]) begin

if (RN2 == 0) RD2 = 32'd0;

else RD2 = file_array[RN2];

$display($time, " reg_file[%d] => %d (Port 2)", RN2, RD2);

end

always @(posedge clk)

if (RegWrite && (WN != 0)) begin

file_array[WN] <= WD;

$display($time, " reg_file[%d] <= %d (Write)", WN, WD);

end endmodule //file reg32.v

module reg32 (clk, reset, d_in, d_out);

input clk, reset;

input [31:0] d_in;

output [31:0] d_out;

reg [31:0] d_out;

always @(posedge clk)

begin

if (reset) d_out <= 0;

else d_out <= d_in;

end endmodule //file reg32en.v

module reg32en (clk, reset, enable, d_in, d_out);

input clk, reset, enable;

input [31:0] d_in;

output [31:0] d_out;

reg [31:0] d_out;

always @(posedge clk) begin

if (reset) d_out <= 0;

else if (enable) d_out <= d_in;

end endmodule //file mux2.v

module mux2( sel, a, b, y );

parameter bitwidth=32;

input sel;

input [bitwidth-1:0] a, b;

output [bitwidth-1:0] y;

assign y = sel ? b : a;

endmodule //file mux3.v

module mux3(s, d0, d1, d2, y);

parameter bitwidth=32;

input [1:0] s;

input [bitwidth-1:0] d0, d1, d2;

output [bitwidth-1:0] y;

reg [bitwidth-1:0] y;

always @(d0 or d1 or d2 or s) case ( s)

2'd0 : y = d0;

2'd1 : y = d1;

2'd2 : y = d2;

default : y = {bitwidth{1'bx}};

endcase endmodule //file mux4.v

module mux4(s, d0, d1, d2, d3, y);

parameter bitwidth=32;

input [1:0] s;

input [bitwidth-1:0] d0, d1, d2, d3;

output [bitwidth-1:0] y;

reg [bitwidth-1:0] y;

always @(d0 or d1 or d2 or d3 or s) case ( s)

2'd0 : y = d0;

2'd1 : y = d1;

2'd2 : y = d2;

2'd3 : y = d3;

default : y = {bitwidth{1'bx}};

endcase endmodule

PHỤ LỤC 2:

Một phần của tài liệu Thiết kế CPU RISC đa chu kỳ 32 bit (Trang 60 - 71)

Tải bản đầy đủ (PDF)

(74 trang)