2021-12-14 07:23:24 +08:00
|
|
|
/*****************************************************************************\
|
2022-06-09 07:12:01 +08:00
|
|
|
| Copyright (C) 2021-2022 Luke Wren |
|
2021-12-14 07:23:24 +08:00
|
|
|
| SPDX-License-Identifier: Apache-2.0 |
|
|
|
|
\*****************************************************************************/
|
2021-11-24 06:10:39 +08:00
|
|
|
|
|
|
|
`default_nettype none
|
|
|
|
|
2021-05-21 10:46:29 +08:00
|
|
|
module hazard3_instr_decompress #(
|
2021-05-21 09:34:16 +08:00
|
|
|
parameter PASSTHROUGH = 0
|
|
|
|
) (
|
|
|
|
input wire [31:0] instr_in,
|
|
|
|
output reg instr_is_32bit,
|
|
|
|
output reg [31:0] instr_out,
|
|
|
|
output reg invalid
|
|
|
|
);
|
|
|
|
|
|
|
|
`include "rv_opcodes.vh"
|
|
|
|
|
|
|
|
localparam W_REGADDR = 5;
|
|
|
|
|
|
|
|
// Long-register formats: cr, ci, css
|
|
|
|
// Short-register formats: ciw, cl, cs, cb, cj
|
|
|
|
wire [W_REGADDR-1:0] rd_l = instr_in[11:7];
|
|
|
|
wire [W_REGADDR-1:0] rs1_l = instr_in[11:7];
|
|
|
|
wire [W_REGADDR-1:0] rs2_l = instr_in[6:2];
|
|
|
|
wire [W_REGADDR-1:0] rd_s = {2'b01, instr_in[4:2]};
|
|
|
|
wire [W_REGADDR-1:0] rs1_s = {2'b01, instr_in[9:7]};
|
|
|
|
wire [W_REGADDR-1:0] rs2_s = {2'b01, instr_in[4:2]};
|
|
|
|
|
2022-08-20 21:58:41 +08:00
|
|
|
// Mapping of cx -> x immediate formats (we are *expanding* instructions, not
|
|
|
|
// decoding them):
|
2021-05-21 09:34:16 +08:00
|
|
|
|
2022-08-20 21:58:41 +08:00
|
|
|
wire [31:0] imm_ci = {
|
|
|
|
{7{instr_in[12]}},
|
|
|
|
instr_in[6:2],
|
|
|
|
20'h00000
|
|
|
|
};
|
2021-05-21 09:34:16 +08:00
|
|
|
|
2022-08-20 21:58:41 +08:00
|
|
|
wire [31:0] imm_cj = {
|
|
|
|
instr_in[12],
|
|
|
|
instr_in[8],
|
|
|
|
instr_in[10:9],
|
|
|
|
instr_in[6],
|
|
|
|
instr_in[7],
|
|
|
|
instr_in[2],
|
|
|
|
instr_in[11],
|
|
|
|
instr_in[5:3],
|
|
|
|
{9{instr_in[12]}},
|
|
|
|
12'h000
|
|
|
|
};
|
2021-05-21 09:34:16 +08:00
|
|
|
|
2022-08-20 21:58:41 +08:00
|
|
|
wire [31:0] imm_cb ={
|
|
|
|
{4{instr_in[12]}},
|
|
|
|
instr_in[6:5],
|
|
|
|
instr_in[2],
|
|
|
|
13'h0000,
|
|
|
|
instr_in[11:10],
|
|
|
|
instr_in[4:3],
|
|
|
|
instr_in[12],
|
|
|
|
7'h00
|
|
|
|
};
|
2021-05-21 09:34:16 +08:00
|
|
|
|
2022-08-20 21:58:41 +08:00
|
|
|
function [31:0] rfmt_rd; input [4:0] rd; begin rfmt_rd = {20'h00000, rd, 7'h00}; end endfunction
|
|
|
|
function [31:0] rfmt_rs1; input [4:0] rs1; begin rfmt_rs1 = {12'h000, rs1, 15'h0000}; end endfunction
|
|
|
|
function [31:0] rfmt_rs2; input [4:0] rs2; begin rfmt_rs2 = {7'h00, rs2, 20'h00000}; end endfunction
|
2021-05-21 09:34:16 +08:00
|
|
|
|
|
|
|
generate
|
2021-06-04 03:03:43 +08:00
|
|
|
if (PASSTHROUGH) begin: instr_passthrough
|
2021-05-21 09:34:16 +08:00
|
|
|
always @ (*) begin
|
|
|
|
instr_is_32bit = 1'b1;
|
|
|
|
instr_out = instr_in;
|
|
|
|
invalid = 1'b0;
|
|
|
|
end
|
2021-06-04 03:03:43 +08:00
|
|
|
end else begin: instr_decompress
|
|
|
|
always @ (*) begin
|
2021-05-21 09:34:16 +08:00
|
|
|
if (instr_in[1:0] == 2'b11) begin
|
|
|
|
instr_is_32bit = 1'b1;
|
|
|
|
instr_out = instr_in;
|
|
|
|
invalid = 1'b0;
|
|
|
|
end else begin
|
|
|
|
instr_is_32bit = 1'b0;
|
|
|
|
instr_out = 32'h0;
|
|
|
|
invalid = 1'b0;
|
|
|
|
casez (instr_in[15:0])
|
|
|
|
16'h0: invalid = 1'b1;
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_ADDI4SPN: instr_out = `RVOPC_NOZ_ADDI | rfmt_rd(rd_s) | rfmt_rs1(5'h2)
|
2022-08-20 22:27:14 +08:00
|
|
|
| {2'h0, instr_in[10:7], instr_in[12:11], instr_in[5], instr_in[6], 2'b00, 20'h00000};
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_LW: instr_out = `RVOPC_NOZ_LW | rfmt_rd(rd_s) | rfmt_rs1(rs1_s)
|
2022-08-20 23:11:58 +08:00
|
|
|
| {5'h00, instr_in[5], instr_in[12:10], instr_in[6], 2'b00, 20'h00000};
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_SW: instr_out = `RVOPC_NOZ_SW | rfmt_rs2(rs2_s) | rfmt_rs1(rs1_s)
|
2022-08-20 22:27:14 +08:00
|
|
|
| {5'h00, instr_in[5], instr_in[12], 13'h000, instr_in[11:10], instr_in[6], 2'b00, 7'h00};
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_ADDI: instr_out = `RVOPC_NOZ_ADDI | rfmt_rd(rd_l) | rfmt_rs1(rs1_l) | imm_ci;
|
|
|
|
`RVOPC_C_JAL: instr_out = `RVOPC_NOZ_JAL | rfmt_rd(5'h1) | imm_cj;
|
|
|
|
`RVOPC_C_J: instr_out = `RVOPC_NOZ_JAL | rfmt_rd(5'h0) | imm_cj;
|
|
|
|
`RVOPC_C_LI: instr_out = `RVOPC_NOZ_ADDI | rfmt_rd(rd_l) | imm_ci;
|
|
|
|
`RVOPC_C_LUI: begin
|
2021-05-21 09:34:16 +08:00
|
|
|
if (rd_l == 5'h2) begin
|
2022-08-20 22:27:14 +08:00
|
|
|
// addi16sp
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_ADDI | rfmt_rd(5'h2) | rfmt_rs1(5'h2) |
|
2022-08-20 22:27:14 +08:00
|
|
|
{{3{instr_in[12]}}, instr_in[4:3], instr_in[5], instr_in[2], instr_in[6], 24'h000000};
|
2021-05-21 09:34:16 +08:00
|
|
|
end else begin
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_LUI | rfmt_rd(rd_l) | {{15{instr_in[12]}}, instr_in[6:2], 12'h000};
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
2021-06-04 03:03:43 +08:00
|
|
|
invalid = ~|{instr_in[12], instr_in[6:2]}; // RESERVED if imm == 0
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_SLLI: instr_out = `RVOPC_NOZ_SLLI | rfmt_rd(rs1_l) | rfmt_rs1(rs1_l) | imm_ci;
|
|
|
|
`RVOPC_C_SRAI: instr_out = `RVOPC_NOZ_SRAI | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | imm_ci;
|
|
|
|
`RVOPC_C_SRLI: instr_out = `RVOPC_NOZ_SRLI | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | imm_ci;
|
|
|
|
`RVOPC_C_ANDI: instr_out = `RVOPC_NOZ_ANDI | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | imm_ci;
|
|
|
|
`RVOPC_C_AND: instr_out = `RVOPC_NOZ_AND | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | rfmt_rs2(rs2_s);
|
|
|
|
`RVOPC_C_OR: instr_out = `RVOPC_NOZ_OR | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | rfmt_rs2(rs2_s);
|
|
|
|
`RVOPC_C_XOR: instr_out = `RVOPC_NOZ_XOR | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | rfmt_rs2(rs2_s);
|
|
|
|
`RVOPC_C_SUB: instr_out = `RVOPC_NOZ_SUB | rfmt_rd(rs1_s) | rfmt_rs1(rs1_s) | rfmt_rs2(rs2_s);
|
|
|
|
`RVOPC_C_ADD: begin
|
2021-06-04 03:03:43 +08:00
|
|
|
if (|rs2_l) begin
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_ADD | rfmt_rd(rd_l) | rfmt_rs1(rs1_l) | rfmt_rs2(rs2_l);
|
2021-06-04 03:03:43 +08:00
|
|
|
end else if (|rs1_l) begin // jalr
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_JALR | rfmt_rd(5'h1) | rfmt_rs1(rs1_l);
|
2021-06-04 03:03:43 +08:00
|
|
|
end else begin // ebreak
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_EBREAK;
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
|
|
|
end
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_MV: begin
|
2021-06-04 03:03:43 +08:00
|
|
|
if (|rs2_l) begin // mv
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_ADD | rfmt_rd(rd_l) | rfmt_rs2(rs2_l);
|
2021-05-21 09:34:16 +08:00
|
|
|
end else begin // jr
|
2022-08-20 23:22:04 +08:00
|
|
|
instr_out = `RVOPC_NOZ_JALR | rfmt_rs1(rs1_l);
|
2021-06-04 03:03:43 +08:00
|
|
|
invalid = ~|rs1_l; // RESERVED
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
|
|
|
end
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_LWSP: begin
|
|
|
|
instr_out = `RVOPC_NOZ_LW | rfmt_rd(rd_l) | rfmt_rs1(5'h2) |
|
2022-08-20 22:27:14 +08:00
|
|
|
{4'h0, instr_in[3:2], instr_in[12], instr_in[6:4], 2'b00, 20'h00000};
|
2021-06-04 03:03:43 +08:00
|
|
|
invalid = ~|rd_l; // RESERVED
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_SWSP: instr_out = `RVOPC_NOZ_SW | rfmt_rs2(rs2_l) | rfmt_rs1(5'h2)
|
2022-08-20 22:27:14 +08:00
|
|
|
| {4'h0, instr_in[8:7], instr_in[12], 13'h0000, instr_in[11:9], 2'b00, 7'h00};
|
2022-08-20 23:22:04 +08:00
|
|
|
`RVOPC_C_BEQZ: instr_out = `RVOPC_NOZ_BEQ | rfmt_rs1(rs1_s) | imm_cb;
|
|
|
|
`RVOPC_C_BNEZ: instr_out = `RVOPC_NOZ_BNE | rfmt_rs1(rs1_s) | imm_cb;
|
2021-05-21 09:34:16 +08:00
|
|
|
default: invalid = 1'b1;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
2021-05-21 10:46:29 +08:00
|
|
|
endmodule
|
2021-11-24 06:10:39 +08:00
|
|
|
|
|
|
|
`default_nettype wire
|