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
|
module decode
import riscv_types::*;
#(
)
(
input logic clk,
input logic rst_l,
// I-MEM Interface
input logic [31:0] imem_id_instr_ID,
// Fetch Interface
input logic [31:0] imem_id_pc_ID
// Dispatch Interface
);
// OpCode
opcode_t instrOpCode_ID;
// Instruction Type
logic instrTypeR_ID;
logic instrTypeI_ID;
logic instrTypeS_ID;
logic instrTypeB_ID;
logic instrTypeU_ID;
logic instrTypeJ_ID;
// Immediate
logic [31:0] instrImm_ID;
logic instrImmSign_ID;
// Register Indices
logic [4:0] instrRs1Idx_ID;
logic instrRs1Vld_ID;
logic [4:0] instrRs2Idx_ID;
logic instrRs2Vld_ID;
logic [4:0] instrRdIdx_ID;
logic instrRdVld_ID;
// Funct3 and Funct7
logic [2:0] instrFunct3_ID;
logic instrFunct7_ID;
// Control Bits
// Memory Op
mem_op_t instrMemOp_ID;
// Branch OP
brjmp_op_t instrBrJmpOp_ID;
// ALU Operand Selection
aluSelOp1_t instrAluOp1_ID;
aluSelOp2_t instrAluOp2_ID;
// DEBUG: Display decode instr
always_ff @(clk) begin : f_print_decode
$display("OpCode: %s", instrOpCode_ID.name());
$display("Immediate: %0d", instrImm_ID);
$display("Memory: %s", instrMemOp_ID.name());
$display("Branch: %s", instrBrJmpOp_ID.name());
$display("ALU Sel 1: %s", instrAluOp1_ID.name());
$display("ALU Sel 2: %s", instrAluOp2_ID.name());
$display("Funct3: %0x", instrFunct3_ID);
$display("Funct7: %0x", instrFunct7_ID);
end
// Instruction Type Decode
// FIXME: Add support for FENCE + ECALL + EBREAK + CSRs
assign instrTypeI_ID = (instrOpCode_ID == INSTR_TYPE_IMM)
| (instrOpCode_ID == INSTR_TYPE_JALR)
| (instrOpCode_ID == INSTR_TYPE_LD);
assign instrTypeU_ID = (instrOpCode_ID == INSTR_TYPE_LUI)
| (instrOpCode_ID == INSTR_TYPE_AUIPC);
assign instrTypeR_ID = (instrOpCode_ID == INSTR_TYPE_REG);
assign instrTypeS_ID = (instrOpCode_ID == INSTR_TYPE_ST);
assign instrTypeB_ID = (instrOpCode_ID == INSTR_TYPE_BR);
assign instrTypeJ_ID = (instrOpCode_ID == INSTR_TYPE_JAL);
// Register Index Decode
assign instrRs1Idx_ID = imem_id_instr_ID[19:15];
assign instrRs1Vld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeS_ID | instrTypeB_ID;
assign instrRs2Idx_ID = imem_id_instr_ID[24:20];
assign instrRs2Vld_ID = instrTypeR_ID | instrTypeS_ID | instrTypeB_ID;
assign instrRdIdx_ID = imem_id_instr_ID[11:7];
assign instrRdVld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeU_ID | instrTypeJ_ID;
// Func Bit decode
assign instrFunct7_ID = imem_id_instr_ID[30];
assign instrFunct3_ID = imem_id_instr_ID[14:12];
// Instruction Type (OpCode) Decode
assign instrImmSign_ID = imem_id_instr_ID[31];
assign instrOpCode_ID = opcode_t'(imem_id_instr_ID[6:0]);
// Immediate Decode
assign instrImm_ID[0] = instrTypeJ_ID ? imem_id_instr_ID[25] : // Bit 25 for I-Type
instrTypeS_ID ? imem_id_instr_ID[7] : // Bit 7 for S-Type
'0; // All other instructions set to 0
assign instrImm_ID[4:1] = instrTypeI_ID ? imem_id_instr_ID[24:21] : // I-Type bits
(instrTypeS_ID | instrTypeB_ID) ? imem_id_instr_ID[11:8] : // S-Type + B-Type bits
'0; // All other instructions set to 0
assign instrImm_ID[10:5] = instrTypeU_ID ? '0 : imem_id_instr_ID[30:25]; // Only J type is an immediate instruction that doesn't have it in 30:25
assign instrImm_ID[11] = (instrTypeI_ID | instrTypeS_ID) ? imem_id_instr_ID[31] :
(instrTypeB_ID) ? imem_id_instr_ID[7] :
(instrTypeJ_ID) ? imem_id_instr_ID[20] :
'0;
assign instrImm_ID[19:12] = (instrTypeU_ID | instrTypeJ_ID) ? imem_id_instr_ID[19:12] : { 8{instrImmSign_ID}}; // Only J and U types use 19:12 as not sign bit
assign instrImm_ID[31:20] = (instrTypeU_ID) ? imem_id_instr_ID[31:20] : {12{instrImmSign_ID}}; // Only U type use 31:20 as not sign bit
// Control Bits
assign instrMemOp_ID = (instrOpCode_ID == INSTR_TYPE_ST) ? MEM_OP_STORE :
(instrOpCode_ID == INSTR_TYPE_LD) ? MEM_OP_LOAD :
MEM_OP_NONE;
assign instrBrJmpOp_ID = (instrOpCode_ID == INSTR_TYPE_JALR) ? REG_IMM_OFFSET :
(instrOpCode_ID == INSTR_TYPE_BR | instrOpCode_ID == INSTR_TYPE_JAL) ? PC_IMM_OFFSET :
OFFSET_NONE;
assign instrAluOp1_ID = (instrOpCode_ID == INSTR_TYPE_AUIPC) | (instrOpCode_ID == INSTR_TYPE_JAL) ? PC : // Loading PC for AUIPC, PC Offset for JAL
(instrOpCode_ID == INSTR_TYPE_LUI) ? OP_NONE : // Only loading immediate for LUI
RS1; // All else use RS1 value
assign instrAluOp2_ID = (instrOpCode_ID == INSTR_TYPE_REG) ? RS2 : IMM; // Only R2R needs non-immediate op in ALU
endmodule
|