You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
11 KiB
252 lines
11 KiB
`include "../Defines.v"
|
|
|
|
module id(input wire rst,
|
|
input wire[`InstAddrBus] pc_i,
|
|
input wire[`InstBus] inst_i,
|
|
input wire[`RegBus] reg1_data_i,
|
|
input wire[`RegBus] reg2_data_i,
|
|
input wire ex_wreg_i, //EX
|
|
input wire[`RegBus] ex_wdata_i,
|
|
input wire[`RegAddrBus] ex_wd_i,
|
|
input wire mem_wreg_i, //MEM
|
|
input wire[`RegBus] mem_wdata_i,
|
|
input wire[`RegAddrBus] mem_wd_i,
|
|
output reg reg1_read_o,
|
|
output reg reg2_read_o,
|
|
output reg[`RegAddrBus] reg1_addr_o,
|
|
output reg[`RegAddrBus] reg2_addr_o,
|
|
output reg[`AluOpBus] aluop_o,
|
|
output reg[`AluSelBus] alusel_o,
|
|
output reg[`RegBus] reg1_o,
|
|
output reg[`RegBus] reg2_o,
|
|
output reg[`RegAddrBus] wd_o,
|
|
output reg wreg_o);
|
|
|
|
wire[5:0] op = inst_i[31:26];
|
|
wire[4:0] op2 = inst_i[10:6];
|
|
wire[5:0] op3 = inst_i[5:0];
|
|
wire[4:0] op4 = inst_i[20:16];
|
|
reg[`RegBus] imm;
|
|
reg instvalid;
|
|
|
|
|
|
always @ (*) begin
|
|
if (rst == `RstEnable) begin
|
|
aluop_o <= `EXE_NOP_OP;
|
|
alusel_o <= `EXE_RES_NOP;
|
|
wd_o <= `NOPRegAddr;
|
|
wreg_o <= `WriteDisable;
|
|
instvalid <= `InstValid;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b0;
|
|
reg1_addr_o <= `NOPRegAddr;
|
|
reg2_addr_o <= `NOPRegAddr;
|
|
imm <= 32'h0;
|
|
end else begin
|
|
aluop_o <= `EXE_NOP_OP;
|
|
alusel_o <= `EXE_RES_NOP;
|
|
wd_o <= inst_i[15:11];
|
|
wreg_o <= `WriteDisable;
|
|
instvalid <= `InstInvalid;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b0;
|
|
reg1_addr_o <= inst_i[25:21];
|
|
reg2_addr_o <= inst_i[20:16];
|
|
imm <= `ZeroWord;
|
|
case (op)
|
|
`EXE_SPECIAL_INST: begin
|
|
case (op2)
|
|
5'b00000: begin
|
|
case (op3)
|
|
`EXE_OR: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_OR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_AND: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_AND_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_XOR: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_XOR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_NOR: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_NOR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_SLLV: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SLL_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_SRLV: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SRL_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_SRAV: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SRA_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_SYNC: begin
|
|
wreg_o <= `WriteDisable;
|
|
aluop_o <= `EXE_NOP_OP;
|
|
alusel_o <= `EXE_RES_NOP;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b1;
|
|
instvalid <= `InstValid;
|
|
end
|
|
default: begin
|
|
end
|
|
endcase
|
|
end
|
|
default: begin
|
|
end
|
|
endcase
|
|
end
|
|
`EXE_ORI: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_OR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b0;
|
|
imm <= {16'h0, inst_i[15:0]};
|
|
wd_o <= inst_i[20:16];
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_ANDI: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_AND_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b0;
|
|
imm <= {16'h0, inst_i[15:0]};
|
|
wd_o <= inst_i[20:16];
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_XORI: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_XOR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b0;
|
|
imm <= {16'h0, inst_i[15:0]};
|
|
wd_o <= inst_i[20:16];
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_LUI: begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_OR_OP;
|
|
alusel_o <= `EXE_RES_LOGIC;
|
|
reg1_read_o <= 1'b1;
|
|
reg2_read_o <= 1'b0;
|
|
imm <= {inst_i[15:0], 16'h0};
|
|
wd_o <= inst_i[20:16];
|
|
instvalid <= `InstValid;
|
|
end
|
|
`EXE_PREF: begin
|
|
wreg_o <= `WriteDisable;
|
|
aluop_o <= `EXE_NOP_OP;
|
|
alusel_o <= `EXE_RES_NOP;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b0;
|
|
instvalid <= `InstValid;
|
|
end
|
|
default: begin
|
|
end
|
|
endcase
|
|
|
|
if (inst_i[31:21] == 11'b00000000000) begin
|
|
if (op3 == `EXE_SLL) begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SLL_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b1;
|
|
imm[4:0] <= inst_i[10:6];
|
|
wd_o <= inst_i[15:11];
|
|
instvalid <= `InstValid;
|
|
end else if (op3 == `EXE_SRL) begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SRL_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b1;
|
|
imm[4:0] <= inst_i[10:6];
|
|
wd_o <= inst_i[15:11];
|
|
instvalid <= `InstValid;
|
|
end else if (op3 == `EXE_SRA) begin
|
|
wreg_o <= `WriteEnable;
|
|
aluop_o <= `EXE_SRA_OP;
|
|
alusel_o <= `EXE_RES_SHIFT;
|
|
reg1_read_o <= 1'b0;
|
|
reg2_read_o <= 1'b1;
|
|
imm[4:0] <= inst_i[10:6];
|
|
wd_o <= inst_i[15:11];
|
|
instvalid <= `InstValid;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
always @ (*) begin
|
|
if (rst == `RstEnable) begin
|
|
reg1_o <= `ZeroWord;
|
|
end else if ((reg1_read_o == 1'b1)&&(ex_wreg_i == 1'b1)&&(ex_wd_i == reg1_addr_o)) begin
|
|
reg1_o <= ex_wdata_i;
|
|
end else if ((reg1_read_o == 1'b1)&&(mem_wreg_i == 1'b1)&&(mem_wd_i == reg1_addr_o)) begin
|
|
reg1_o <= mem_wdata_i;
|
|
end else if (reg1_read_o == 1'b1) begin
|
|
reg1_o <= reg1_data_i;
|
|
end else if (reg1_read_o == 1'b0) begin
|
|
reg1_o <= imm;
|
|
end else begin
|
|
reg1_o <= `ZeroWord;
|
|
end
|
|
end
|
|
|
|
always @ (*) begin
|
|
if (rst == `RstEnable) begin
|
|
reg2_o <= `ZeroWord;
|
|
end else if ((reg2_read_o == 1'b1)&&(ex_wreg_i == 1'b1)&&(ex_wd_i == reg2_addr_o)) begin
|
|
reg2_o <= ex_wdata_i;
|
|
end else if ((reg2_read_o == 1'b1)&&(mem_wreg_i == 1'b1)&&(mem_wd_i == reg2_addr_o)) begin
|
|
reg2_o <= mem_wdata_i;
|
|
end else if (reg2_read_o == 1'b1) begin
|
|
reg2_o <= reg2_data_i;
|
|
end else if (reg2_read_o == 1'b0) begin
|
|
reg2_o <= imm;
|
|
end else begin
|
|
reg2_o <= `ZeroWord;
|
|
end
|
|
end
|
|
|
|
endmodule
|