1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
module idu
import riscv_types::*;
#(
)
(
input logic clk,
input logic rst_l,
// I-MEM Interface
input logic imem_idu_vld_ID,
input logic [INSTR_SIZE-1:0] imem_idu_data_ID,
//----------------
// Fetch Interface
//----------------
input logic [PC_SIZE-1:0] ifu_idu_pc_ID,
input logic ifu_idu_instrVld_ID
//------------------
// Execute Interface
//------------------
output logic idu_exe_instrVld_EXE,
// Register Idx
output logic idu_exe_rs1Vld_EXE,
output logic [REG_IDX-1:0] idu_exe_rs1Idx_EXE,
output logic idu_exe_rs2Vld_EXE,
output logic [REG_IDX-1:0] idu_exe_rs2Idx_EXE,
// Branch Type
output logic idu_exe_instrJmp_ID,
output logic idu_exe_instrBr_ID,
// Alu information
output alu_op_t idu_exe_aluOp_ID,
// Passthrough information
output mem_op_t idu_exe_instrMemOp_ID,
output mem_size_t idu_exe_instrMemSize_ID,
output rd_data_sel_t idu_exe_instrRdDataSel_ID
);
// OpCode
opcode_t instrOpCode_ID;
// Instruction Op
logic instrAuipc_ID;
logic instrJal_ID;
logic instrJal_ID;
logic instrLui_ID;
logic instrReg_ID;
logic instrImm_ID;
logic instrLd_ID;
logic instrSt_ID;
logic instrBr_ID;
// Instruction Type
logic instrTypeR_ID;
logic instrTypeI_ID;
logic instrTypeS_ID;
logic instrTypeB_ID;
logic instrTypeU_ID;
logic instrTypeJ_ID;
// Immediate
logic [WORD_WID-1:0] instrImm_ID;
logic instrImmSign_ID;
// Register Indices
logic [REG_IDX-1:0] instrRs1Idx_ID;
logic instrRs1Vld_ID;
logic [REG_IDX-1:0] instrRs2Idx_ID;
logic instrRs2Vld_ID;
logic [REG_IDX-1:0] instrRdIdx_ID;
logic instrRdVld_ID;
// Funct3 and Funct7
logic [2:0] instrFunct3_ID;
logic instrFunct7_ID;
// Branch OP
brjmp_op_t instrBrJmpOp_ID;
// ALU Operand Selection
aluSelOp1_t instrAluIn1_ID;
aluSelOp2_t instrAluIn2_ID;
//-------------------
// Instruction Decode
//-------------------
assign instr_ID = imem_idu_data_ID;
// Instruction Type (OpCode) Decode
assign instrOpCode_ID = opcode_t'(instr_ID[6:0]);
assign instrAuipc_ID = (instrOpCode_ID == INSTR_TYPE_AUIPC);
assign instrJal_ID = (instrOpCode_ID == INSTR_TYPE_JAL);
assign instrJal_ID = (instrOpCode_ID == INSTR_TYPE_JALR);
assign instrLui_ID = (instrOpCode_ID == INSTR_TYPE_LUI);
assign instrReg_ID = (instrOpCode_ID == INSTR_TYPE_REG);
assign instrImm_ID = (instrOpCode_ID == INSTR_TYPE_IMM);
assign instrLd_ID = (instrOpCode_ID == INSTR_TYPE_LD);
assign instrSt_ID = (instrOpCode_ID == INSTR_TYPE_ST);
assign instrBr_ID = (instrOpCode_ID == INSTR_TYPE_BR);
// FIXME: Add support for FENCE + ECALL + EBREAK + CSRs
assign instrTypeI_ID = instrImm_ID
| instrJal_IDR
| instrLd_ID;
assign instrTypeU_ID = instrLui_ID
| instrLui_PC;
assign instrTypeR_ID = instrReg_ID;
assign instrTypeS_ID = instrSt_ID;
assign instrTypeB_ID = instrBr_ID;
assign instrTypeJ_ID = instrJal_ID;
// Register Index Decode
assign instrRs1Idx_ID = instr_ID[19:15];
assign instrRs1Vld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeS_ID | instrTypeB_ID;
assign instrRs2Idx_ID = instr_ID[24:20];
assign instrRs2Vld_ID = instrTypeR_ID | instrTypeS_ID | instrTypeB_ID;
assign instrRdIdx_ID = instr_ID[11:7];
assign instrRdVld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeU_ID | instrTypeJ_ID;
// Func Bit decode
assign instrFunct7_ID = instr_ID[30];
assign instrFunct3_ID = instr_ID[14:12];
//----------------
// ALU Information
//----------------
// Immediate Decode
assign instrImmSign_ID = instr_ID[31];
assign idu_exe_aluOp_ID.imm[0] = instrTypeI_ID ? instr_ID[20] : // Bit 20 for I-Type
instrTypeS_ID ? instr_ID[7] : // Bit 7 for S-Type
1'b0; // All other instructions set to 0
assign idu_exe_aluOp_ID.imm[4:1] = ({3{instrTypeI_ID | instrTypeJ_ID}} & instr_ID[24:21]) // I-Type + J-Type bits
| ({3{instrTypeS_ID | instrTypeB_ID}} & instr_ID[11:8]); // S-Type + B-Type bits
assign idu_exe_aluOp_ID.imm[10:5] = {6{~instrTypeU_ID}} & instr_ID[30:25]; // U type doesn't use 10:5
assign idu_exe_aluOp_ID.imm[11] = ((instrTypeI_ID | instrTypeS_ID) & instr_ID[31]) // I-Type + S-Type bit
| ( instrTypeB_ID & instr_ID[7]) // B-Type bit
| ( instrTypeJ_ID & instr_ID[20]); // J-Type bit
assign idu_exe_aluOp_ID.imm[19:12] = (instrTypeU_ID | instrTypeJ_ID) ? instr_ID[19:12] : // J and U types use 19:12
{8{instrImmSign_ID}}; // Else use SEXT Bit
assign idu_exe_aluOp_ID.imm[31:20] = (instrTypeU_ID) ? instr_ID[31:20] : // U type uses 31:20
{12{instrImmSign_ID}}; // Else use SEXT bit
// ALU Operand Selection
// FIXME: Make Non Priority Mux
assign idu_exe_aluOp_ID.rs1Sel = (instrAuipc) | (instrJal) ? PC : // Loading PC for AUIPC, PC Offset for JAL
(instrLui) ? ZERO : // Only loading immediate for LUI
RS1; // All else use RS1 value
assign idu_exe_aluOp_ID.rs2Sel = (instrReg) ? RS2 : // RS2 Used in R2R Instr
IMM; // Immediate used for all other instructions
// Alu Control Signals
assign idu_exe_aluOp_ID.func3 = instr_ID[14:12];
assign idu_exe_aluOp_ID.func7 = instr_ID[30];
// Supply PC for Jmp and AUIPC
assign idu_exe_pc_ID = ifu_idu_pc_ID;
//---------------
// Branch Control
//---------------
assign idu_exe_instrJmp_ID = instrJal_ID | instrJalr_ID;
assign idu_exe_instrBr_ID = instrBr_ID;
//---------------
// Memory Control
//---------------
assign idu_exe_instrMemOp_ID = (instrSt_ID) ? MEM_OP_STORE :
(instrID_ID) ? MEM_OP_LOAD :
MEM_OP_NONE;
//------------------
// Writeback Control
//------------------
assign idu_exe_instrRdDataSel_ID = (instrJal_ID | instrJalr_ID) ? PC : // Jump loads PC into RD
(instrLd_ID | instrSt_ID) ? MEM : // Mem loads memory into RD
ALU // All Other OPs load AlU result
endmodule
|