diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-01-21 06:23:46 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-02-20 11:11:17 -0600 |
| commit | f3b18ead59ae02f95dabbf0a1dea40873a816975 (patch) | |
| tree | 8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/core_control_cycles.sv | |
| parent | a8bc5a353ea997f73209b39377ee15a73e471237 (diff) | |
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/core_control_cycles.sv')
| -rw-r--r-- | rtl/core/core_control_cycles.sv | 148 |
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 |
