-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathVerdecode.sv
84 lines (78 loc) · 3.78 KB
/
Verdecode.sv
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
//
// SPDX-License-Identifier: CERN-OHL-W-2.0
// SPDX-FileCopyrightText: 2023 Guillaume Savaton <guillaume.savaton@tiliosys.fr>
//
`default_nettype none
// Vermicel instruction decoder.
//
// This module extracts the fields of an instruction word.
// It prepares the execution by determining which ALU operation to execute
// and how the instruction will use the data path.
module Verdecode
import Verdata_pkg::*,
Veropcodes_pkg::*;
(
input word_t data, // The instruction word to decode.
output instruction_t instr // The decoded instruction fields.
);
funct7_t funct7 = data[31:25]; // Funct7 field of the instruction word.
register_index_t rs2 = data[24:20]; // Source register index for operand 2.
register_index_t rs1 = data[19:15]; // Source register index for operand 1.
funct3_t funct3 = data[14:12]; // Funct3 field of the instruction word.
register_index_t rd = data[11: 7]; // Destination register index.
base_opcode_t opcode = data[ 6: 0]; // Base opcode of the instruction.
signed_word_t imm; // Decoded immediate value.
alu_fn_t alu_fn; // Decoded ALU operation.
// Decode the immediate value.
always_comb begin
case (opcode)
OPCODE_OP : imm = 0;
OPCODE_STORE : imm = signed_word_t'(signed'({funct7, rd}));
OPCODE_BRANCH : imm = signed_word_t'(signed'({data[31], data[7], data[30:25], data[11:8], 1'b0}));
OPCODE_LUI, OPCODE_AUIPC : imm = signed_word_t'(signed'({funct7, rs2, rs1, funct3, 12'b0}));
OPCODE_JAL : imm = signed_word_t'(signed'({data[31], rs1, funct3, data[20], data[30:21], 1'b0}));
default : imm = signed_word_t'(signed'({funct7, rs2}));
endcase
end
// Decode the ALU function.
always_comb begin
case (opcode)
OPCODE_LUI : alu_fn = ALU_NOP;
OPCODE_OP, OPCODE_OP_IMM : begin
case (funct3)
FUNCT3_SLT : alu_fn = ALU_SLT;
FUNCT3_SLTU : alu_fn = ALU_SLTU;
FUNCT3_AND : alu_fn = ALU_AND;
FUNCT3_OR : alu_fn = ALU_OR;
FUNCT3_XOR : alu_fn = ALU_XOR;
FUNCT3_SLL : alu_fn = ALU_SLL;
FUNCT3_SRL_SRA : alu_fn = (funct7 == FUNCT7_SUB_SRA)
? ALU_SRA
: ALU_SRL;
FUNCT3_ADD_SUB : alu_fn = (opcode == OPCODE_OP && funct7 == FUNCT7_SUB_SRA)
? ALU_SUB
: ALU_ADD;
default : alu_fn = ALU_ADD;
endcase
end
default : alu_fn = ALU_ADD;
endcase
end
assign instr = '{
rd : rd,
rs1 : rs1,
rs2 : rs2,
imm : imm,
funct3 : funct3,
alu_fn : alu_fn,
use_pc : opcode == OPCODE_AUIPC || opcode == OPCODE_JAL || opcode == OPCODE_BRANCH,
use_imm : opcode != OPCODE_OP,
has_rd : opcode != OPCODE_BRANCH && opcode != OPCODE_STORE && rd != 0,
is_load : opcode == OPCODE_LOAD,
is_store : opcode == OPCODE_STORE,
is_jump : opcode == OPCODE_JAL || opcode == OPCODE_JALR,
is_branch : opcode == OPCODE_BRANCH,
is_mret : opcode == OPCODE_SYSTEM && funct3 == FUNCT3_DEFAULT && imm == IMM_MRET,
is_trap : opcode == OPCODE_SYSTEM && funct3 == FUNCT3_DEFAULT && (imm == IMM_ECALL || imm == IMM_EBREAK)
};
endmodule