tinyriscv/rtl/ex.v

479 lines
26 KiB
Coq
Raw Normal View History

/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
// excute and writeback module
module ex (
input wire clk,
input wire rst,
// from id
input wire[`SramBus] inst_i, // inst content
input wire inst_valid_i,
input wire[`SramAddrBus] inst_addr_i, // inst addr
// from regs
input wire[`RegBus] reg1_rdata_i, // reg1 read data
input wire[`RegBus] reg2_rdata_i, // reg2 read data
// from sram
input wire[`SramBus] sram_rdata_i, // ram read data
// to sram
output reg[`SramBus] sram_wdata_o, // ram write data
output reg[`SramAddrBus] sram_raddr_o, // ram read addr
output reg[`SramAddrBus] sram_waddr_o, // ram write addr
// to regs
output reg[`RegBus] reg_wdata_o, // reg write data
// to pc_reg
output reg jump_flag_o, // if jump or not flag
output reg[`RegBus] jump_addr_o // jump dest addr
);
wire[31:0] sign_extend_tmp;
wire[4:0] shift_bits;
reg[1:0] sram_raddr_index;
reg[1:0] sram_waddr_index;
wire[6:0] opcode = inst_i[6:0];
wire[2:0] funct3 = inst_i[14:12];
assign sign_extend_tmp = {{20{inst_i[31]}}, inst_i[31:20]};
assign shift_bits = inst_i[24:20];
always @ (posedge clk) begin
if (rst == `RstEnable) begin
sram_raddr_o <= `ZeroWord;
jump_flag_o <= `JumpDisable;
sram_raddr_index <= 2'b0;
sram_waddr_index <= 2'b0;
end
end
always @ (*) begin
if (inst_valid_i == `InstValid) begin
case (opcode)
`INST_TYPE_I: begin
case (funct3)
`INST_ADDI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
end
`INST_SLTI: begin
jump_flag_o <= `JumpDisable;
if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b1) begin
if (reg1_rdata_i < sign_extend_tmp) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end else if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b0) begin
reg_wdata_o <= 32'h00000001;
end else if (reg1_rdata_i[31] == 1'b0 && sign_extend_tmp[31] == 1'b1) begin
reg_wdata_o <= 32'h00000000;
end else begin
if (reg1_rdata_i < sign_extend_tmp) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end
end
`INST_SLTIU: begin
jump_flag_o <= `JumpDisable;
if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b1) begin
if (reg1_rdata_i < sign_extend_tmp) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end else if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b0) begin
reg_wdata_o <= 32'h00000000;
end else if (reg1_rdata_i[31] == 1'b0 && sign_extend_tmp[31] == 1'b1) begin
reg_wdata_o <= 32'h00000001;
end else begin
if (reg1_rdata_i < sign_extend_tmp) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end
end
`INST_XORI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i ^ {{20{inst_i[31]}}, inst_i[31:20]};
end
`INST_ORI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i | {{20{inst_i[31]}}, inst_i[31:20]};
end
`INST_ANDI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i & {{20{inst_i[31]}}, inst_i[31:20]};
end
`INST_SLLI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i << shift_bits;
end
`INST_SRI: begin
jump_flag_o <= `JumpDisable;
if (inst_i[30] == 1'b1) begin
reg_wdata_o <= ({32{reg1_rdata_i[31]}} << (6'd32 - {1'b0, shift_bits})) | (reg1_rdata_i >> shift_bits);
end else begin
reg_wdata_o <= reg1_rdata_i >> shift_bits;
end
end
endcase
end
`INST_TYPE_R: begin
case (funct3)
`INST_ADD_SUB: begin
jump_flag_o <= `JumpDisable;
if (inst_i[30] == 1'b0) begin
reg_wdata_o <= reg1_rdata_i + reg2_rdata_i;
end else begin
reg_wdata_o <= reg1_rdata_i - reg2_rdata_i;
end
end
`INST_SLL: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i << reg2_rdata_i[4:0];
end
`INST_SLT: begin
jump_flag_o <= `JumpDisable;
if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i < reg2_rdata_i) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin
reg_wdata_o <= 32'h00000001;
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin
reg_wdata_o <= 32'h00000000;
end else begin
if (reg1_rdata_i < reg2_rdata_i) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end
end
`INST_SLTU: begin
jump_flag_o <= `JumpDisable;
if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i < reg2_rdata_i) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin
reg_wdata_o <= 32'h00000000;
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin
reg_wdata_o <= 32'h00000001;
end else begin
if (reg1_rdata_i < reg2_rdata_i) begin
reg_wdata_o <= 32'h00000001;
end else begin
reg_wdata_o <= 32'h00000000;
end
end
end
`INST_XOR: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i ^ reg2_rdata_i;
end
`INST_SR: begin
jump_flag_o <= `JumpDisable;
if (inst_i[30] == 1'b1) begin
reg_wdata_o <= ({32{reg1_rdata_i[31]}} << (6'd32 - {1'b0, reg2_rdata_i[4:0]})) | (reg1_rdata_i >> reg2_rdata_i[4:0]);
end else begin
reg_wdata_o <= reg1_rdata_i >> reg2_rdata_i[4:0];
end
end
`INST_OR: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i | reg2_rdata_i;
end
`INST_AND: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= reg1_rdata_i & reg2_rdata_i;
end
endcase
end
`INST_TYPE_L: begin
case (funct3)
`INST_LB: begin
jump_flag_o <= `JumpDisable;
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
sram_raddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11;
end
`INST_LH: begin
jump_flag_o <= `JumpDisable;
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
sram_raddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11;
end
`INST_LW: begin
jump_flag_o <= `JumpDisable;
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
sram_raddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11;
end
`INST_LBU: begin
jump_flag_o <= `JumpDisable;
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
sram_raddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11;
end
`INST_LHU: begin
jump_flag_o <= `JumpDisable;
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]};
sram_raddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11;
end
endcase
end
`INST_TYPE_S: begin
case (funct3)
`INST_SB: begin
jump_flag_o <= `JumpDisable;
sram_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
sram_waddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) - (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]} & 32'hfffffffc)) & 2'b11;
end
`INST_SH: begin
jump_flag_o <= `JumpDisable;
sram_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
sram_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
sram_waddr_index <= ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) - (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]} & 32'hfffffffc)) & 2'b11;
end
`INST_SW: begin
jump_flag_o <= `JumpDisable;
sram_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
sram_wdata_o <= reg2_rdata_i;
end
endcase
end
`INST_TYPE_B: begin
case (funct3)
`INST_BEQ: begin
if (reg1_rdata_i == reg2_rdata_i) begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end else begin
jump_flag_o <= `JumpDisable;
end
end
`INST_BNE: begin
if (reg1_rdata_i != reg2_rdata_i) begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end else begin
jump_flag_o <= `JumpDisable;
end
end
`INST_BLT: begin
if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i >= reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin
if (reg1_rdata_i >= reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else begin
jump_flag_o <= `JumpDisable;
end
end
`INST_BGE: begin
if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i < reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin
if (reg1_rdata_i < reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else begin
jump_flag_o <= `JumpDisable;
end
end
`INST_BLTU: begin
if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin
jump_flag_o <= `JumpDisable;
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i >= reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin
if (reg1_rdata_i >= reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end
`INST_BGEU: begin
if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin
jump_flag_o <= `JumpDisable;
end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin
if (reg1_rdata_i < reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin
if (reg1_rdata_i < reg2_rdata_i) begin
jump_flag_o <= `JumpDisable;
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end else begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
end
endcase
end
`INST_JAL: begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
reg_wdata_o <= inst_addr_i + 4'h4;
end
`INST_JALR: begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & (32'hfffffffe);
reg_wdata_o <= inst_addr_i + 4'h4;
end
`INST_LUI: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= {inst_i[31:12], 12'b0};
end
`INST_AUIPC: begin
jump_flag_o <= `JumpDisable;
reg_wdata_o <= {inst_i[31:12], 12'b0} + inst_addr_i;
end
`INST_NOP: begin
jump_flag_o <= `JumpDisable;
end
`INST_FENCE: begin
jump_flag_o <= `JumpEnable;
jump_addr_o <= inst_addr_i + 4'h4;
end
default: begin
end
endcase
end
end
always @ (*) begin
if (inst_valid_i == `InstValid) begin
case (opcode)
`INST_TYPE_L: begin
case (funct3)
`INST_LB: begin
if (sram_raddr_index == 2'b0)
reg_wdata_o <= {{24{sram_rdata_i[7]}}, sram_rdata_i[7:0]};
else if (sram_raddr_index == 2'b01)
reg_wdata_o <= {{24{sram_rdata_i[15]}}, sram_rdata_i[15:8]};
else if (sram_raddr_index == 2'b10)
reg_wdata_o <= {{24{sram_rdata_i[23]}}, sram_rdata_i[23:16]};
else
reg_wdata_o <= {{24{sram_rdata_i[31]}}, sram_rdata_i[31:24]};
end
`INST_LH: begin
if (sram_raddr_index == 2'b0)
reg_wdata_o <= {{16{sram_rdata_i[15]}}, sram_rdata_i[15:0]};
else
reg_wdata_o <= {{16{sram_rdata_i[31]}}, sram_rdata_i[31:16]};
end
`INST_LW: begin
reg_wdata_o <= sram_rdata_i;
end
`INST_LBU: begin
if (sram_raddr_index == 2'b0)
reg_wdata_o <= {24'h0, sram_rdata_i[7:0]};
else if (sram_raddr_index == 2'b01)
reg_wdata_o <= {24'h0, sram_rdata_i[15:8]};
else if (sram_raddr_index == 2'b10)
reg_wdata_o <= {24'h0, sram_rdata_i[23:16]};
else
reg_wdata_o <= {24'h0, sram_rdata_i[31:24]};
end
`INST_LHU: begin
if (sram_raddr_index == 2'b0)
reg_wdata_o <= {16'h0, sram_rdata_i[15:0]};
else
reg_wdata_o <= {16'h0, sram_rdata_i[31:16]};
end
endcase
end
`INST_TYPE_S: begin
case (funct3)
`INST_SB: begin
if (sram_waddr_index == 2'b00)
sram_wdata_o <= {sram_rdata_i[31:8], reg2_rdata_i[7:0]};
else if (sram_waddr_index == 2'b01)
sram_wdata_o <= {sram_rdata_i[31:16], reg2_rdata_i[7:0], sram_rdata_i[7:0]};
else if (sram_waddr_index == 2'b10)
sram_wdata_o <= {sram_rdata_i[31:24], reg2_rdata_i[7:0], sram_rdata_i[15:0]};
else
sram_wdata_o <= {reg2_rdata_i[7:0], sram_rdata_i[23:0]};
end
`INST_SH: begin
if (sram_waddr_index == 2'b00)
sram_wdata_o <= {sram_rdata_i[31:16], reg2_rdata_i[15:0]};
else
sram_wdata_o <= {reg2_rdata_i[15:0], sram_rdata_i[15:0]};
end
endcase
end
endcase
end
end
endmodule