diff --git a/doc/index.rst b/doc/index.rst index e393a36..20eb826 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -77,7 +77,7 @@ serv_ctrl .. image:: serv_ctrl.png -serv_ctrl keeps track of the current PC and contains the logic needed to calculate the next PC. The PC is stored in shift register with a parellel output connected to the instruction bus. New instructions are fetched by asserting o_ibus_cyc until there is a response on i_ibus_ack. Instruction fetches occur when the reset signal is deasserted, which is what gets SERV started, or when the PC has finished updating its value. +serv_ctrl keeps track of the current PC and contains the logic needed to calculate the next PC. The PC is stored in shift register with a parellel output connected to the instruction bus. The new PC can come from three sources. For normal instructions, it is incremented by four, which is the next 32-bit address. Jumps can be absolute or relative to the current PC. Absolute jumps are precalculated in serv_bufreg and written directly to the PC. PC relative jumps have the offset part precalculated in serv_bufreg which gets added to the current PC before storing as the new PC. The third source for the new PC comes from the CSR registers when entering or returning traps. @@ -120,7 +120,9 @@ serv_rf_ram_if converts between the SERV RF IF and the serv_rf_ram interface serv_state ^^^^^^^^^^ -serv_state keeps track of the state for the core and contains all dynamic control signals during an operations life time. Also controls the accesses towards the RF and dbus +serv_state keeps track of the state for the core and contains all dynamic control signals during an operations life time. Also controls the accesses towards the RF, ibus and dbus + +New instructions are fetched by asserting o_ibus_cyc until there is a response on i_ibus_ack. Instruction fetches occur when the reset signal is deasserted, which is what gets SERV started, or when the PC has finished updating its value. shift_reg ^^^^^^^^^ diff --git a/doc/serv_ctrl.png b/doc/serv_ctrl.png index 469b133..d364776 100644 Binary files a/doc/serv_ctrl.png and b/doc/serv_ctrl.png differ diff --git a/doc/serv_ctrl_int.png b/doc/serv_ctrl_int.png index 292145e..f017a6a 100644 Binary files a/doc/serv_ctrl_int.png and b/doc/serv_ctrl_int.png differ diff --git a/rtl/serv_ctrl.v b/rtl/serv_ctrl.v index 826f0b2..5a5554e 100644 --- a/rtl/serv_ctrl.v +++ b/rtl/serv_ctrl.v @@ -4,32 +4,28 @@ module serv_ctrl parameter RESET_PC = 32'd0, parameter WITH_CSR = 1) ( - input wire clk, - input wire i_rst, + input wire clk, + input wire i_rst, //State - input wire i_pc_en, - input wire i_cnt12to31, - input wire i_cnt0, - input wire i_cnt2, - input wire i_cnt_done, + input wire i_pc_en, + input wire i_cnt12to31, + input wire i_cnt0, + input wire i_cnt2, + input wire i_cnt_done, //Control - input wire i_jump, - input wire i_jal_or_jalr, - input wire i_utype, - input wire i_pc_rel, - input wire i_trap, + input wire i_jump, + input wire i_jal_or_jalr, + input wire i_utype, + input wire i_pc_rel, + input wire i_trap, //Data - input wire i_imm, - input wire i_buf, - input wire i_csr_pc, - output wire o_rd, - output wire o_bad_pc, + input wire i_imm, + input wire i_buf, + input wire i_csr_pc, + output wire o_rd, + output wire o_bad_pc, //External - output reg [31:0] o_ibus_adr, - output wire o_ibus_cyc, - input wire i_ibus_ack); - - reg en_pc_r; + output reg [31:0] o_ibus_adr); wire pc_plus_4; wire pc_plus_4_cy; @@ -67,17 +63,12 @@ module serv_ctrl assign pc_plus_offset_aligned = pc_plus_offset & !i_cnt0; - assign o_ibus_cyc = en_pc_r & !i_pc_en; - initial if (RESET_STRATEGY == "NONE") o_ibus_adr = RESET_PC; always @(posedge clk) begin pc_plus_4_cy_r <= i_pc_en & pc_plus_4_cy; pc_plus_offset_cy_r <= i_pc_en & pc_plus_offset_cy; - if (i_ibus_ack | i_pc_en | i_rst) - en_pc_r <= i_pc_en | i_rst; - if (RESET_STRATEGY == "NONE") begin if (i_pc_en) o_ibus_adr <= {new_pc, o_ibus_adr[31:1]}; diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 9701180..27ef1b0 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -8,6 +8,7 @@ module serv_state output wire o_trap_taken, output reg o_pending_irq, input wire i_dbus_ack, + output wire o_ibus_cyc, input wire i_ibus_ack, output wire o_rf_rreq, output wire o_rf_wreq, @@ -50,6 +51,7 @@ module serv_state reg [4:2] o_cnt; reg [3:0] o_cnt_r; + reg ibus_cyc; //Update PC in RUN or TRAP states assign o_ctrl_pc_en = o_cnt_en & !o_init; @@ -98,7 +100,22 @@ module serv_state initial if (RESET_STRATEGY == "NONE") o_cnt_r = 4'b0001; + + assign o_ibus_cyc = ibus_cyc & !i_rst; + always @(posedge i_clk) begin + //ibus_cyc changes on three conditions. + //1. i_rst is asserted. Together with the async gating above, o_ibus_cyc + // will be asserted as soon as the reset is released. This is how the + // first instruction is fetced + //2. o_cnt_done and o_ctrl_pc_en are asserted. This means that SERV just + // finished updating the PC, is done with the current instruction and + // o_ibus_cyc gets asserted to fetch a new instruction + //3. When i_ibus_ack, a new instruction is fetched and o_ibus_cyc gets + // deasserted to finish the transaction + if (i_ibus_ack | o_cnt_done | i_rst) + ibus_cyc <= o_ctrl_pc_en | i_rst; + if (o_cnt_done) o_ctrl_jump <= o_init & take_branch; diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 0bb0f4e..c7fc54f 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -197,6 +197,7 @@ module serv_top //External .o_dbus_cyc (o_dbus_cyc), .i_dbus_ack (i_dbus_ack), + .o_ibus_cyc (o_ibus_cyc), .i_ibus_ack (i_ibus_ack), //RF Interface .o_rf_rreq (o_rf_rreq), @@ -322,10 +323,7 @@ module serv_top .o_rd (ctrl_rd), .o_bad_pc (bad_pc), //External - .o_ibus_adr (o_ibus_adr), - .o_ibus_cyc (o_ibus_cyc), - .i_ibus_ack (i_ibus_ack)); - + .o_ibus_adr (o_ibus_adr)); serv_alu alu (