summaryrefslogtreecommitdiff
path: root/rtl/core/cycles.sv
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rtl/core/cycles.sv130
1 files changed, 113 insertions, 17 deletions
diff --git a/rtl/core/cycles.sv b/rtl/core/cycles.sv
index ddaf237..c416187 100644
--- a/rtl/core/cycles.sv
+++ b/rtl/core/cycles.sv
@@ -10,12 +10,16 @@ module core_cycles
input ptr dec_branch_offset,
input snd_decode dec_snd,
input data_decode dec_data,
+ input ldst_decode dec_ldst,
input ptr fetch_insn_pc,
input psr_flags flags,
- input word rd_value_b,
+ input word rd_value_a,
+ rd_value_b,
q_alu,
q_shifter,
input logic c_shifter,
+ mem_ready,
+ input word mem_data_rd,
output logic stall,
branch,
@@ -29,31 +33,53 @@ module core_cycles
pc_visible,
output psr_mode reg_mode,
output alu_op alu,
- output word alu_b,
+ output word alu_a,
+ alu_b,
wr_value,
output shifter_control shifter,
- output logic[7:0] shifter_shift
+ output logic[7:0] shifter_shift,
+ output ptr mem_addr,
+ output word mem_data_wr,
+ output logic mem_start,
+ mem_write
);
enum
{
ISSUE,
RD_INDIRECT_SHIFT,
- WITH_SHIFT
+ WITH_SHIFT,
+ TRANSFER,
+ BASE_WRITEBACK
} cycle, next_cycle;
logic bubble, 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;
logic[5:0] data_shift_imm;
logic[11:0] data_imm;
- word saved_base;
- reg_num r_shift, final_rd;
+ word saved_base, mem_offset;
+ reg_num r_shift, final_rd, popped_upper, popped_lower, popped;
+ reg_list mem_regs, next_regs_upper, next_regs_lower;
ptr pc;
assign stall = (next_cycle != ISSUE) | bubble;
assign pc_visible = pc + 2;
assign reg_mode = `MODE_SVC; //TODO
+ assign trivial_shift = shifter_shift == 0;
+ assign mem_data_wr = rd_value_b;
+ assign popped = ldst_increment ? popped_lower : popped_upper;
+
+ core_cycles_ldst_pop ldst_pop
+ (
+ .regs(mem_regs),
+ .valid(pop_valid),
+ .next_upper(next_regs_upper),
+ .next_lower(next_regs_lower),
+ .pop_upper(popped_upper),
+ .pop_lower(popped_lower)
+ );
always_comb begin
unique case(cycle)
@@ -61,10 +87,6 @@ module core_cycles
default: shifter_shift = {2'b00, data_shift_imm};
endcase
- trivial_shift = 1;
- if(final_writeback & (shifter.shl | shifter.shr | shifter.ror))
- trivial_shift = shifter_shift == 0;
-
next_cycle = ISSUE;
unique case(cycle)
@@ -78,34 +100,54 @@ module core_cycles
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)
- ISSUE:
+ TRANSFER: alu_a = saved_base;
+ 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;
-
- RD_INDIRECT_SHIFT, WITH_SHIFT:
- alu_b = saved_base;
endcase
end
always_ff @(posedge clk) begin
cycle <= next_cycle;
bubble <= 0;
+ branch <= 0;
writeback <= 0;
- wr_value <= q_alu;
+
+ unique case(cycle)
+ TRANSFER: wr_value <= mem_data_rd;
+ BASE_WRITEBACK: wr_value <= saved_base;
+ default: wr_value <= q_alu;
+ endcase
unique case(next_cycle)
ISSUE: begin
- branch <= 0;
- branch_target <= {30{1'bx}};
final_writeback <= 0;
final_update_flags <= 0;
@@ -135,6 +177,16 @@ module core_cycles
r_shift <= dec_snd.r_shift;
c_in <= flags.c;
+ // TODO: dec_ldst.unprivileged/user_regs
+ // TODO: byte/halfword sizes
+ ldst <= dec_ldst.enable;
+ ldst_pre <= dec_ldst.pre_indexed;
+ ldst_increment <= dec_ldst.increment;
+ ldst_writeback <= dec_ldst.writeback;
+
+ mem_regs <= dec_ldst.regs;
+ mem_write <= !dec_ldst.load;
+
final_rd <= dec_data.rd;
final_writeback <= dec_writeback;
final_update_flags <= dec_update_flags;
@@ -156,6 +208,39 @@ module core_cycles
c_in <= c_shifter;
saved_base <= q_shifter;
end
+
+ TRANSFER: begin
+ if(cycle != TRANSFER) begin
+ ldst <= 0;
+ mem_offset <= alu_b;
+ end
+
+ if(mem_ready) begin
+ wr_value <= mem_data_rd;
+ writeback <= !mem_write;
+ end
+
+ if(cycle != TRANSFER || mem_ready) begin
+ mem_regs <= ldst_increment ? next_regs_lower : next_regs_upper;
+ mem_addr <= ldst_pre ? q_alu[31:2] : alu_a[31:2];
+ saved_base <= q_alu;
+
+ if(pop_valid) begin
+ rd <= popped;
+ rb <= popped;
+ end else
+ rb <= final_rd; // Viene de dec_ldst.rd
+ end
+
+ mem_start <= cycle != TRANSFER || (mem_ready && pop_valid);
+ end
+
+ BASE_WRITEBACK: begin
+ rd <= final_rd;
+ wr_value <= mem_data_rd;
+ writeback <= !mem_write;
+ final_rd <= ra;
+ end
endcase
end
@@ -170,6 +255,17 @@ module core_cycles
branch_target = 30'd0;
data_snd_shift_by_reg = 0;
+ ldst = 0;
+ ldst_pre = 0;
+ ldst_writeback = 0;
+ ldst_increment = 0;
+
+ mem_addr = 30'b0;
+ mem_write = 0;
+ mem_start = 0;
+ mem_regs = 16'b0;
+ mem_offset = 0;
+
final_rd = 0;
final_writeback = 0;
end