summaryrefslogtreecommitdiff
path: root/rtl/core/control
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/core/control')
-rw-r--r--rtl/core/control/control.sv126
-rw-r--r--rtl/core/control/cycles.sv56
-rw-r--r--rtl/core/control/mux.sv50
-rw-r--r--rtl/core/control/stall.sv44
4 files changed, 181 insertions, 95 deletions
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 95d3bb9..059cb2d 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -3,16 +3,10 @@
module core_control
(
input logic clk,
- dec_execute,
- dec_undefined,
- dec_conditional,
- dec_uses_rn,
- dec_branch,
- dec_writeback,
- dec_update_flags,
- input ptr dec_branch_offset,
- input snd_decode dec_snd,
+ input datapath_decode dec,
+ input branch_decode dec_branch,
input data_decode dec_data,
+ input snd_decode dec_snd,
input ldst_decode dec_ldst,
input ptr fetch_insn_pc,
input psr_flags flags,
@@ -49,17 +43,7 @@ module core_control
mem_write
);
- enum
- {
- ISSUE,
- RD_INDIRECT_SHIFT,
- WITH_SHIFT,
- TRANSFER,
- BASE_WRITEBACK,
- EXCEPTION
- } cycle, next_cycle;
-
- logic bubble, next_bubble, final_writeback, final_update_flags,
+ logic final_writeback, final_update_flags,
ldst, ldst_pre, ldst_increment, ldst_writeback, pop_valid,
data_snd_is_imm, data_snd_shift_by_reg, trivial_shift,
undefined, exception, high_vectors;
@@ -72,7 +56,6 @@ module core_control
reg_list mem_regs, next_regs_upper, next_regs_lower;
ptr pc /*verilator public*/, next_pc_visible;
- assign stall = next_cycle != ISSUE || next_bubble;
assign reg_mode = `MODE_SVC; //TODO
assign trivial_shift = shifter_shift == 0;
assign mem_data_wr = rd_value_b;
@@ -82,10 +65,19 @@ module core_control
assign vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00};
assign next_pc_visible = fetch_insn_pc + 2;
- assign next_bubble =
- ((dec_update_flags || dec_conditional) && (final_update_flags || update_flags))
- || (final_writeback && ((dec_uses_rn && (final_rd == dec_data.rn || dec_data.rn == `R15))
- || final_rd == dec_snd.r || dec_snd.r == `R15));
+ ctrl_cycle cycle, next_cycle;
+
+ core_control_cycles cycles
+ (
+ .*
+ );
+
+ logic bubble, next_bubble;
+
+ core_control_stall ctrl_stall
+ (
+ .*
+ );
core_control_ldst_pop ldst_pop
(
@@ -97,67 +89,15 @@ module core_control
.pop_lower(popped_lower)
);
- always_comb begin
- unique case(cycle)
- RD_INDIRECT_SHIFT: shifter_shift = rd_value_b[7:0];
- default: shifter_shift = {2'b00, data_shift_imm};
- endcase
-
- next_cycle = ISSUE;
-
- unique case(cycle)
- ISSUE:
- if(exception)
- next_cycle = EXCEPTION;
- else if(data_snd_shift_by_reg)
- next_cycle = RD_INDIRECT_SHIFT;
- else if(~trivial_shift)
- next_cycle = WITH_SHIFT;
-
- RD_INDIRECT_SHIFT:
- if(~trivial_shift)
- next_cycle = WITH_SHIFT;
-
- TRANSFER:
- if(!mem_ready || pop_valid)
- next_cycle = TRANSFER;
- else if(ldst_writeback)
- next_cycle = BASE_WRITEBACK;
-
- default: ;
- endcase
-
- if(bubble)
- next_cycle = ISSUE;
- else if(next_cycle == ISSUE && ldst)
- next_cycle = TRANSFER;
-
- unique case(cycle)
- TRANSFER: alu_a = saved_base;
- EXCEPTION: alu_a = {pc, 2'b00};
- default: alu_a = rd_value_a;
- endcase
-
- unique case(cycle)
- RD_INDIRECT_SHIFT, WITH_SHIFT:
- alu_b = saved_base;
-
- TRANSFER:
- alu_b = mem_offset;
-
- default:
- if(data_snd_is_imm)
- alu_b = {{20{1'b0}}, data_imm};
- else
- alu_b = rd_value_b;
- endcase
+ core_control_mux mux
+ (
+ .*
+ );
+ always_comb
vector_offset = 3'b001; //TODO
- end
always_ff @(posedge clk) begin
- cycle <= next_cycle;
- bubble <= 0;
branch <= 0;
writeback <= 0;
update_flags <= 0;
@@ -174,11 +114,9 @@ module core_control
final_writeback <= 0;
final_update_flags <= 0;
- bubble <= next_bubble;
-
- if(dec_execute & ~next_bubble) begin
- branch <= dec_branch;
- branch_target <= next_pc_visible + dec_branch_offset;
+ if(dec.execute & ~next_bubble) begin
+ branch <= dec_branch.branch;
+ branch_target <= next_pc_visible + dec_branch.offset;
alu <= dec_data.op;
ra <= dec_data.rn;
@@ -208,13 +146,13 @@ module core_control
mem_write <= !dec_ldst.load;
final_rd <= dec_data.rd;
- final_writeback <= dec_writeback;
- final_update_flags <= dec_update_flags;
+ final_writeback <= dec.writeback;
+ final_update_flags <= dec.update_flags;
end
update_flags <= final_update_flags;
writeback <= final_writeback;
- undefined <= dec_undefined;
+ undefined <= dec.undefined;
rd <= final_rd;
pc <= fetch_insn_pc;
@@ -238,9 +176,10 @@ module core_control
mem_offset <= alu_b;
end
+ writeback <= mem_ready && !mem_write;
if(mem_ready) begin
+ rd <= final_rd;
wr_value <= mem_data_rd;
- writeback <= !mem_write;
end
if(cycle != TRANSFER || mem_ready) begin
@@ -249,8 +188,8 @@ module core_control
saved_base <= q_alu;
if(pop_valid) begin
- rd <= popped;
rb <= popped;
+ final_rd <= popped;
end else
rb <= final_rd; // Viene de dec_ldst.rd
end
@@ -286,9 +225,6 @@ module core_control
end
initial begin
- cycle = ISSUE;
- bubble = 0;
-
pc = 0;
pc_visible = 2;
diff --git a/rtl/core/control/cycles.sv b/rtl/core/control/cycles.sv
new file mode 100644
index 0000000..f804e93
--- /dev/null
+++ b/rtl/core/control/cycles.sv
@@ -0,0 +1,56 @@
+`include "core/uarch.sv"
+
+module core_control_cycles
+(
+ input logic clk,
+ ldst,
+ bubble,
+ exception,
+ mem_ready,
+ pop_valid,
+ trivial_shift,
+ ldst_writeback,
+ data_snd_shift_by_reg,
+
+ output ctrl_cycle cycle,
+ next_cycle
+);
+
+ always_comb begin
+ next_cycle = ISSUE;
+
+ unique case(cycle)
+ ISSUE:
+ if(exception)
+ next_cycle = EXCEPTION;
+ else if(data_snd_shift_by_reg)
+ next_cycle = RD_INDIRECT_SHIFT;
+ else if(!trivial_shift)
+ next_cycle = WITH_SHIFT;
+
+ RD_INDIRECT_SHIFT:
+ if(!trivial_shift)
+ next_cycle = WITH_SHIFT;
+
+ TRANSFER:
+ if(!mem_ready || pop_valid)
+ next_cycle = TRANSFER;
+ else if(ldst_writeback)
+ next_cycle = BASE_WRITEBACK;
+
+ default: ;
+ endcase
+
+ if(bubble)
+ next_cycle = ISSUE;
+ else if(next_cycle == ISSUE && ldst)
+ next_cycle = TRANSFER;
+ end
+
+ always_ff @(posedge clk)
+ cycle <= next_cycle;
+
+ initial
+ cycle = ISSUE;
+
+endmodule
diff --git a/rtl/core/control/mux.sv b/rtl/core/control/mux.sv
new file mode 100644
index 0000000..58d2197
--- /dev/null
+++ b/rtl/core/control/mux.sv
@@ -0,0 +1,50 @@
+`include "core/uarch.sv"
+
+module core_control_mux
+(
+ input logic clk,
+
+ input word rd_value_a,
+ rd_value_b,
+
+ input ctrl_cycle cycle,
+ input logic data_snd_is_imm,
+ input logic[5:0] data_shift_imm,
+ input logic[11:0] data_imm,
+ input ptr pc,
+ input word saved_base,
+ mem_offset,
+
+ output word alu_a,
+ alu_b,
+ output logic[7:0] shifter_shift
+);
+
+ always_comb begin
+ unique case(cycle)
+ RD_INDIRECT_SHIFT: shifter_shift = rd_value_b[7:0];
+ default: shifter_shift = {2'b00, data_shift_imm};
+ endcase
+
+ unique case(cycle)
+ TRANSFER: alu_a = saved_base;
+ EXCEPTION: alu_a = {pc, 2'b00};
+ default: alu_a = rd_value_a;
+ endcase
+
+ unique case(cycle)
+ RD_INDIRECT_SHIFT, WITH_SHIFT:
+ alu_b = saved_base;
+
+ TRANSFER:
+ alu_b = mem_offset;
+
+ default:
+ if(data_snd_is_imm)
+ alu_b = {{20{1'b0}}, data_imm};
+ else
+ alu_b = rd_value_b;
+ endcase
+ end
+
+endmodule
diff --git a/rtl/core/control/stall.sv b/rtl/core/control/stall.sv
new file mode 100644
index 0000000..4dc56e4
--- /dev/null
+++ b/rtl/core/control/stall.sv
@@ -0,0 +1,44 @@
+`include "core/uarch.sv"
+
+module core_control_stall
+(
+ input logic clk,
+
+ input datapath_decode dec,
+ input data_decode dec_data,
+ input snd_decode dec_snd,
+
+ input ctrl_cycle next_cycle,
+ input logic final_update_flags,
+ update_flags,
+ final_writeback,
+ writeback,
+ input reg_num final_rd,
+
+ output logic stall,
+ bubble,
+ next_bubble
+);
+
+ logic pc_writeback_hazard, flags_hazard, data_hazard, rn_hazard,
+ snd_hazard, flags_dependency, updating_flags;
+
+ assign stall = next_cycle != ISSUE || next_bubble;
+ assign next_bubble = pc_writeback_hazard || flags_hazard || data_hazard;
+
+ assign pc_writeback_hazard = final_writeback && final_rd == `R15;
+ assign flags_hazard = flags_dependency && updating_flags;
+ assign data_hazard = final_writeback && (rn_hazard || snd_hazard);
+ assign rn_hazard = dec_data.uses_rn && (final_rd == dec_data.rn || dec_data.rn == `R15);
+ assign snd_hazard = !dec_snd.is_imm && (dec_snd.r == final_rd || dec_snd.r == `R15);
+
+ assign flags_dependency = dec.update_flags || dec.conditional;
+ assign updating_flags = final_update_flags || update_flags;
+
+ always_ff @(posedge clk)
+ bubble <= next_cycle == ISSUE ? next_bubble : 0;
+
+ initial
+ bubble = 0;
+
+endmodule