mirror of
https://github.com/olofk/serv.git
synced 2026-01-11 23:42:50 +00:00
235 lines
5.8 KiB
Verilog
235 lines
5.8 KiB
Verilog
/*
|
|
* serv_immdec.v : SERV module for decoding immediates from instruction words
|
|
*
|
|
* SPDX-FileCopyrightText: 2020 Olof Kindgren <olof@award-winning.me>
|
|
* SPDX-License-Identifier: ISC
|
|
*/
|
|
`default_nettype none
|
|
module serv_immdec
|
|
#(parameter SHARED_RFADDR_IMM_REGS = 1,
|
|
parameter W = 1)
|
|
(
|
|
input wire i_clk,
|
|
//State
|
|
input wire i_cnt_en,
|
|
input wire i_cnt_done,
|
|
//Control
|
|
input wire [3:0] i_immdec_en,
|
|
input wire i_csr_imm_en,
|
|
input wire [3:0] i_ctrl,
|
|
output wire [4:0] o_rd_addr,
|
|
output wire [4:0] o_rs1_addr,
|
|
output wire [4:0] o_rs2_addr,
|
|
//Data
|
|
output wire [W-1:0] o_csr_imm,
|
|
output wire [W-1:0] o_imm,
|
|
//External
|
|
input wire i_wb_en,
|
|
input wire [31:7] i_wb_rdt);
|
|
|
|
generate
|
|
if (W == 1) begin : gen_immdec_w_eq_1
|
|
reg imm31;
|
|
|
|
reg [8:0] imm19_12_20;
|
|
reg imm7;
|
|
reg [5:0] imm30_25;
|
|
reg [4:0] imm24_20;
|
|
reg [4:0] imm11_7;
|
|
|
|
assign o_csr_imm = imm19_12_20[4];
|
|
|
|
wire signbit = imm31 & !i_csr_imm_en;
|
|
|
|
if (SHARED_RFADDR_IMM_REGS) begin : gen_shared_imm_regs
|
|
assign o_rs1_addr = imm19_12_20[8:4];
|
|
assign o_rs2_addr = imm24_20;
|
|
assign o_rd_addr = imm11_7;
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_wb_en) begin
|
|
/* CSR immediates are always zero-extended, hence clear the signbit */
|
|
imm31 <= i_wb_rdt[31];
|
|
end
|
|
if (i_wb_en | (i_cnt_en & i_immdec_en[1]))
|
|
imm19_12_20 <= i_wb_en ? {i_wb_rdt[19:12],i_wb_rdt[20]} : {i_ctrl[3] ? signbit : imm24_20[0], imm19_12_20[8:1]};
|
|
if (i_wb_en | (i_cnt_en))
|
|
imm7 <= i_wb_en ? i_wb_rdt[7] : signbit;
|
|
|
|
if (i_wb_en | (i_cnt_en & i_immdec_en[3]))
|
|
imm30_25 <= i_wb_en ? i_wb_rdt[30:25] : {i_ctrl[2] ? imm7 : i_ctrl[1] ? signbit : imm19_12_20[0], imm30_25[5:1]};
|
|
|
|
if (i_wb_en | (i_cnt_en & i_immdec_en[2]))
|
|
imm24_20 <= i_wb_en ? i_wb_rdt[24:20] : {imm30_25[0], imm24_20[4:1]};
|
|
|
|
if (i_wb_en | (i_cnt_en & i_immdec_en[0]))
|
|
imm11_7 <= i_wb_en ? i_wb_rdt[11:7] : {imm30_25[0], imm11_7[4:1]};
|
|
end
|
|
end else begin : gen_separate_imm_regs
|
|
reg [4:0] rd_addr;
|
|
reg [4:0] rs1_addr;
|
|
reg [4:0] rs2_addr;
|
|
|
|
assign o_rd_addr = rd_addr;
|
|
assign o_rs1_addr = rs1_addr;
|
|
assign o_rs2_addr = rs2_addr;
|
|
always @(posedge i_clk) begin
|
|
if (i_wb_en) begin
|
|
/* CSR immediates are always zero-extended, hence clear the signbit */
|
|
imm31 <= i_wb_rdt[31];
|
|
imm19_12_20 <= {i_wb_rdt[19:12],i_wb_rdt[20]};
|
|
imm7 <= i_wb_rdt[7];
|
|
imm30_25 <= i_wb_rdt[30:25];
|
|
imm24_20 <= i_wb_rdt[24:20];
|
|
imm11_7 <= i_wb_rdt[11:7];
|
|
|
|
rd_addr <= i_wb_rdt[11:7];
|
|
rs1_addr <= i_wb_rdt[19:15];
|
|
rs2_addr <= i_wb_rdt[24:20];
|
|
end
|
|
if (i_cnt_en) begin
|
|
imm19_12_20 <= {i_ctrl[3] ? signbit : imm24_20[0], imm19_12_20[8:1]};
|
|
imm7 <= signbit;
|
|
imm30_25 <= {i_ctrl[2] ? imm7 : i_ctrl[1] ? signbit : imm19_12_20[0], imm30_25[5:1]};
|
|
imm24_20 <= {imm30_25[0], imm24_20[4:1]};
|
|
imm11_7 <= {imm30_25[0], imm11_7[4:1]};
|
|
end
|
|
end
|
|
end
|
|
|
|
assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];
|
|
end else begin : gen_immdec_w_eq_4
|
|
reg [4:0] rd_addr;
|
|
reg [4:0] rs1_addr;
|
|
reg [4:0] rs2_addr;
|
|
|
|
reg i31;
|
|
reg i30;
|
|
reg i29;
|
|
reg i28;
|
|
reg i27;
|
|
reg i26;
|
|
reg i25;
|
|
reg i24;
|
|
reg i23;
|
|
reg i22;
|
|
reg i21;
|
|
reg i20;
|
|
reg i19;
|
|
reg i18;
|
|
reg i17;
|
|
reg i16;
|
|
reg i15;
|
|
reg i14;
|
|
reg i13;
|
|
reg i12;
|
|
reg i11;
|
|
reg i10;
|
|
reg i9;
|
|
reg i8;
|
|
reg i7;
|
|
|
|
reg i7_2;
|
|
reg i20_2;
|
|
|
|
wire signbit = i31 & !i_csr_imm_en;
|
|
|
|
assign o_csr_imm[3] = i18;
|
|
assign o_csr_imm[2] = i17;
|
|
assign o_csr_imm[1] = i16;
|
|
assign o_csr_imm[0] = i15;
|
|
|
|
assign o_rd_addr = rd_addr;
|
|
assign o_rs1_addr = rs1_addr;
|
|
assign o_rs2_addr = rs2_addr;
|
|
always @(posedge i_clk) begin
|
|
if (i_wb_en) begin
|
|
//Common
|
|
i31 <= i_wb_rdt[31];
|
|
|
|
//Bit lane 3
|
|
i19 <= i_wb_rdt[19];
|
|
i15 <= i_wb_rdt[15];
|
|
i20 <= i_wb_rdt[20];
|
|
i7 <= i_wb_rdt[7];
|
|
i27 <= i_wb_rdt[27];
|
|
i23 <= i_wb_rdt[23];
|
|
i10 <= i_wb_rdt[10];
|
|
|
|
//Bit lane 2
|
|
i22 <= i_wb_rdt[22];
|
|
i9 <= i_wb_rdt[ 9];
|
|
i26 <= i_wb_rdt[26];
|
|
i30 <= i_wb_rdt[30];
|
|
i14 <= i_wb_rdt[14];
|
|
i18 <= i_wb_rdt[18];
|
|
|
|
//Bit lane 1
|
|
i21 <= i_wb_rdt[21];
|
|
i8 <= i_wb_rdt[ 8];
|
|
i25 <= i_wb_rdt[25];
|
|
i29 <= i_wb_rdt[29];
|
|
i13 <= i_wb_rdt[13];
|
|
i17 <= i_wb_rdt[17];
|
|
|
|
//Bit lane 0
|
|
i11 <= i_wb_rdt[11];
|
|
i7_2 <= i_wb_rdt[7 ];
|
|
i20_2 <= i_wb_rdt[20];
|
|
i24 <= i_wb_rdt[24];
|
|
i28 <= i_wb_rdt[28];
|
|
i12 <= i_wb_rdt[12];
|
|
i16 <= i_wb_rdt[16];
|
|
|
|
rd_addr <= i_wb_rdt[11:7];
|
|
rs1_addr <= i_wb_rdt[19:15];
|
|
rs2_addr <= i_wb_rdt[24:20];
|
|
end
|
|
if (i_cnt_en) begin
|
|
//Bit lane 3
|
|
i10 <= i27;
|
|
i23 <= i27;
|
|
i27 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
|
|
i7 <= signbit;
|
|
i20 <= i15;
|
|
i15 <= i19;
|
|
i19 <= i_ctrl[3] ? signbit : i23;
|
|
|
|
//Bit lane 2
|
|
i22 <= i26;
|
|
i9 <= i26;
|
|
i26 <= i30;
|
|
i30 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i14;
|
|
i14 <= i18;
|
|
i18 <= i_ctrl[3] ? signbit : i22;
|
|
|
|
//Bit lane 1
|
|
i21 <= i25;
|
|
i8 <= i25;
|
|
i25 <= i29;
|
|
i29 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i13;
|
|
i13 <= i17;
|
|
i17 <= i_ctrl[3] ? signbit : i21;
|
|
|
|
//Bit lane 0
|
|
i7_2 <= i11;
|
|
i11 <= i28;
|
|
i20_2 <= i24;
|
|
i24 <= i28;
|
|
i28 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
|
|
i12 <= i16;
|
|
i16 <= i_ctrl[3] ? signbit : i20_2;
|
|
|
|
end
|
|
end
|
|
|
|
assign o_imm[3] = (i_cnt_done ? signbit : (i_ctrl[0] ? i10 : i23));
|
|
assign o_imm[2] = i_ctrl[0] ? i9 : i22;
|
|
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
|
|
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
|
|
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|