aboutsummaryrefslogtreecommitdiff
path: root/core/rtl/idu.sv
blob: 8736613caf105081d73c67580bb82476730232bc (plain) (blame)
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