mirror of
https://github.com/sxpert/hp-saturn
synced 2024-11-16 19:50:19 +01:00
add mmio
fix rtn instructions decode block 14x
This commit is contained in:
parent
b2ae484450
commit
a1b22269b2
7 changed files with 437 additions and 29 deletions
|
@ -2,6 +2,7 @@ read_verilog -I. saturn_top.v
|
|||
read_verilog -I. saturn_serial.v
|
||||
read_verilog -I. saturn_bus.v
|
||||
read_verilog -I. saturn_hp48gx_rom.v
|
||||
read_verilog -I. saturn_hp48gx_mmio.v
|
||||
read_verilog -I. saturn_bus_controller.v
|
||||
read_verilog -I. saturn_debugger.v
|
||||
read_verilog -I. saturn_control_unit.v
|
||||
|
|
2
run.sh
2
run.sh
|
@ -12,7 +12,7 @@
|
|||
#iverilog -v -Wall -DSIM -o mask_gen_tb mask_gen.v
|
||||
iverilog -v -Wall -DSIM -o z_saturn_test.iv -s saturn_top \
|
||||
saturn_top.v saturn_serial.v \
|
||||
saturn_bus.v saturn_hp48gx_rom.v \
|
||||
saturn_bus.v saturn_hp48gx_rom.v saturn_hp48gx_mmio.v \
|
||||
saturn_bus_controller.v saturn_debugger.v \
|
||||
saturn_control_unit.v saturn_inst_decoder.v\
|
||||
saturn_regs_pc_rstk.v #saturn_alu_module.v
|
||||
|
|
31
saturn_bus.v
31
saturn_bus.v
|
@ -82,6 +82,36 @@ saturn_hp48gx_rom hp48gx_rom (
|
|||
|
||||
wire [3:0] rom_bus_nibble_out;
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* this is the io-ram module
|
||||
* this module only takes one configuration parameter, size is fixed
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
saturn_hp48gx_mmio hp48gx_mmio (
|
||||
.i_clk (i_clk),
|
||||
.i_clk_en (i_clk_en),
|
||||
.i_reset (i_reset),
|
||||
.i_phase (phase),
|
||||
.i_phases (phases),
|
||||
.i_cycle_ctr (cycle_ctr),
|
||||
.i_debug_cycle (dbg_debug_cycle),
|
||||
|
||||
.i_bus_clk_en (bus_clk_en),
|
||||
.i_bus_is_data (ctrl_bus_is_data),
|
||||
.o_bus_nibble_out (mmio_bus_nibble_out),
|
||||
.i_bus_nibble_in (ctrl_bus_nibble_out),
|
||||
.i_bus_daisy (1'b1),
|
||||
.o_bus_daisy (mmio_daisy_out),
|
||||
.o_bus_active (mmio_active)
|
||||
);
|
||||
|
||||
wire [3:0] mmio_bus_nibble_out;
|
||||
wire [0:0] mmio_daisy_out;
|
||||
wire [0:0] mmio_active;
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* the main processor is hidden behind this bus controller device
|
||||
|
@ -151,6 +181,7 @@ assign o_halt = bus_halt || ctrl_halt;
|
|||
*/
|
||||
always @(*) begin
|
||||
ctrl_bus_nibble_in = rom_bus_nibble_out;
|
||||
if (mmio_active) ctrl_bus_nibble_in = mmio_bus_nibble_out;
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
|
|
|
@ -119,9 +119,12 @@
|
|||
`define INSTR_TYPE_SET_MODE 2
|
||||
`define INSTR_TYPE_JUMP 3
|
||||
`define INSTR_TYPE_RTN 4
|
||||
`define INSTR_TYPE_LOAD 5
|
||||
`define INSTR_TYPE_CONFIG 6
|
||||
`define INSTR_TYPE_RESET 7
|
||||
`define INSTR_TYPE_LOAD_LENGTH 5
|
||||
`define INSTR_TYPE_LOAD 6
|
||||
`define INSTR_TYPE_MEM_READ 7
|
||||
`define INSTR_TYPE_MEM_WRITE 8
|
||||
`define INSTR_TYPE_CONFIG 9
|
||||
`define INSTR_TYPE_RESET 10
|
||||
|
||||
|
||||
`define INSTR_TYPE_NONE 15
|
||||
|
|
345
saturn_hp48gx_mmio.v
Normal file
345
saturn_hp48gx_mmio.v
Normal file
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
(c) Raphaël Jacquot 2019
|
||||
|
||||
This file is part of hp_saturn.
|
||||
hp_saturn is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
any later version.
|
||||
hp_saturn is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
|
||||
`include "saturn_def_buscmd.v"
|
||||
|
||||
module saturn_hp48gx_mmio (
|
||||
i_clk,
|
||||
i_clk_en,
|
||||
i_reset,
|
||||
i_phase,
|
||||
i_phases,
|
||||
i_cycle_ctr,
|
||||
i_debug_cycle,
|
||||
|
||||
i_bus_clk_en,
|
||||
i_bus_is_data,
|
||||
o_bus_nibble_out,
|
||||
i_bus_nibble_in,
|
||||
i_bus_daisy,
|
||||
o_bus_daisy,
|
||||
o_bus_active,
|
||||
|
||||
o_menu_height,
|
||||
o_rom_mode
|
||||
);
|
||||
|
||||
input wire [0:0] i_clk;
|
||||
input wire [0:0] i_clk_en;
|
||||
input wire [0:0] i_reset;
|
||||
input wire [1:0] i_phase;
|
||||
input wire [3:0] i_phases;
|
||||
input wire [31:0] i_cycle_ctr;
|
||||
input wire [0:0] i_debug_cycle;
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* bus I/O
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
input wire [0:0] i_bus_clk_en;
|
||||
input wire [0:0] i_bus_is_data;
|
||||
output reg [3:0] o_bus_nibble_out;
|
||||
input wire [3:0] i_bus_nibble_in;
|
||||
input wire [0:0] i_bus_daisy;
|
||||
output wire [0:0] o_bus_daisy;
|
||||
output wire [0:0] o_bus_active;
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* I/O registers
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
output reg [5:0] o_menu_height; // 0x28 bits 0-3 | 0x29 bits 0-1
|
||||
output reg [0:0] o_rom_mode; // 0x29 bit 3
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* address handling
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
`define MMIO_BITS 6
|
||||
reg [3:0] ioram_data[0:(2** `MMIO_BITS) - 1];
|
||||
|
||||
reg [3:0] last_cmd;
|
||||
reg [2:0] addr_pos_ctr;
|
||||
reg [19:0] local_pc;
|
||||
reg [19:0] local_dp;
|
||||
reg [0:0] pc_active;
|
||||
reg [0:0] dp_active;
|
||||
|
||||
reg [0:0] configured;
|
||||
reg [19:0] base_addr;
|
||||
|
||||
initial begin
|
||||
last_cmd = 4'b0;
|
||||
addr_pos_ctr = 3'b0;
|
||||
local_pc = 20'b0;
|
||||
local_dp = 20'b0;
|
||||
pc_active = 1'b0;
|
||||
dp_active = 1'b0;
|
||||
configured = 1'b0;
|
||||
base_addr = 20'b0;
|
||||
end
|
||||
|
||||
/*
|
||||
* testing for read
|
||||
*/
|
||||
|
||||
wire [0:0] do_pc_read = (last_cmd == `BUSCMD_PC_READ);
|
||||
wire [0:0] do_dp_read = (last_cmd == `BUSCMD_DP_READ);
|
||||
wire [0:0] do_read = do_pc_read || do_dp_read;
|
||||
|
||||
/*
|
||||
* testing for write
|
||||
*/
|
||||
|
||||
wire [0:0] do_pc_write = (last_cmd == `BUSCMD_PC_WRITE);
|
||||
wire [0:0] do_dp_write = (last_cmd == `BUSCMD_DP_WRITE);
|
||||
wire [0:0] do_write = do_pc_write || do_dp_write;
|
||||
|
||||
|
||||
/*
|
||||
* accessing the ioram
|
||||
*/
|
||||
|
||||
assign o_bus_daisy = configured;
|
||||
|
||||
wire [0:0] use_pc = do_pc_read || do_pc_write;
|
||||
wire [0:0] use_dp = do_dp_read || do_dp_write;
|
||||
|
||||
wire [19:0] above_addr = base_addr + (2 ** `MMIO_BITS);
|
||||
|
||||
wire [0:0] active = ((pc_active && use_pc) || (dp_active && use_dp)) && configured;
|
||||
assign o_bus_active = active;
|
||||
|
||||
wire [19:0] pointer = use_pc?local_pc:local_dp;
|
||||
wire [19:0] access_pointer = pointer - base_addr;
|
||||
|
||||
wire [`MMIO_BITS-1:0] address = access_pointer[`MMIO_BITS-1:0];
|
||||
|
||||
|
||||
wire [0:0] gen_active = i_clk_en && !i_debug_cycle && i_phases[0] && (do_read || do_write);
|
||||
wire [0:0] can_read = i_bus_clk_en && i_clk_en && i_bus_is_data && do_read && active;
|
||||
wire [0:0] can_write = i_bus_clk_en && i_clk_en && i_bus_is_data && do_write && active;
|
||||
|
||||
/*
|
||||
* reading and writing to I/O registers
|
||||
*/
|
||||
|
||||
/*
|
||||
* generate the active signals
|
||||
* these comparisons incur important delays
|
||||
*/
|
||||
always @(posedge i_clk) begin
|
||||
if (gen_active) begin
|
||||
// $display("MMIO-GX %0d: [%d] use_pc %b | use_dp %b | local_pc %5h | local_dp %5h | base %5h | above %5h | conf %b", i_phase, i_cycle_ctr,
|
||||
// use_pc, use_dp, local_pc, local_dp, base_addr, above_addr, configured);
|
||||
pc_active <= use_pc && (local_pc >= base_addr) && (local_pc < above_addr) && configured;
|
||||
dp_active <= use_dp && (local_dp >= base_addr) && (local_dp < above_addr) && configured;
|
||||
end
|
||||
|
||||
if (i_reset) begin
|
||||
pc_active <= 1'b0;
|
||||
dp_active <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (can_read)
|
||||
o_bus_nibble_out <= ioram_data[address];
|
||||
end
|
||||
|
||||
reg [0:0] junk_bit_0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (can_write) begin
|
||||
case (address)
|
||||
6'h28: o_menu_height[3:0] <= i_bus_nibble_in;
|
||||
6'h29: {o_rom_mode, junk_bit_0, o_menu_height[5:4]} <= i_bus_nibble_in;
|
||||
default:
|
||||
begin
|
||||
`ifdef SIM
|
||||
$display("MMIO-GX %0d: [%d] addr %h not handled", i_phase, i_cycle_ctr, pointer);
|
||||
`endif
|
||||
end
|
||||
endcase
|
||||
ioram_data[address] <= i_bus_nibble_in;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef SIM
|
||||
wire [3:0] imm_nibble = ioram_data[address];
|
||||
`endif
|
||||
|
||||
/*
|
||||
* general case
|
||||
*/
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_bus_clk_en && i_clk_en) begin
|
||||
if (i_bus_is_data) begin
|
||||
/* do things with the bits...*/
|
||||
case (last_cmd)
|
||||
`BUSCMD_PC_READ:
|
||||
begin
|
||||
// o_bus_nibble_out <= rom_data[local_pc[`ROMBITS-1:0]];
|
||||
local_pc <= local_pc + 1;
|
||||
end
|
||||
`BUSCMD_DP_READ:
|
||||
begin
|
||||
// o_bus_nibble_out <= rom_data[local_dp[`ROMBITS-1:0]];
|
||||
local_dp <= local_dp + 1;
|
||||
end
|
||||
`BUSCMD_PC_WRITE: local_pc <= local_pc + 1;
|
||||
`BUSCMD_DP_WRITE: local_dp <= local_dp + 1;
|
||||
`BUSCMD_LOAD_PC:
|
||||
begin
|
||||
local_pc[addr_pos_ctr*4+:4] <= i_bus_nibble_in;
|
||||
addr_pos_ctr <= addr_pos_ctr + 3'd1;
|
||||
end
|
||||
`BUSCMD_LOAD_DP:
|
||||
begin
|
||||
local_dp[addr_pos_ctr*4+:4] <= i_bus_nibble_in;
|
||||
addr_pos_ctr <= addr_pos_ctr + 3'd1;
|
||||
end
|
||||
`BUSCMD_CONFIGURE:
|
||||
if (i_bus_daisy && !configured) begin
|
||||
base_addr[addr_pos_ctr*4+:4] <= i_bus_nibble_in;
|
||||
addr_pos_ctr <= addr_pos_ctr + 3'd1;
|
||||
end
|
||||
default: begin end
|
||||
endcase
|
||||
|
||||
/* auto switch to pc read / dp read */
|
||||
if (addr_pos_ctr == 4) begin
|
||||
case (last_cmd)
|
||||
`BUSCMD_LOAD_PC: last_cmd <= `BUSCMD_PC_READ;
|
||||
`BUSCMD_LOAD_DP: last_cmd <= `BUSCMD_DP_READ;
|
||||
`BUSCMD_CONFIGURE:
|
||||
begin
|
||||
// set above_addr
|
||||
configured <= 1'b1;
|
||||
end
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
`ifdef SIM
|
||||
$write("MMIO-GX %0d: [%d] ", i_phase, i_cycle_ctr);
|
||||
case (last_cmd)
|
||||
`BUSCMD_PC_READ:
|
||||
begin
|
||||
$write("PC_READ ");
|
||||
if (configured)
|
||||
begin
|
||||
if (can_read) $write("<= mmio[%5h]: %h", local_pc, imm_nibble);
|
||||
else $write("inactive");
|
||||
end
|
||||
else $write("(ignore)");
|
||||
end
|
||||
`BUSCMD_DP_READ:
|
||||
begin
|
||||
$write("DP_READ ");
|
||||
if (configured)
|
||||
begin
|
||||
if (can_read) $write("<= mmio[%5h]: %h", local_dp, imm_nibble);
|
||||
else $write("(inactive)");
|
||||
end
|
||||
else $write("(ignore)");
|
||||
end
|
||||
`BUSCMD_DP_WRITE:
|
||||
begin
|
||||
$write("DP_WRITE ");
|
||||
if (configured)
|
||||
begin
|
||||
if (can_write) $write("mmio[%5h] <= %h", local_dp, i_bus_nibble_in);
|
||||
else $write("(inactive %h)", i_bus_nibble_in);
|
||||
end
|
||||
else $write("(ignore)");
|
||||
end
|
||||
`BUSCMD_LOAD_PC: $write("LOAD_PC - pc %5h, %h pos %0d", local_pc, i_bus_nibble_in, addr_pos_ctr);
|
||||
`BUSCMD_LOAD_DP: $write("LOAD_DP - dp %5h, %h pos %0d", local_dp, i_bus_nibble_in, addr_pos_ctr);
|
||||
`BUSCMD_CONFIGURE:
|
||||
begin
|
||||
if (!configured) $write("CONFIGURE - base_addr %5h, %h pos %0d", base_addr, i_bus_nibble_in, addr_pos_ctr);
|
||||
else $write("CONFIGURE - already done, ignore");
|
||||
end
|
||||
`BUSCMD_RESET: $write("RESET");
|
||||
default: $write("last_command %h nibble %h - UNHANDLED", last_cmd, i_bus_nibble_in);
|
||||
endcase
|
||||
if (addr_pos_ctr == 4) begin
|
||||
case (last_cmd)
|
||||
`BUSCMD_LOAD_PC: $write(" auto switch to PC_READ");
|
||||
`BUSCMD_LOAD_DP: $write(" auto switch to DP_READ");
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
$write("\n");
|
||||
`endif
|
||||
end else begin
|
||||
last_cmd <= i_bus_nibble_in;
|
||||
|
||||
if ((i_bus_nibble_in == `BUSCMD_LOAD_PC) || (i_bus_nibble_in == `BUSCMD_LOAD_DP))
|
||||
addr_pos_ctr <= 0;
|
||||
|
||||
if (i_bus_nibble_in == `BUSCMD_CONFIGURE)
|
||||
addr_pos_ctr <= 3'd0;
|
||||
|
||||
if (i_bus_nibble_in == `BUSCMD_RESET)
|
||||
begin
|
||||
base_addr <= 20'b0;
|
||||
configured <= 1'b0;
|
||||
end
|
||||
|
||||
`ifdef SIM
|
||||
$write("MMIO-GX %0d: [%d] ", i_phase, i_cycle_ctr);
|
||||
case (i_bus_nibble_in)
|
||||
`BUSCMD_PC_READ: $write("PC_READ");
|
||||
`BUSCMD_DP_READ: $write("DP_READ");
|
||||
`BUSCMD_DP_WRITE: $write("DP_WRITE");
|
||||
`BUSCMD_LOAD_PC: $write("LOAD_PC");
|
||||
`BUSCMD_LOAD_DP: $write("LOAD_DP");
|
||||
`BUSCMD_CONFIGURE: $write("CONFIGURE");
|
||||
`BUSCMD_RESET: $write("RESET base_addr to %5h and unconfigure", 20'h0);
|
||||
default: begin end
|
||||
endcase
|
||||
$write("\n");
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
if (i_reset) begin
|
||||
last_cmd <= 4'b0;
|
||||
addr_pos_ctr <= 3'b0;
|
||||
local_pc <= 20'b0;
|
||||
local_dp <= 20'b0;
|
||||
configured <= 1'b0;
|
||||
base_addr <= 20'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Verilator lint_off UNUSED
|
||||
wire [(20 -`MMIO_BITS):0] unused;
|
||||
assign unused = { junk_bit_0, access_pointer[19:`MMIO_BITS] };
|
||||
// Verilator lint_on UNUSED
|
||||
|
||||
endmodule
|
|
@ -52,6 +52,8 @@ module saturn_inst_decoder (
|
|||
o_jump_length,
|
||||
o_block_0x,
|
||||
|
||||
o_mem_pointer,
|
||||
|
||||
o_instr_type,
|
||||
o_push_pc,
|
||||
o_instr_decoded,
|
||||
|
@ -92,6 +94,8 @@ output reg [2:0] o_jump_length;
|
|||
output wire [0:0] o_block_0x;
|
||||
assign o_block_0x = block_0x;
|
||||
|
||||
output reg [0:0] o_mem_pointer;
|
||||
|
||||
output reg [3:0] o_instr_type;
|
||||
output reg [0:0] o_push_pc;
|
||||
/* instruction is fully decoded */
|
||||
|
@ -134,6 +138,7 @@ reg [0:0] decode_started;
|
|||
|
||||
reg [0:0] block_0x;
|
||||
reg [0:0] block_1x;
|
||||
reg [0:0] block_14x;
|
||||
reg [0:0] block_2x;
|
||||
reg [0:0] block_3x;
|
||||
reg [0:0] block_8x;
|
||||
|
@ -186,6 +191,7 @@ initial begin
|
|||
|
||||
block_0x = 1'b0;
|
||||
block_1x = 1'b0;
|
||||
block_14x = 1'b0;
|
||||
block_2x = 1'b0;
|
||||
block_3x = 1'b0;
|
||||
block_8x = 1'b0;
|
||||
|
@ -319,6 +325,7 @@ always @(posedge i_clk) begin
|
|||
|
||||
if (block_1x) begin
|
||||
case (i_nibble)
|
||||
4'h4: block_14x <= 1'b1;
|
||||
4'hB:
|
||||
begin
|
||||
$display("DECODER %0d: [%d] D)=(5)", i_phase, i_cycle_ctr, i_nibble);
|
||||
|
@ -339,6 +346,22 @@ always @(posedge i_clk) begin
|
|||
block_1x <= 1'b0;
|
||||
end
|
||||
|
||||
if (block_14x) begin
|
||||
$display("DECODER %0d: [%d] block_14x %h", i_phase, i_cycle_ctr, i_nibble);
|
||||
o_mem_pointer <= i_nibble[0];
|
||||
o_instr_type <= i_nibble[1]?`INSTR_TYPE_MEM_READ:`INSTR_TYPE_MEM_WRITE;
|
||||
o_alu_reg_dest <= i_nibble[2]?`ALU_REG_C:`ALU_REG_A;
|
||||
o_alu_reg_src_1 <= i_nibble[2]?`ALU_REG_C:`ALU_REG_A;
|
||||
o_alu_reg_src_2 <= `ALU_REG_NONE;
|
||||
o_alu_field <= i_nibble[3]?`FT_FIELD_B:`FT_FIELD_A;
|
||||
o_alu_ptr_begin <= 4'h0;
|
||||
o_alu_ptr_end <= i_nibble[3]?1:4;
|
||||
o_instr_execute <= 1'b1;
|
||||
o_instr_decoded <= 1'b1;
|
||||
decode_started <= 1'b0;
|
||||
block_14x <= 1'b0;
|
||||
end
|
||||
|
||||
if (block_2x) begin
|
||||
o_alu_reg_dest <= `ALU_REG_P;
|
||||
o_alu_reg_src_1 <= `ALU_REG_IMM;
|
||||
|
@ -685,6 +708,7 @@ always @(posedge i_clk) begin
|
|||
|
||||
block_0x <= 1'b0;
|
||||
block_1x <= 1'b0;
|
||||
block_14x <= 1'b0;
|
||||
block_2x <= 1'b0;
|
||||
block_3x <= 1'b0;
|
||||
block_8x <= 1'b0;
|
||||
|
|
|
@ -95,12 +95,14 @@ reg [0:0] jump_exec;
|
|||
reg [2:0] jump_counter;
|
||||
reg [19:0] jump_base;
|
||||
reg [19:0] jump_offset;
|
||||
reg [19:0] jump_rel_addr;
|
||||
|
||||
wire [0:0] jump_rel2 = i_jump_instr && (i_jump_length == 3'd1);
|
||||
wire [0:0] jump_rel3 = i_jump_instr && (i_jump_length == 3'd2);
|
||||
wire [0:0] jump_rel4 = i_jump_instr && (i_jump_length == 3'd3);
|
||||
wire [0:0] jump_abs5 = i_jump_instr && (i_jump_length == 3'd4);
|
||||
wire [0:0] jump_relative = jump_rel2 || jump_rel3 || jump_rel4;
|
||||
wire [0:0] is_rtn = i_phases[2] && i_block_0x && !i_nibble[3] && !i_nibble[2];
|
||||
|
||||
reg [19:0] jump_next_offset;
|
||||
|
||||
|
@ -120,6 +122,10 @@ reg [19:0] reg_PC;
|
|||
reg [2:0] reg_rstk_ptr;
|
||||
reg [19:0] reg_RSTK[0:7];
|
||||
|
||||
reg [2:0] rstk_ptr_to_push_at;
|
||||
reg [19:0] addr_to_return_to;
|
||||
reg [2:0] rstk_ptr_after_pop;
|
||||
|
||||
assign o_current_pc = reg_PC;
|
||||
|
||||
initial begin
|
||||
|
@ -131,6 +137,11 @@ initial begin
|
|||
jump_counter = 3'd0;
|
||||
reg_PC = 20'h00000;
|
||||
reg_rstk_ptr = 3'd7;
|
||||
|
||||
addr_to_return_to = 20'b0;
|
||||
rstk_ptr_after_pop = 3'd0;
|
||||
rstk_ptr_to_push_at = 3'd0;
|
||||
jump_rel_addr = 20'b0;
|
||||
end
|
||||
|
||||
/*
|
||||
|
@ -184,10 +195,13 @@ always @(posedge i_clk) begin
|
|||
* address of nibble after the offset when gosub
|
||||
*/
|
||||
if (i_phases[3] && do_jump_instr && !jump_decode) begin
|
||||
`ifdef SIM
|
||||
$display("PC_RSTK %0d: [%d] start decode jump %0d | jump_base %5h", i_phase, i_cycle_ctr, i_jump_length, reg_PC);
|
||||
`endif
|
||||
jump_counter <= 3'd0;
|
||||
jump_base <= reg_PC;
|
||||
jump_decode <= 1'b1;
|
||||
rstk_ptr_to_push_at <= (reg_rstk_ptr + 3'o1) & 3'o7;
|
||||
end
|
||||
|
||||
/* one step of the calculation (one nibble of data came in) */
|
||||
|
@ -209,28 +223,24 @@ always @(posedge i_clk) begin
|
|||
$write("\n");
|
||||
end
|
||||
end
|
||||
|
||||
// /* all done, apply to PC and RSTK */
|
||||
// if (i_phases[3] && do_jump_instr && jump_exec) begin
|
||||
// $write("PC_RSTK %0d: [%d] execute jump %0d", i_phase, i_cycle_ctr, i_jump_length);
|
||||
// if (i_push_pc) begin
|
||||
// $write(" ( push %5h => RSTK[%0d])", reg_PC, reg_rstk_ptr + 3'd1);
|
||||
// reg_RSTK[(reg_rstk_ptr + 3'o1)&3'o7] <= reg_PC;
|
||||
// reg_rstk_ptr <= reg_rstk_ptr + 3'd1;
|
||||
// end
|
||||
// $display("");
|
||||
// reg_PC <= jump_relative ? jump_offset + jump_base : jump_offset;
|
||||
// jump_exec <= 1'b0;
|
||||
// o_reload_pc <= 1'b0;
|
||||
// end
|
||||
end
|
||||
|
||||
/*
|
||||
* RTN instruction
|
||||
*/
|
||||
|
||||
if (i_clk_en && !i_bus_busy && !i_exec_unit_busy) begin
|
||||
/* this happens at the same time in the decoder */
|
||||
if (i_phases[2] && i_block_0x && (i_nibble[3:2] == 2'b00)) begin
|
||||
if (i_phases[1]) begin
|
||||
addr_to_return_to <= reg_RSTK[reg_rstk_ptr];
|
||||
rstk_ptr_after_pop <= (reg_rstk_ptr - 3'o1) & 3'o7;
|
||||
end
|
||||
|
||||
if (is_rtn) begin
|
||||
/* this is an RTN */
|
||||
reg_PC <= addr_to_return_to;
|
||||
reg_RSTK[reg_rstk_ptr] <= 20'h00000;
|
||||
reg_rstk_ptr <= rstk_ptr_after_pop;
|
||||
`ifdef SIM
|
||||
$write("PC_RSTK %0d: [%d] RTN", i_phase, i_cycle_ctr);
|
||||
case (i_nibble)
|
||||
4'h0: $display("SXM");
|
||||
|
@ -238,20 +248,14 @@ always @(posedge i_clk) begin
|
|||
4'h3: $display("CC");
|
||||
default: begin end
|
||||
endcase
|
||||
// o_reload_pc <= 1'b1;
|
||||
$display("PC_RSTK %0d: [%d] execute RTN back to %5h", i_phase, i_cycle_ctr, addr_to_return_to);
|
||||
`endif
|
||||
end
|
||||
|
||||
if (i_phases[3] && i_rtn_instr) begin
|
||||
$display("PC_RSTK %0d: [%d] execute RTN back to %5h", i_phase, i_cycle_ctr, reg_RSTK[reg_rstk_ptr]);
|
||||
reg_PC <= reg_RSTK[reg_rstk_ptr];
|
||||
reg_RSTK[reg_rstk_ptr] <= 20'h00000;
|
||||
reg_rstk_ptr <= (reg_rstk_ptr - 3'd1) & 3'd7;
|
||||
/* o_reload_pc was set in advance above */
|
||||
// o_reload_pc <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
// if (i_phases[0] && i_clk_en) begin
|
||||
// $write("RSTK : ptr %0d | ", reg_rstk_ptr);
|
||||
// for (tmp_ctr = 4'd0; tmp_ctr < 4'd8; tmp_ctr = tmp_ctr + 4'd1)
|
||||
|
|
Loading…
Reference in a new issue