summaryrefslogtreecommitdiff
path: root/rtl/core/core_control_data.sv
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/core/core_control_data.sv')
-rw-r--r--rtl/core/core_control_data.sv117
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