本設計分爲10個模塊加一個整體仿真激勵模塊,各模塊代碼如下:
流水燈的變換形式爲: 0000000 -> 00000001 -> 00000011 -> 00000111 -> 00001111 -> 00011111 -> 00111111 -> 01111111 -> 11111111
時間間隔爲1s。
`timescale 1ns / 1ps
//包括IR
module InsMem(
input CLK,
input InsMemRW, IRWre,
input [31:0] pc_out,
output reg [31:0] ins_out
);
reg [31:0] IDataOut;
reg [7:0] InsMemory[0:255];
initial begin
$readmemb("instructions.txt", InsMemory);
end
always @ (pc_out or InsMemRW) begin
if (InsMemRW) begin
IDataOut[31:24] = InsMemory[pc_out];
IDataOut[23:16] = InsMemory[pc_out+1];
IDataOut[15:8] = InsMemory[pc_out+2];
IDataOut[7:0] = InsMemory[pc_out+3];
end
end
always @ (posedge CLK) begin
if (IRWre)
ins_out <= IDataOut;
end
endmodule
module fp50m(clk,reset,newclk);
input clk,reset;
output newclk;
reg newclk;
reg [31:0] count,count1;
always@(posedge clk or negedge reset)
begin
if(!reset)
begin
newclk<=1'd0;
count<=32'd0;
end
else if(count==32'd1250000) //0.1s 2500000
begin
count<=32'd0;
newclk<=~newclk;
end//end begin
else count<=count+1'd1;
end
endmodule
`timescale 1ns / 1ps
module Extend(
input ExtSel,
input [15:0] Imm_16,
output reg [31:0] Imm
);
always @ (Imm_16 or ExtSel) begin
if (ExtSel) begin
Imm = {{16{Imm_16[15]}}, Imm_16[15:0]};
end else begin
Imm = {{16{0}}, Imm_16[15:0]};
end
end
endmodule
`timescale 1ns / 1ps
//包括2選1模塊,一個緩衝
module DataMem(
input RD, WR, CLK,
input ALUM2Reg,
input [31:0] alu_out,
input [31:0] result,
input [31:0] reg_out2,
output wire [31:0] data_out
);
reg [31:0] DataOut;
reg [7:0] DataMemory[0:63];
assign data_out = (ALUM2Reg ? DataOut : result);
always @ (alu_out or reg_out2 or RD or WR) begin
if (WR) begin //寫入
DataMemory[alu_out] = reg_out2[31:24];
DataMemory[alu_out+1] = reg_out2[23:16];
DataMemory[alu_out+2] = reg_out2[15:8];
DataMemory[alu_out+3] = reg_out2[7:0];
end else begin //讀出
DataOut[31:24] = DataMemory[alu_out];
DataOut[23:16] = DataMemory[alu_out+1];
DataOut[15:8] = DataMemory[alu_out+2];
DataOut[7:0] = DataMemory[alu_out+3];
end
//if (ALUM2Reg) data_out = DataOut;
//else data_out = result;
end
endmodule
`timescale 1ns / 1ps
module ControlUnit(
input CLK, RST,
input zero,
input [5:0] op,
output reg WrRegData, RegWre, ALUSrcA, ALUSrcB, InsMemRW, IRWre, PCWre, RD, WR, ExtSel, ALUM2Reg,
output reg [1:0] RegDst, PCSrc,
output reg [2:0] ALUOp, state
);
reg [2:0] next_state;
parameter [2:0] IF = 3'b000,
ID = 3'b001,
EXE_1 = 3'b110,
EXE_2 = 3'b101,
EXE_3 = 3'b010,
MEM = 3'b011,
WB_1 = 3'b111,
WB_2 = 3'b100;
parameter [5:0] _addu = 6'b000000,
_subu = 6'b000001,
_addiu = 6'b000010,
_or = 6'b010000,
_and = 6'b010001,
_ori = 6'b010010,
_sll = 6'b011000,
_sltu = 6'b100110,
_sltiu = 6'b100111,
_sw = 6'b110000,
_lw = 6'b110001,
_beq = 6'b110100,
_j = 6'b111000,
_jr = 6'b111001,
_jal = 6'b111010,
_halt = 6'b111111;
initial begin
PCWre = 0;
ALUSrcA = 0;
ALUSrcB = 0;
ALUM2Reg = 0;
RegWre = 0;
WrRegData = 0;
InsMemRW = 0;
RD = 0;
WR = 0;
IRWre = 0;
ExtSel = 0;
PCSrc = 2'b00;
RegDst = 2'b11;
ALUOp = 3'b000;
state = IF;
end
always @ (posedge CLK) begin // ״̬Ȑۻ
if (RST == 0) begin
state <= IF;
end else begin
state <= next_state;
end
end
always @ (op or state) begin
case (state)
IF: next_state = ID;
ID: begin
if (op == _j || op == _jal || op == _jr || op == _halt) next_state = IF;
else if (op == _sw || op == _lw) next_state = EXE_3;
else if (op == _beq) next_state = EXE_2;
else next_state = EXE_1;
end
EXE_1: next_state = WB_1;
EXE_2: next_state = IF;
EXE_3: next_state = MEM;
MEM: begin
if (op == _lw)
next_state = WB_2;
else
next_state = IF;
end
WB_1: next_state = IF;
WB_2: next_state = IF;
default: next_state = IF;
endcase
end
always @ (state or op) begin
//PCWre
if (state == IF && op != _halt) PCWre = 1;
else PCWre = 0;
//ALUSrcA
if (op == _sll) ALUSrcA = 1;
else ALUSrcA = 0;
//ALUSrcB
if (op == _addiu || op == _ori || op == _sltiu || op == _sw || op == _lw) ALUSrcB = 1;
else ALUSrcB = 0;
//ALUM2Reg
if (state == WB_2) ALUM2Reg = 1;
else ALUM2Reg = 0;
//RegWre
if (state == WB_1 || state == WB_2 || op == _jal) RegWre = 1;
else RegWre = 0;
//WrRegData
//if (state == WB_1 || state == WB_2) WrRegData = 1;
if (op == _jal) WrRegData = 0;
else WrRegData = 1;
//InsMemRW
InsMemRW = 1;
//RD
if (state == MEM && op == _lw) RD = 1;
else RD = 0;
//WR
if (state == MEM && op == _sw) WR = 1;
else WR = 0;
//IRWre
if (state == IF) IRWre = 1;
else IRWre = 0;
//ExtSel
if (state == EXE_1 && (op == _ori || op == _sll)) ExtSel = 0;
else ExtSel = 1;
//PCSrc
case (op)
_j: PCSrc = 2'b11;
_jal: PCSrc = 2'b11;
_jr: PCSrc = 2'b10;
_beq: begin
if (zero) PCSrc = 2'b01;
else PCSrc = 2'b00;
end
default: PCSrc = 2'b00;
endcase
//RegDst
if (op == _jal) RegDst = 2'b00;
else if (op == _addiu || op == _ori || op == _sltiu || op == _lw) RegDst = 2'b01;
else RegDst = 2'b10;
//ALUOp
case (op)
_subu: ALUOp = 3'b001;
_or: ALUOp = 3'b101;
_and: ALUOp = 3'b110;
_ori: ALUOp = 3'b101;
_sltu: ALUOp = 3'b010;
_sltiu: ALUOp = 3'b010;
_sll: ALUOp = 3'b100;
_beq: ALUOp = 3'b001;
default: ALUOp = 3'b000;
endcase
end
endmodule
`timescale 1ns / 1ps
//包括兩個2選1模塊,一個緩衝
module ALU(
input CLK, ALUSrcA, ALUSrcB,
input [2:0] ALUOp,
input [31:0] reg_out1, reg_out2,
input [31:0] ins_out, Imm,
input [31:0] sa,
output reg [31:0] result,
output reg [31:0] alu_out,
output zero
);
initial begin
result = 0;
end
wire [31:0] A, B;
assign A = (ALUSrcA ? sa : reg_out1);
assign B = (ALUSrcB ? Imm : reg_out2);
assign zero = (result ? 0 : 1);
always @ (A or B or ALUOp) begin
case (ALUOp)
3'b000: result = A + B;
3'b001: result = A - B;
3'b010: result = (A < B ? 1 : 0);
3'b011: result = B >> A;
3'b100: result = B << 1;
3'b101: result = A | B;
3'b110: result = A & B;
3'b111: result = (~A & B) | (A & ~B);
default: result = 0;
endcase
alu_out = result;
end
endmodule
`timescale 1ns / 1ps
//包括3選1模塊,2選1模塊,兩個緩衝
module RegFile(
input CLK,
input RegWre, WrRegData,
input [1:0] RegDst,
input [31:0] pc_out,
//input [31:0] PC4,
input [4:0] rs, rt, rd,
input [31:0] data_out,
output reg [31:0] reg_out1, reg_out2,
output reg [31:0] ReadData1, ReadData2,
output wire [31:0] WriteData,
output reg [4:0] WriteReg,
output wire [7:0] pin_out
);
reg [31:0] register[0:31];
initial begin
register[0] = 0;
end
assign pin_out = (register[1][15:8]);
assign WriteData = (WrRegData ? data_out : (pc_out + 4));
always @ (negedge CLK) begin
case (RegDst)
2'b00: WriteReg <= 5'b11111; //$31
2'b01: WriteReg <= rt;
2'b10: WriteReg <= rd;
default: WriteReg <= 0; //$0不能改值
endcase
//WriteData <= (WrRegData ? data_out : (pc_out + 4));
//assign WriteData = (WrRegData ? data_out : PC4);
ReadData1 <= register[rs];
ReadData2 <= register[rt];
if ((WriteReg != 0) && (RegWre == 1)) begin
register[WriteReg] <= WriteData;
end
end
always @ (negedge CLK) begin
reg_out1 <= ReadData1;
reg_out2 <= ReadData2;
end
endmodule
`timescale 1ns / 1ps
//包括邏輯左移模塊
module PC_0(
input [31:0] ins_out,
input [31:0] pc_out,
output reg [31:0] addr
);
wire [27:0] temp;
assign temp = ins_out[25:0] << 2 ;
always @ (ins_out) begin
addr <= {pc_out[31:28], temp[27:0]};
end
endmodule
`timescale 1ns / 1ps
//包括加4模塊,加立即數模塊,4選1模塊
module PC(
input CLK, RST,
input PCWre,
input [1:0] PCSrc,
input [31:0] Imm,
input [31:0] ReadData1,
input [31:0] addr,
output reg [31:0] pc_out
);
always @ (negedge CLK or negedge RST) begin
if (!RST) begin
pc_out <= 0;
end else if (PCWre) begin
case (PCSrc)
2'b00: pc_out <= pc_out + 4;
2'b01: pc_out <= Imm * 4 + pc_out + 4;
2'b10: pc_out <= ReadData1;
2'b11: pc_out <= addr; // addr是跳轉地址
default: pc_out <= 0;
endcase
end
end
endmodule
`timescale 1ns / 1ps
module MultiCycleCPU(
input clk, RST,
output [7:0] pin_out
);
wire CLK;
wire [31:0] WriteData, pc_out, addr;
wire [31:0] reg_out1, reg_out2, data_out;
wire [31:0] alu_out,sa;
wire [5:0] op;
wire [4:0] rs,rt, WriteReg;
wire [2:0] state,ALUOp;
wire [1:0] RegDst;
wire zero;
//WrRegData;
//wire CLK;
wire [31:0] result, ReadData1, ReadData2, ins_out, /*addr, */Imm;
wire [15:0] Imm_16;
wire [4:0] rd;
//wire [2:0] ALUOp;
wire [1:0] /*RegDst, */PCSrc;
wire PCWre, InsMemRW, IRWre, RegWre, WrRegData, ExtSel, ALUSrcA, ALUSrcB, RD, WR, ALUM2Reg;
assign op = ins_out[31:26];
assign rs = ins_out[25:21];
assign rt = ins_out[20:16];
assign rd = ins_out[15:11];
assign Imm_16 = ins_out[15:0];
assign sa = {{27{0}}, ins_out[10:6]};
fp50m fp50m(clk,RST,CLK);
PC PC(CLK, RST, PCWre, PCSrc, Imm, ReadData1, addr, pc_out);
PC_0 PC_0(ins_out, pc_out, addr);
InsMem InsMem(CLK, InsMemRW, IRWre, pc_out, ins_out);
RegFile RegFile(CLK, RegWre, WrRegData, RegDst, pc_out, rs, rt, rd, data_out, reg_out1, reg_out2, ReadData1, ReadData2, WriteData, WriteReg ,pin_out);
Extend Extend(ExtSel, Imm_16, Imm);
ALU ALU(CLK, ALUSrcA, ALUSrcB, ALUOp, reg_out1, reg_out2, ins_out, Imm, sa, result, alu_out, zero);
DataMem DataMem(RD, WR, CLK, ALUM2Reg, alu_out, result, reg_out2, data_out);
ControlUnit ControlUnit(CLK, RST, zero, op, WrRegData, RegWre, ALUSrcA, ALUSrcB, InsMemRW, IRWre, PCWre, RD, WR, ExtSel, ALUM2Reg, RegDst, PCSrc, ALUOp, state);
endmodule
`timescale 1ns / 1ps
//仿真激勵模塊
module MultiCycleCOU_tf;
// Inputs
reg CLK;
reg RST;
// Outputs
wire [31:0] Imm;
/*wire [31:0] ReadData1;
wire [31:0] ReadData2;*/
wire [31:0] WriteData;
wire [31:0] addr;
wire [31:0] pc_out;
wire [31:0] reg_out1;
wire [31:0] reg_out2;
//wire [31:0] ins_out;
wire [31:0] data_out;
//wire [31:0] result;
wire [31:0] alu_out;
wire [31:0] sa;
/*wire [31:0] A;
wire [31:0] B;*/
//wire [15:0] Imm_16;
wire [5:0] op;
wire [4:0] rs;
wire [4:0] rt;
wire [4:0] rd;
wire [4:0] WriteReg;
wire [2:0] ALUOp;
wire [2:0] state_out;
wire [2:0] state;
wire [1:0] RegDst;
wire [1:0] PCSrc;
wire zero;
wire PCWre;
wire InsMemRW;
wire IRWre;
wire RegWre;
wire WrRegData;
wire ExtSel;
wire ALUSrcA;
wire ALUSrcB;
//wire DataMemRW;
wire RD;
wire WR;
wire ALUM2Reg;
// Instantiate the Unit Under Test (UUT)
MultiCycleCPU uut (
.CLK(CLK),
.RST(RST),
.Imm(Imm),
/*.ReadData1(ReadData1),
.ReadData2(ReadData2),*/
.WriteData(WriteData),
.addr(addr),
.pc_out(pc_out),
.reg_out1(reg_out1),
.reg_out2(reg_out2),
//.ins_out(ins_out),
.data_out(data_out),
//.result(result),
.alu_out(alu_out),
.sa(sa),
/*.A(A),
.B(B),*/
//.Imm_16(Imm_16),
.op(op),
.rs(rs),
.rt(rt),
.rd(rd),
.WriteReg(WriteReg),
.ALUOp(ALUOp),
.state_out(state_out),
.state(state),
.RegDst(RegDst),
.PCSrc(PCSrc),
.zero(zero),
.PCWre(PCWre),
.InsMemRW(InsMemRW),
.IRWre(IRWre),
.RegWre(RegWre),
.WrRegData(WrRegData),
.ExtSel(ExtSel),
.ALUSrcA(ALUSrcA),
.ALUSrcB(ALUSrcB),
//.DataMemRW(DataMemRW),
.RD(RD),
.WR(WR),
.ALUM2Reg(ALUM2Reg)
);
always #30 CLK = !CLK;
initial begin
// Initialize Inputs
CLK = 1;
RST = 0;
// Wait 60ns for global reset to finish
#90;
RST = 1;
// Add stimulus here
end
endmodule
指令代碼設計文件(instruction.txt)
00001000
00000001
00000000
11111111
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00000011
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00000110
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00001001
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00001100
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00001111
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00010010
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00010101
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00011000
01100000
00100001
00001000
00000001
11000000
00000001
00000000
11111111
11100000
00000000
00000000
00000000