blob: d763cfff673a7edd29040de6a38769c001d3aa9d [file] [log] [blame]
module flexbex_ibex_decoder (
deassert_we_i,
data_misaligned_i,
branch_mux_i,
jump_mux_i,
illegal_insn_o,
ebrk_insn_o,
mret_insn_o,
dret_insn_o,
ecall_insn_o,
pipe_flush_o,
instr_rdata_i,
illegal_c_insn_i,
alu_operator_o,
alu_op_a_mux_sel_o,
alu_op_b_mux_sel_o,
imm_a_mux_sel_o,
imm_b_mux_sel_o,
mult_int_en_o,
div_int_en_o,
multdiv_operator_o,
multdiv_signed_mode_o,
regfile_we_o,
csr_access_o,
csr_op_o,
csr_status_o,
data_req_o,
data_we_o,
data_type_o,
data_sign_extension_o,
data_reg_offset_o,
jump_in_id_o,
branch_in_id_o,
eFPGA_operator_o,
eFPGA_int_en_o,
eFPGA_delay_o
);
parameter [0:0] RV32M = 1;
input wire deassert_we_i;
input wire data_misaligned_i;
input wire branch_mux_i;
input wire jump_mux_i;
output reg illegal_insn_o;
output reg ebrk_insn_o;
output reg mret_insn_o;
output reg dret_insn_o;
output reg ecall_insn_o;
output reg pipe_flush_o;
input wire [31:0] instr_rdata_i;
input wire illegal_c_insn_i;
output reg [4:0] alu_operator_o;
output reg [1:0] alu_op_a_mux_sel_o;
output reg alu_op_b_mux_sel_o;
output reg imm_a_mux_sel_o;
output reg [2:0] imm_b_mux_sel_o;
output wire mult_int_en_o;
output wire div_int_en_o;
output reg [1:0] multdiv_operator_o;
output reg [1:0] multdiv_signed_mode_o;
output wire regfile_we_o;
output reg csr_access_o;
output wire [1:0] csr_op_o;
output reg csr_status_o;
output wire data_req_o;
output reg data_we_o;
output reg [1:0] data_type_o;
output reg data_sign_extension_o;
output reg [1:0] data_reg_offset_o;
output wire jump_in_id_o;
output wire branch_in_id_o;
output reg [1:0] eFPGA_operator_o;
output wire eFPGA_int_en_o;
output reg [3:0] eFPGA_delay_o;
reg regfile_we;
reg data_req;
reg mult_int_en;
reg div_int_en;
reg branch_in_id;
reg jump_in_id;
reg eFPGA_int_en;
reg [1:0] csr_op;
reg csr_illegal;
reg [6:0] opcode;
always @(*) begin
jump_in_id = 1'b0;
branch_in_id = 1'b0;
alu_operator_o = 5'd19;
alu_op_a_mux_sel_o = 2'd0;
alu_op_b_mux_sel_o = 1'd0;
imm_a_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd0;
mult_int_en = 1'b0;
div_int_en = 1'b0;
multdiv_operator_o = 2'd0;
multdiv_signed_mode_o = 2'b00;
eFPGA_int_en = 1'b0;
eFPGA_operator_o = 2'b00;
regfile_we = 1'b0;
csr_access_o = 1'b0;
csr_status_o = 1'b0;
csr_illegal = 1'b0;
csr_op = 2'd0;
data_we_o = 1'b0;
data_type_o = 2'b00;
data_sign_extension_o = 1'b0;
data_reg_offset_o = 2'b00;
data_req = 1'b0;
illegal_insn_o = 1'b0;
ebrk_insn_o = 1'b0;
mret_insn_o = 1'b0;
dret_insn_o = 1'b0;
ecall_insn_o = 1'b0;
pipe_flush_o = 1'b0;
opcode = instr_rdata_i[6:0];
case (opcode)
7'h6f: begin
jump_in_id = 1'b1;
if (jump_mux_i) begin
alu_op_a_mux_sel_o = 2'd1;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd4;
alu_operator_o = 5'd0;
regfile_we = 1'b0;
end
else begin
alu_op_a_mux_sel_o = 2'd1;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd5;
alu_operator_o = 5'd0;
regfile_we = 1'b1;
end
end
7'h67: begin
jump_in_id = 1'b1;
if (jump_mux_i) begin
alu_op_a_mux_sel_o = 2'd0;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd0;
alu_operator_o = 5'd0;
regfile_we = 1'b0;
end
else begin
alu_op_a_mux_sel_o = 2'd1;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd5;
alu_operator_o = 5'd0;
regfile_we = 1'b1;
end
if (instr_rdata_i[14:12] != 3'b000) begin
jump_in_id = 1'b0;
regfile_we = 1'b0;
illegal_insn_o = 1'b1;
end
end
7'h63: begin
branch_in_id = 1'b1;
if (branch_mux_i)
case (instr_rdata_i[14:12])
3'b000: alu_operator_o = 5'd16;
3'b001: alu_operator_o = 5'd17;
3'b100: alu_operator_o = 5'd8;
3'b101: alu_operator_o = 5'd14;
3'b110: alu_operator_o = 5'd9;
3'b111: alu_operator_o = 5'd15;
default: illegal_insn_o = 1'b1;
endcase
else begin
alu_op_a_mux_sel_o = 2'd1;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd2;
alu_operator_o = 5'd0;
regfile_we = 1'b0;
end
end
7'h23: begin
data_req = 1'b1;
data_we_o = 1'b1;
alu_operator_o = 5'd0;
if (!instr_rdata_i[14]) begin
imm_b_mux_sel_o = 3'd1;
alu_op_b_mux_sel_o = 1'd1;
end
else begin
data_req = 1'b0;
data_we_o = 1'b0;
illegal_insn_o = 1'b1;
end
case (instr_rdata_i[13:12])
2'b00: data_type_o = 2'b10;
2'b01: data_type_o = 2'b01;
2'b10: data_type_o = 2'b00;
default: begin
data_req = 1'b0;
data_we_o = 1'b0;
illegal_insn_o = 1'b1;
end
endcase
end
7'h03: begin
data_req = 1'b1;
regfile_we = 1'b1;
data_type_o = 2'b00;
alu_operator_o = 5'd0;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd0;
data_sign_extension_o = ~instr_rdata_i[14];
case (instr_rdata_i[13:12])
2'b00: data_type_o = 2'b10;
2'b01: data_type_o = 2'b01;
2'b10: data_type_o = 2'b00;
default: data_type_o = 2'b00;
endcase
if (instr_rdata_i[14:12] == 3'b111) begin
alu_op_b_mux_sel_o = 1'd0;
data_sign_extension_o = ~instr_rdata_i[30];
case (instr_rdata_i[31:25])
7'b0000000, 7'b0100000: data_type_o = 2'b10;
7'b0001000, 7'b0101000: data_type_o = 2'b01;
7'b0010000: data_type_o = 2'b00;
default: illegal_insn_o = 1'b1;
endcase
end
if (instr_rdata_i[14:12] == 3'b011)
illegal_insn_o = 1'b1;
end
7'h37: begin
alu_op_a_mux_sel_o = 2'd2;
alu_op_b_mux_sel_o = 1'd1;
imm_a_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd3;
alu_operator_o = 5'd0;
regfile_we = 1'b1;
end
7'h17: begin
alu_op_a_mux_sel_o = 2'd1;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd3;
alu_operator_o = 5'd0;
regfile_we = 1'b1;
end
7'h13: begin
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd0;
regfile_we = 1'b1;
case (instr_rdata_i[14:12])
3'b000: alu_operator_o = 5'd0;
3'b010: alu_operator_o = 5'd18;
3'b011: alu_operator_o = 5'd19;
3'b100: alu_operator_o = 5'd2;
3'b110: alu_operator_o = 5'd3;
3'b111: alu_operator_o = 5'd4;
3'b001: begin
alu_operator_o = 5'd7;
if (instr_rdata_i[31:25] != 7'b0000000)
illegal_insn_o = 1'b1;
end
3'b101:
if (instr_rdata_i[31:25] == 7'b0000000)
alu_operator_o = 5'd6;
else if (instr_rdata_i[31:25] == 7'b0100000)
alu_operator_o = 5'd5;
else
illegal_insn_o = 1'b1;
default:
;
endcase
end
7'h33: begin
regfile_we = 1'b1;
if (instr_rdata_i[31])
illegal_insn_o = 1'b1;
else if (!instr_rdata_i[28])
case ({instr_rdata_i[30:25], instr_rdata_i[14:12]})
9'b000000000: alu_operator_o = 5'd0;
9'b100000000: alu_operator_o = 5'd1;
9'b000000010: alu_operator_o = 5'd18;
9'b000000011: alu_operator_o = 5'd19;
9'b000000100: alu_operator_o = 5'd2;
9'b000000110: alu_operator_o = 5'd3;
9'b000000111: alu_operator_o = 5'd4;
9'b000000001: alu_operator_o = 5'd7;
9'b000000101: alu_operator_o = 5'd6;
9'b100000101: alu_operator_o = 5'd5;
9'b000001000: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd0;
mult_int_en = 1'b1;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001001: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd1;
mult_int_en = 1'b1;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001010: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd1;
mult_int_en = 1'b1;
multdiv_signed_mode_o = 2'b01;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001011: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd1;
mult_int_en = 1'b1;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001100: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd2;
div_int_en = 1'b1;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001101: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd2;
div_int_en = 1'b1;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001110: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd3;
div_int_en = 1'b1;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
9'b000001111: begin
alu_operator_o = 5'd0;
multdiv_operator_o = 2'd3;
div_int_en = 1'b1;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = (RV32M ? 1'b0 : 1'b1);
end
default: illegal_insn_o = 1'b1;
endcase
end
7'h0b: begin
regfile_we = 1'b1;
eFPGA_operator_o = instr_rdata_i[13:12];
eFPGA_delay_o = instr_rdata_i[28:25];
eFPGA_int_en = 1'b1;
end
7'h0f:
if (instr_rdata_i[14:12] == 3'b000) begin
alu_operator_o = 5'd0;
regfile_we = 1'b0;
end
else
illegal_insn_o = 1'b1;
7'h73:
if (instr_rdata_i[14:12] == 3'b000)
case (instr_rdata_i[31:20])
12'h000: ecall_insn_o = 1'b1;
12'h001: ebrk_insn_o = 1'b1;
12'h302: mret_insn_o = 1'b1;
12'h7b2: dret_insn_o = 1'b1;
12'h105: pipe_flush_o = 1'b1;
default: illegal_insn_o = 1'b1;
endcase
else begin
csr_access_o = 1'b1;
regfile_we = 1'b1;
alu_op_b_mux_sel_o = 1'd1;
imm_a_mux_sel_o = 1'd0;
imm_b_mux_sel_o = 3'd0;
if (instr_rdata_i[14])
alu_op_a_mux_sel_o = 2'd2;
else
alu_op_a_mux_sel_o = 2'd0;
case (instr_rdata_i[13:12])
2'b01: csr_op = 2'd1;
2'b10: csr_op = 2'd2;
2'b11: csr_op = 2'd3;
default: csr_illegal = 1'b1;
endcase
if (!csr_illegal)
if (((((instr_rdata_i[31:20] == 12'h300) || (instr_rdata_i[31:20] == 12'h7b0)) || (instr_rdata_i[31:20] == 12'h7b1)) || (instr_rdata_i[31:20] == 12'h7b2)) || (instr_rdata_i[31:20] == 12'h7b3))
csr_status_o = 1'b1;
illegal_insn_o = csr_illegal;
end
default: illegal_insn_o = 1'b1;
endcase
if (illegal_c_insn_i)
illegal_insn_o = 1'b1;
if (data_misaligned_i) begin
alu_op_a_mux_sel_o = 2'd0;
alu_op_b_mux_sel_o = 1'd1;
imm_b_mux_sel_o = 3'd5;
regfile_we = 1'b0;
end
end
assign regfile_we_o = (deassert_we_i ? 1'b0 : regfile_we);
assign mult_int_en_o = (RV32M ? (deassert_we_i ? 1'b0 : mult_int_en) : 1'b0);
assign div_int_en_o = (RV32M ? (deassert_we_i ? 1'b0 : div_int_en) : 1'b0);
assign data_req_o = (deassert_we_i ? 1'b0 : data_req);
assign csr_op_o = (deassert_we_i ? 2'd0 : csr_op);
assign jump_in_id_o = (deassert_we_i ? 1'b0 : jump_in_id);
assign branch_in_id_o = (deassert_we_i ? 1'b0 : branch_in_id);
assign eFPGA_int_en_o = (deassert_we_i ? 1'b0 : eFPGA_int_en);
endmodule