diff options
Diffstat (limited to 'rtl/core/core_control_data.sv')
| -rw-r--r-- | rtl/core/core_control_data.sv | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/rtl/core/core_control_data.sv b/rtl/core/core_control_data.sv new file mode 100644 index 0000000..3174ee1 --- /dev/null +++ b/rtl/core/core_control_data.sv @@ -0,0 +1,117 @@ +`include "core/uarch.sv" + +module core_control_data +( + input logic clk, + rst_n, + + input insn_decode dec, + input word rd_value_a, + rd_value_b, + input logic mem_ready, + mem_write, + input word mem_data_rd, + q_alu, + q_shifter, + input logic c_shifter, + + input ctrl_cycle cycle, + next_cycle, + input ptr pc_visible, + input logic ldst_next, + input logic[1:0] ldst_shift, + input word mem_offset, + input psr_flags flags, + input logic exception_offset_pc, + + output alu_op alu, + output word alu_a, + alu_b, + saved_base, + output shifter_control shifter, + output word shifter_base, + output logic[7:0] shifter_shift, + output logic c_logic, + trivial_shift, + data_snd_shift_by_reg +); + + logic data_snd_is_imm; + logic[5:0] data_shift_imm; + logic[11:0] data_imm; + + assign trivial_shift = shifter_shift == 0; + + always_comb begin + if(cycle.rd_indirect_shift) + shifter_shift = rd_value_b[7:0]; + else if(cycle.transfer) + shifter_shift = {3'b000, ldst_shift, 3'b000}; + else + shifter_shift = {2'b00, data_shift_imm}; + + if(cycle.transfer) + alu_a = saved_base; + else if(cycle.exception) + alu_a = {pc_visible, 2'b00}; + else + alu_a = rd_value_a; + + if(cycle.rd_indirect_shift || cycle.with_shift) + alu_b = saved_base; + else if(cycle.transfer) + alu_b = mem_offset; + else if(data_snd_is_imm) + alu_b = {{20{1'b0}}, data_imm}; + else + alu_b = rd_value_b; + + if(cycle.transfer) + shifter_base = mem_write ? rd_value_b : mem_data_rd; + else + shifter_base = alu_b; + end + + always_ff @(posedge clk or negedge rst_n) + if(!rst_n) begin + alu <= {$bits(alu){1'b0}}; + c_logic <= 0; + shifter <= {$bits(shifter){1'b0}}; + data_imm <= {$bits(data_imm){1'b0}}; + saved_base <= 0; + data_shift_imm <= {$bits(data_shift_imm){1'b0}}; + data_snd_is_imm <= 0; + data_snd_shift_by_reg <= 0; + end else if(next_cycle.issue) begin + alu <= dec.data.op; + c_logic <= 0; + + data_imm <= dec.snd.imm; + data_shift_imm <= dec.snd.shift_imm; + data_snd_is_imm <= dec.snd.is_imm; + data_snd_shift_by_reg <= dec.snd.shift_by_reg; + + shifter.shr <= dec.snd.shr; + shifter.ror <= dec.snd.ror; + shifter.put_carry <= dec.snd.put_carry; + shifter.sign_extend <= dec.snd.sign_extend; + end else if(next_cycle.rd_indirect_shift) begin + saved_base <= rd_value_b; + data_snd_shift_by_reg <= 0; + end else if(next_cycle.with_shift) begin + c_logic <= c_shifter; + saved_base <= q_shifter; + end else if(next_cycle.transfer) begin + if(ldst_next) + saved_base <= q_alu; + + shifter.ror <= 0; + shifter.shr <= !mem_write; + end else if(next_cycle.exception) begin + alu <= `ALU_SUB; + // Either pc_visible - 0 (pc + 8) or pc_visible - 4 (pc + 4) + data_imm <= {9'd0, exception_offset_pc, 2'b00}; + data_snd_is_imm <= 1; + end + +endmodule |
