icicle/rv32_fetch.sv

86 lines
2.2 KiB
Systemverilog
Raw Normal View History

2017-12-01 23:30:33 +00:00
`ifndef RV32_FETCH
`define RV32_FETCH
`include "rv32_opcodes.sv"
2017-11-30 22:30:49 +00:00
module rv32_fetch (
input clk,
/* control in (from hazard) */
input stall_in,
input flush_in,
2017-11-30 22:30:49 +00:00
/* control in (from mem) */
2017-12-30 13:48:14 +00:00
input branch_mispredicted_in,
2017-12-02 15:23:12 +00:00
/* data in (from mem) */
2017-12-02 15:23:12 +00:00
input [31:0] branch_pc_in,
2017-12-25 23:12:55 +00:00
/* data in (from memory bus) */
input [31:0] instr_read_value_in,
2017-12-30 13:48:14 +00:00
/* control out (to memory bus) */
2017-12-25 23:12:55 +00:00
output logic instr_read_out,
2017-12-30 13:48:14 +00:00
/* control out */
output logic branch_predicted_taken_out,
2017-11-30 22:30:49 +00:00
/* data out */
output logic [31:0] pc_out,
2017-12-25 23:12:55 +00:00
output logic [31:0] instr_out,
/* data out (to memory bus) */
output logic [31:0] instr_address_out
2017-11-30 22:30:49 +00:00
);
2017-12-02 15:23:12 +00:00
logic [31:0] next_pc;
logic [31:0] pc;
2017-11-30 22:30:49 +00:00
2017-12-30 13:48:14 +00:00
logic sign;
logic [31:0] imm_j;
logic [31:0] imm_b;
logic [7:0] opcode;
logic branch_predicted_taken;
logic [31:0] branch_offset;
assign pc = branch_mispredicted_in ? branch_pc_in : next_pc;
2017-12-25 23:12:55 +00:00
assign instr_read_out = 1;
assign instr_address_out = pc;
2017-12-30 13:48:14 +00:00
assign sign = instr_read_value_in[31];
assign imm_j = {{12{sign}}, instr_read_value_in[19:12], instr_read_value_in[20], instr_read_value_in[30:25], instr_read_value_in[24:21], 1'b0};
assign imm_b = {{20{sign}}, instr_read_value_in[7], instr_read_value_in[30:25], instr_read_value_in[11:8], 1'b0};
assign opcode = instr_read_value_in[7:0];
always_comb begin
case ({opcode, sign})
{`RV32_OPCODE_JAL, 1'bx}: begin
branch_predicted_taken = 1;
branch_offset = imm_j;
end
{`RV32_OPCODE_BRANCH, 1'b1}: begin
branch_predicted_taken = 1;
branch_offset = imm_b;
end
default: begin
branch_predicted_taken = 0;
branch_offset = 32'd4;
end
endcase
end
2017-11-30 22:30:49 +00:00
always_ff @(posedge clk) begin
if (!stall_in) begin
2017-12-30 13:48:14 +00:00
branch_predicted_taken_out <= branch_predicted_taken;
2017-12-25 23:12:55 +00:00
instr_out <= instr_read_value_in;
2017-12-30 13:48:14 +00:00
next_pc <= pc + branch_offset;
pc_out <= pc;
if (flush_in)
instr_out <= `RV32_INSTR_NOP;
end
2017-11-30 22:30:49 +00:00
end
endmodule
2017-12-01 23:30:33 +00:00
`endif