summaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'rtl')
-rw-r--r--rtl/core/arm810.sv2
-rw-r--r--rtl/core/control/select.sv34
-rw-r--r--rtl/core/control/writeback.sv108
-rw-r--r--rtl/core/regs/file.sv40
-rw-r--r--rtl/core/regs/regs.sv45
-rw-r--r--rtl/core/uarch.sv3
6 files changed, 127 insertions, 105 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv
index 3f237aa..5525f95 100644
--- a/rtl/core/arm810.sv
+++ b/rtl/core/arm810.sv
@@ -19,7 +19,7 @@ module arm810
core_fetch #(.PREFETCH_ORDER(2)) fetch
(
- .branch(explicit_branch | wr_pc),
+ .branch(explicit_branch || wr_pc),
.flush(0), //TODO
.target(wr_pc ? wr_value[31:2] : branch_target),
.addr(insn_addr),
diff --git a/rtl/core/control/select.sv b/rtl/core/control/select.sv
index cedf3cf..3c0ec6c 100644
--- a/rtl/core/control/select.sv
+++ b/rtl/core/control/select.sv
@@ -22,36 +22,44 @@ module core_control_select
output psr_mode reg_mode
);
- reg_num r_shift;
+ reg_num r_shift, last_ra, last_rb;
assign reg_mode = `MODE_SVC; //TODO
- always_ff @(posedge clk)
+ always_comb begin
+ ra = last_ra;
+ rb = last_rb;
+
unique case(next_cycle)
ISSUE:
if(issue) begin
- ra <= dec_data.rn;
- rb <= dec_snd.r;
- r_shift <= dec_snd.r_shift;
+ ra = dec_data.rn;
+ rb = dec_snd.r;
end
- RD_INDIRECT_SHIFT:
- rb <= r_shift;
-
TRANSFER:
if(cycle != TRANSFER || mem_ready)
// final_rd viene de dec_ldst.rd
- rb <= pop_valid ? popped : final_rd;
+ rb = pop_valid ? popped : final_rd;
MUL_ACC_LD: begin
- ra <= mul_r_add_hi;
- rb <= mul_r_add_lo;
+ ra = mul_r_add_hi;
+ rb = mul_r_add_lo;
end
endcase
+ end
+
+ always_ff @(posedge clk) begin
+ last_ra <= ra;
+ last_rb <= rb;
+
+ if(next_cycle == ISSUE && issue)
+ r_shift <= dec_snd.r_shift;
+ end
initial begin
- ra = {$bits(ra){1'b0}};
- rb = {$bits(rb){1'b0}};
+ last_ra = {$bits(ra){1'b0}};
+ last_rb = {$bits(rb){1'b0}};
r_shift = {$bits(r_shift){1'b0}};
end
diff --git a/rtl/core/control/writeback.sv b/rtl/core/control/writeback.sv
index 733881c..a4465ff 100644
--- a/rtl/core/control/writeback.sv
+++ b/rtl/core/control/writeback.sv
@@ -35,53 +35,91 @@ module core_control_writeback
output psr_flags wb_alu_flags
);
- always_ff @(posedge clk) begin
- wb_alu_flags <= alu_flags;
+ reg_num last_rd;
+ always_comb begin
+ rd = last_rd;
unique case(next_cycle)
TRANSFER:
if(mem_ready)
- rd <= final_rd;
+ rd = final_rd;
ISSUE, BASE_WRITEBACK:
- rd <= final_rd;
+ rd = final_rd;
EXCEPTION:
- rd <= `R15;
+ rd = `R15;
MUL_HI_WB:
- rd <= mul_r_add_hi;
+ rd = mul_r_add_hi;
endcase
unique case(next_cycle)
ISSUE:
- if(issue)
- final_rd <= dec_data.rd;
+ writeback = final_writeback;
TRANSFER:
- if((cycle != TRANSFER || mem_ready) && pop_valid)
- final_rd <= popped;
+ writeback = mem_ready && !mem_write;
BASE_WRITEBACK:
- final_rd <= ra;
+ writeback = !mem_write;
+
+ EXCEPTION, MUL_HI_WB:
+ writeback = 1;
+
+ default:
+ writeback = 0;
+ endcase
+
+ unique case(cycle)
+ TRANSFER:
+ wr_value = mem_data_rd;
+
+ BASE_WRITEBACK:
+ wr_value = saved_base;
+
+ MUL, MUL_HI_WB:
+ wr_value = mul_q_lo;
+
+ default:
+ // Ruta combinacional larga
+ wr_value = q_alu;
+ endcase
+
+ unique case(next_cycle)
+ TRANSFER:
+ if(mem_ready)
+ wr_value = mem_data_rd;
+
+ BASE_WRITEBACK:
+ wr_value = mem_data_rd;
EXCEPTION:
- final_rd <= `R14;
+ wr_value = vector;
+
+ MUL_HI_WB:
+ wr_value = mul_q_hi;
endcase
+ end
+
+ always_ff @(posedge clk) begin
+ last_rd <= rd;
+ wb_alu_flags <= alu_flags;
- writeback <= 0;
unique case(next_cycle)
ISSUE:
- writeback <= final_writeback;
+ if(issue)
+ final_rd <= dec_data.rd;
TRANSFER:
- writeback <= mem_ready && !mem_write;
+ if((cycle != TRANSFER || mem_ready) && pop_valid)
+ final_rd <= popped;
BASE_WRITEBACK:
- writeback <= !mem_write;
+ final_rd <= ra;
- EXCEPTION, MUL_HI_WB:
- writeback <= 1;
+ EXCEPTION:
+ final_rd <= `R14;
endcase
unique case(next_cycle)
@@ -108,48 +146,16 @@ module core_control_writeback
EXCEPTION:
final_update_flags <= 0;
endcase
-
- unique case(cycle)
- TRANSFER:
- wr_value <= mem_data_rd;
-
- BASE_WRITEBACK:
- wr_value <= saved_base;
-
- MUL, MUL_HI_WB:
- wr_value <= mul_q_lo;
-
- default:
- wr_value <= q_alu;
- endcase
-
- unique case(next_cycle)
- TRANSFER:
- if(mem_ready)
- wr_value <= mem_data_rd;
-
- BASE_WRITEBACK:
- wr_value <= mem_data_rd;
-
- EXCEPTION:
- wr_value <= vector;
-
- MUL_HI_WB:
- wr_value <= mul_q_hi;
- endcase
end
initial begin
- rd = 0;
+ last_rd = 0;
final_rd = 0;
-
- writeback = 0;
final_writeback = 0;
update_flags = 0;
final_update_flags = 0;
- wr_value = 0;
wb_alu_flags = {$bits(wb_alu_flags){1'b0}};
end
diff --git a/rtl/core/regs/file.sv b/rtl/core/regs/file.sv
index e0f9b4c..38c3301 100644
--- a/rtl/core/regs/file.sv
+++ b/rtl/core/regs/file.sv
@@ -3,27 +3,47 @@
module core_reg_file
(
input logic clk,
- input reg_index rd_index,
- wr_index,
+ input psr_mode rd_mode,
+ input reg_num rd_r,
+ input reg_index wr_index,
input logic wr_enable,
+ wr_enable_file,
input word wr_value,
+ wr_current,
+ pc_word,
output word rd_value
);
// Ver comentario en uarch.sv
- word file[30] /*verilator public*/;
+ word file[`NUM_GPREGS] /*verilator public*/;
+ word rd_actual;
+ logic rd_pc, hold_rd_pc, forward;
+ reg_index rd_index;
+
+ core_reg_map map_rd
+ (
+ .r(rd_r),
+ .mode(rd_mode),
+ .is_pc(rd_pc),
+ .index(rd_index)
+ );
+
+ assign rd_value = hold_rd_pc ? pc_word : forward ? wr_current : rd_actual;
- //FIXME: Esto claramente no sirve
-`ifdef VERILATOR
- always_ff @(negedge clk) begin
-`else
always_ff @(posedge clk) begin
-`endif
- if(wr_enable)
+ forward <= wr_enable && rd_index == wr_index;
+ hold_rd_pc <= rd_pc;
+
+ if(wr_enable_file)
file[wr_index] <= wr_value;
- rd_value <= file[rd_index];
+ rd_actual <= file[rd_index];
+ end
+
+ initial begin
+ forward = 0;
+ hold_rd_pc = 0;
end
endmodule
diff --git a/rtl/core/regs/regs.sv b/rtl/core/regs/regs.sv
index 9b9ba57..b25a122 100644
--- a/rtl/core/regs/regs.sv
+++ b/rtl/core/regs/regs.sv
@@ -23,48 +23,28 @@ module core_regs
* sincronizadas del archivo de registros.
*/
- logic rd_pc_a, rd_pc_b, wr_pc, file_wr_enable;
- reg_index rd_index_a, rd_index_b, wr_index;
- word pc_word, file_rd_value_a, file_rd_value_b;
+ word pc_word, wr_current;
+ logic wr_pc, wr_enable_file;
+ reg_index wr_index;
+ assign branch = wr_enable && wr_pc;
assign pc_word = {pc_visible, 2'b00};
- assign rd_value_a = rd_pc_a ? pc_word : (wr_enable && rd_index_a == wr_index) ? wr_value : file_rd_value_a;
- assign rd_value_b = rd_pc_b ? pc_word : (wr_enable && rd_index_b == wr_index) ? wr_value : file_rd_value_b;
- assign file_wr_enable = wr_enable & ~wr_pc;
- assign branch = wr_enable & wr_pc;
+ assign wr_enable_file = wr_enable && !wr_pc;
core_reg_file a
(
- .rd_index(rd_index_a),
- .rd_value(file_rd_value_a),
- .wr_enable(file_wr_enable),
+ .rd_r(rd_r_a),
+ .rd_value(rd_value_a),
.*
);
core_reg_file b
(
- .rd_index(rd_index_b),
- .rd_value(file_rd_value_b),
- .wr_enable(file_wr_enable),
+ .rd_r(rd_r_b),
+ .rd_value(rd_value_b),
.*
);
- core_reg_map map_rd_a
- (
- .r(rd_r_a),
- .mode(rd_mode),
- .is_pc(rd_pc_a),
- .index(rd_index_a)
- );
-
- core_reg_map map_rd_b
- (
- .r(rd_r_b),
- .mode(rd_mode),
- .is_pc(rd_pc_b),
- .index(rd_index_b)
- );
-
core_reg_map map_wr
(
.r(wr_r),
@@ -73,4 +53,11 @@ module core_regs
.index(wr_index)
);
+ always_ff @(posedge clk)
+ if(wr_enable)
+ wr_current <= wr_value;
+
+ initial
+ wr_current = 0;
+
endmodule
diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv
index 2b3c55a..d4654a7 100644
--- a/rtl/core/uarch.sv
+++ b/rtl/core/uarch.sv
@@ -22,7 +22,8 @@ typedef logic[29:0] ptr;
* registers are 32 bits wide and are described in General-purpose registers on
* page A2-6.
*/
-typedef logic[4:0] reg_index;
+`define NUM_GPREGS 30
+typedef logic[$clog2(`NUM_GPREGS) - 1:0] reg_index;
typedef logic[3:0] alu_op;