📄 id.v
字号:
//******************************************************************************
//
// id.v
//
// the implementation for ID unit .
//
// verilog written by Pengcheng Li, HNU 2006/07/15
//
//******************************************************************************
module ID(//input
clk,rst,D_IR,D_NPC,
E_WriteReg,
E_RD,
E_Result,
M_WriteReg,
M_RD,
M_Result,
W_WriteReg,W_RegWriteAddr,W_RegWriteData,
//output
WritePC,Branch,WriteIR,ReadMem,WriteReg,MemToReg,WriteMem,
ALUcontrol,RegDes,ALUSrcB,FWDB,FWDA,
BranchAddr,
ea,eb,ei,ert,erd);
input clk,rst;
input [31:0] D_IR,D_NPC;
input E_WriteReg,M_WriteReg,W_WriteReg;
input [4:0] E_RD,M_RD,W_RegWriteAddr;
input [31:0] E_Result,M_Result,W_RegWriteData;
output WritePC,Branch,WriteIR,ReadMem,WriteReg,MemToReg,WriteMem,RegDes,ALUSrcB;
output [3:0] ALUcontrol;
output [1:0] FWDA,FWDB;
output [31:0] BranchAddr;
output [31:0] ea,eb,ei;
output [4:0] ert,erd;
wire [31:0] RegA,RegB;
//******************************************************************************
// instruction field
//******************************************************************************
`define opfield 31:26 // 6-bit operation code
`define rs 25:21 // 5-bit source register specifier
`define rt 20:16 // 5-bit source/dest register specifier
`define immediate 15:0 // 16-bit immediate, branch or address disp
`define rd 15:11 // 5-bit destination register specifier
`define funct 5:0 // 6-bit function field
wire [5:0] op;
wire [4:0] RtAddr, RdAddr, RsAddr;
wire [5:0] func;
wire [15:0] immediate;
assign op = D_IR[`opfield];
assign RtAddr = D_IR[`rt];
assign RdAddr = D_IR[`rd];
assign RsAddr = D_IR[`rs];
assign func = D_IR[`funct];
assign immediate = D_IR[`immediate];
assign ert = RtAddr;
assign erd = RdAddr;
assign ei = {{16{immediate[15]}},immediate[15:0]};// the sign extent of immidiate number
//******************************************************************************
// branch&jump instructions decode
//******************************************************************************
`define opcode_beq 6'b000100
`define opcode_bne 6'b000101
`define opcode_j 6'b000010
wire isBEQ, isBNE, isJ;
assign isBEQ = (op == `opcode_beq);
assign isBNE = (op == `opcode_bne);
assign isJ = (op == `opcode_j);
//******************************************************************************
// ALU instructions decode / control signal for ALU datapath
//******************************************************************************
//operation code and function code
//R-Type
`define opcode_rtype 6'b000000
`define funcode_add 6'b100000
`define funcode_sub 6'b100010
`define funcode_and 6'b100100
`define funcode_or 6'b100101
`define funcode_slt 6'b101010
//I-Type
`define opcode_lw 6'b100011
`define opcode_sw 6'b101011
`define opcode_addi 6'b001000
`define opcode_andi 6'b001100
`define opcode_ori 6'b001101
`define aluop_add 4'b0001
`define aluop_sub 4'b0010
`define aluop_and 4'b0011
`define aluop_or 4'b0100
`define aluop_slt 4'b0101
`define aluop_lw 4'b0110
`define aluop_sw 4'b0111
`define aluop_addi 4'b1000
`define aluop_andi 4'b1001
`define aluop_ori 4'b1010
wire isADD,isSUB,isAND,isOR,isSLT,isLW,isSW,isADDI,isANDI,isORI;
assign isADD = (op == `opcode_rtype) && (func == `funcode_add);
assign isSUB = (op == `opcode_rtype) && (func == `funcode_sub);
assign isAND = (op == `opcode_rtype) && (func == `funcode_and);
assign isOR = (op == `opcode_rtype) && (func == `funcode_or);
assign isSLT = (op == `opcode_rtype) && (func == `funcode_slt);
assign isLW = (op == `opcode_lw);
assign isSW = (op == `opcode_sw);
assign isADDI = (op == `opcode_addi);
assign isANDI = (op == `opcode_andi);
assign isORI = (op == `opcode_ori);
assign ALUcontrol[0] = isADD | isAND | isSLT | isSW | isANDI;
assign ALUcontrol[1] = isSUB | isAND | isLW | isSW | isORI;
assign ALUcontrol[2] = isOR | isSLT | isLW | isSW;
assign ALUcontrol[3] = isADDI | isANDI | isORI;
assign WritePC = 1;
assign WriteIR = 1;
assign ReadMem = 0;
assign WriteReg = isADD | isSUB | isAND | isOR | isSLT | isLW | isADDI | isANDI | isORI;
assign MemToReg = isLW; // use memory data for writing to register
assign WriteMem = isSW; // write to memory
assign RegDes = (op == `opcode_rtype);
assign ALUSrcB = ~(isADDI|isANDI|isORI|isLW|isSW);
//Register file
RegFile RegFile(.RsData(RegA), .RtData(RegB), .clk(clk), .RegWriteData(W_RegWriteData), .RegWriteAddr(W_RegWriteAddr), .RegWriteEn(W_WriteReg), .RsAddr(RsAddr), .RtAddr(RtAddr));
//Internal data forward
assign FWDA[0] = rst?0:((E_WriteReg && (E_RD != 0) && (E_RD ==RsAddr)) || (W_WriteReg && (W_RegWriteAddr != 0) && (E_RD !=RsAddr) && (M_RD !=RsAddr) && (W_RegWriteAddr == RsAddr)));
assign FWDA[1] = rst?0:((M_WriteReg && (M_RD!=0) && (E_RD !=RsAddr) && (M_RD==RsAddr)) || (W_WriteReg && (W_RegWriteAddr != 0) && (E_RD !=RsAddr) && (M_RD !=RsAddr) && (W_RegWriteAddr == RsAddr)));
assign ea = FWDA[0]?(FWDA[1]?W_RegWriteData:E_Result):(FWDA[1]?M_Result:RegA);
assign FWDB[0] = rst?0:(E_WriteReg && (E_RD != 0) && (E_RD ==RtAddr)) || (W_WriteReg && (W_RegWriteAddr != 0) && (E_RD !=RtAddr) && (M_RD !=RtAddr) && (W_RegWriteAddr == RtAddr));
assign FWDB[1] = rst?0:(M_WriteReg && (M_RD!=0) && (E_RD !=RtAddr) && (M_RD==RtAddr)) || (W_WriteReg && (W_RegWriteAddr != 0) && (E_RD !=RtAddr) && (M_RD !=RtAddr) && (W_RegWriteAddr == RtAddr));
assign eb = FWDB[0]?(FWDB[1]?W_RegWriteData:E_Result):(FWDB[1]?M_Result:RegB);
// get the Branch signal and Branch Address
assign ALUZero = (ea == eb);
assign Branch = rst?0:(isBEQ & ALUZero) |(isBNE & ~ALUZero)|isJ;
assign BranchAddr = Branch?(isJ?{D_NPC[31:28],D_IR[25:0],2'b00}:D_NPC + {{14{D_IR[15]}} , D_IR[15:0],2'b00}):32'b0;
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -