aboutsummaryrefslogtreecommitdiff
path: root/core/rtl/decode.sv
blob: 8642013e3155fff2282ecf1df12a4c4c1c0e8428 (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
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