summaryrefslogtreecommitdiff
path: root/rtl/core/core_control_cycles.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-01-21 06:23:46 -0600
committerAlejandro Soto <alejandro@34project.org>2024-02-20 11:11:17 -0600
commitf3b18ead59ae02f95dabbf0a1dea40873a816975 (patch)
tree8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/core_control_cycles.sv
parenta8bc5a353ea997f73209b39377ee15a73e471237 (diff)
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/core_control_cycles.sv')
-rw-r--r--rtl/core/core_control_cycles.sv148
1 files changed, 148 insertions, 0 deletions
diff --git a/rtl/core/core_control_cycles.sv b/rtl/core/core_control_cycles.sv
new file mode 100644
index 0000000..772697d
--- /dev/null
+++ b/rtl/core/core_control_cycles.sv
@@ -0,0 +1,148 @@
+`include "core/uarch.sv"
+
+module core_control_cycles
+(
+ input logic clk,
+ rst_n,
+ halt,
+ mul,
+ psr,
+ ldst,
+ bubble,
+ coproc,
+ exception,
+ mem_ready,
+ mem_fault,
+ mul_add,
+ mul_long,
+ mul_ready,
+ pop_valid,
+ trivial_shift,
+ ldst_reject,
+ ldst_writeback,
+ data_snd_shift_by_reg,
+
+ output ctrl_cycle cycle,
+ next_cycle
+);
+
+ /* qts-qii51007-recommended-hdl.pdf, p. 66
+ * In Quartus II integrated synthesis, the enumerated type that defines the states for the
+ * state machine must be of an unsigned integer type as in Example 13–52. If you do not
+ * specify the enumerated type as int unsigned, a signed int type is used by default. In
+ * this case, the Quartus II integrated synthesis synthesizes the design, but does not infer
+ * or optimize the logic as a state machine.
+ */
+ enum int unsigned
+ {
+ ISSUE,
+ RD_INDIRECT_SHIFT,
+ WITH_SHIFT,
+ TRANSFER,
+ BASE_WRITEBACK,
+ ESCALATE,
+ EXCEPTION,
+ MUL,
+ MUL_ACC_LD,
+ MUL_HI_WB,
+ PSR,
+ COPROC
+ } state, next_state;
+
+ // TODO: debe estar escrito de tal forma que Quartus infiera una FSM
+
+ assign cycle.issue = state == ISSUE;
+ assign cycle.rd_indirect_shift = state == RD_INDIRECT_SHIFT;
+ assign cycle.with_shift = state == WITH_SHIFT;
+ assign cycle.transfer = state == TRANSFER;
+ assign cycle.base_writeback = state == BASE_WRITEBACK;
+ assign cycle.escalate = state == ESCALATE;
+ assign cycle.exception = state == EXCEPTION;
+ assign cycle.mul = state == MUL;
+ assign cycle.mul_acc_ld = state == MUL_ACC_LD;
+ assign cycle.mul_hi_wb = state == MUL_HI_WB;
+ assign cycle.psr = state == PSR;
+ assign cycle.coproc = state == COPROC;
+
+ assign next_cycle.issue = next_state == ISSUE;
+ assign next_cycle.rd_indirect_shift = next_state == RD_INDIRECT_SHIFT;
+ assign next_cycle.with_shift = next_state == WITH_SHIFT;
+ assign next_cycle.transfer = next_state == TRANSFER;
+ assign next_cycle.base_writeback = next_state == BASE_WRITEBACK;
+ assign next_cycle.escalate = next_state == ESCALATE;
+ assign next_cycle.exception = next_state == EXCEPTION;
+ assign next_cycle.mul = next_state == MUL;
+ assign next_cycle.mul_acc_ld = next_state == MUL_ACC_LD;
+ assign next_cycle.mul_hi_wb = next_state == MUL_HI_WB;
+ assign next_cycle.psr = next_state == PSR;
+ assign next_cycle.coproc = next_state == COPROC;
+
+ always_comb begin
+ next_state = ISSUE;
+
+ unique case(state)
+ ISSUE:
+ if(exception)
+ next_state = ESCALATE;
+ else if(halt)
+ next_state = ISSUE;
+ else if(mul)
+ next_state = mul_add ? MUL_ACC_LD : MUL;
+ else if(data_snd_shift_by_reg)
+ next_state = RD_INDIRECT_SHIFT;
+ else if(!trivial_shift)
+ next_state = WITH_SHIFT;
+ else if(coproc)
+ next_state = COPROC;
+
+ RD_INDIRECT_SHIFT:
+ if(!trivial_shift)
+ next_state = WITH_SHIFT;
+
+ ESCALATE:
+ next_state = EXCEPTION;
+
+ TRANSFER: begin
+ if(!mem_ready || pop_valid)
+ next_state = TRANSFER;
+ else if(ldst_writeback)
+ next_state = BASE_WRITEBACK;
+
+ if(mem_ready && mem_fault)
+ next_state = ESCALATE;
+
+ if(ldst_reject)
+ next_state = ISSUE;
+ end
+
+ MUL:
+ if(!mul_ready)
+ next_state = MUL;
+ else if(mul_long)
+ next_state = MUL_HI_WB;
+
+ MUL_ACC_LD:
+ next_state = MUL;
+
+ /* Este default evita problemas de sintetizado, ya que Quartus
+ * asume que los casos mencionados son exhaustivos, provocando
+ * bugs muy difíciles de depurar. No es lo mismo que si se quita
+ * default.
+ */
+ default: ;
+ endcase
+
+ if(bubble)
+ next_state = ISSUE;
+ else if(next_state == ISSUE) begin
+ if(ldst)
+ next_state = TRANSFER;
+ else if(psr)
+ next_state = PSR;
+ end
+ end
+
+ always_ff @(posedge clk or negedge rst_n)
+ state <= !rst_n ? ISSUE : next_state;
+
+endmodule