use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
+library unisim;
+use unisim.vcomponents.all;
+
library utility;
library nexys2_lib;
library ps2;
signal ints: std_logic_vector(15 downto 0);
-- Debug signals
+ signal jtag_reset: std_logic;
+ signal jtag_capture: std_logic;
+ signal jtag_shift: std_logic;
+ signal jtag_update: std_logic;
+ signal jtag_tdi: std_logic;
+ signal jtag_drck1: std_logic;
+ signal jtag_sel1: std_logic;
+ signal jtag_tdo1: std_logic;
+ signal jtag_drck2: std_logic;
+ signal jtag_sel2: std_logic;
+ signal jtag_tdo2: std_logic;
+
+ signal debug_to_host: std_logic_vector(137 downto 0);
+ signal debug_from_host: std_logic_vector(137 downto 0);
+
+ signal deb_halt: std_logic;
signal deb_wait: std_logic;
signal deb_pc: std_logic_vector(31 downto 0);
signal deb_ins: std_logic_vector(7 downto 0);
signal deb_t: std_logic_vector(31 downto 0);
signal deb_n: std_logic_vector(31 downto 0);
signal deb_r: std_logic_vector(31 downto 0);
- signal debug_i: std_logic_vector(63 downto 0);
- signal debug_o: std_logic_vector(63 downto 0);
begin
+ ----------------------------------------------------------------------------
+ -- JTAG debugging
+
+ e_jtag: bscan_spartan3
+ port map (
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+
+ tdi => jtag_tdi,
+
+ drck1 => jtag_drck1,
+ sel1 => jtag_sel1,
+ tdo1 => jtag_tdo1,
+
+ drck2 => jtag_drck2,
+ sel2 => jtag_sel2,
+ tdo2 => jtag_tdo2
+ );
+
+
+ -- Single stepping and CPU state reading
+ e_user1: entity utility.jtag_reg
+ generic map (N => 138)
+ port map (
+ clk_i => d_clk,
+ upd_o => open,
+ dat_i => debug_to_host,
+ dat_o => debug_from_host,
+
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+ sel => jtag_sel1,
+ drck => jtag_drck1,
+ tdi => jtag_tdi,
+ tdo => jtag_tdo1
+ );
+
+ deb_halt <= debug_from_host(137);
+ deb_wait <= debug_from_host(136);
+ debug_to_host <= deb_halt & deb_wait & deb_pc & deb_ins & deb_t & deb_n & deb_r;
+
+
+ -- Only here to not break the JTAG chain when USER2 is selected
+ e_user2: entity utility.jtag_reg
+ generic map (N => 1)
+ port map (
+ clk_i => d_clk,
+ upd_o => open,
+ dat_i => (others => '0'),
+ dat_o => open,
+
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+ sel => jtag_sel2,
+ drck => jtag_drck2,
+ tdi => jtag_tdi,
+ tdo => jtag_tdo2
+ );
+
+
+ ----------------------------------------------------------------------------
+
e_cpu: entity work.cpu
port map (
- rst_i => d_rst,
- clk_i => d_clk,
+ rst_i => d_rst,
+ clk_i => d_clk,
- cyc_o => cyc,
- stb_o => stb,
- we_o => we,
- ack_i => ack,
- adr_o => adr,
- dat_o => dat_mosi,
- dat_i => dat_miso,
+ cyc_o => cyc,
+ stb_o => stb,
+ we_o => we,
+ ack_i => ack,
+ adr_o => adr,
+ dat_o => dat_mosi,
+ dat_i => dat_miso,
- int_i => int_cpu,
- vec_i => int_vec,
+ int_i => int_cpu,
+ vec_i => int_vec,
- halt_i => sw(7),
+ halt_i => deb_halt,
step_i => deb_wait,
- pc_o => open,--deb_pc,
- ins_o => open,--deb_ins,
- t_o => open,--deb_t,
- n_o => open,--deb_n,
- r_o => open--deb_r
+ pc_o => deb_pc,
+ ins_o => deb_ins,
+ t_o => deb_t,
+ n_o => deb_n,
+ r_o => deb_r
);
- deb_wait <= debug_i(0);
- debug_o <= (others => '0');
- --with debug_i(2 downto 1) select debug_o <=
- -- x"000000" & deb_ins & deb_pc when "00",
- -- deb_n & deb_t when "01",
- -- x"00000000" & deb_r when others;
int_vec(7 downto 4) <= (others => '0');
ints(0) <= '0';
-- Signals to the internal device
d_rst_o => d_rst,
d_flags_o => host_flags,
- debug_i => debug_o,
- debug_o => debug_i,
+ debug_i => (others => '0'),
+ debug_o => open,
-- Internal access to control registers
d_cyc_i => host_cyc,
}
if (final)
{
+ // Return to IDLE
EC_FALSE(DjtgClockTck(hif, true, false, 1, false));
EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
}
// -----------------------------------------------------------------------------
+bool cpu_state(HIF hif)
+{
+ assert(hif != hifInvalid);
+
+ uint64_t halt, wait, pc, ins, t, n, r;
+ const char *mnem;
+
+ // Select IR
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Select BYPASS in ROM
+ field_write(8, 0xff);
+ EC_FALSE(tap_reg_shift(hif, 8, false));
+
+ // Select USER1 in FPGA
+ field_write(6, 0x02);
+ EC_FALSE(tap_reg_shift(hif, 6, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select DR
+ EC_FALSE(tap_idle_to_dr(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Shift out ROM's BYPASS
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+
+ // FPGA.USER1.R
+ r = field_read(32);
+ EC_FALSE(tap_reg_shift(hif, 32, false));
+
+ // FPGA.USER1.N
+ n = field_read(32);
+ EC_FALSE(tap_reg_shift(hif, 32, false));
+
+ // FPGA.USER1.T
+ t = field_read(32);
+ EC_FALSE(tap_reg_shift(hif, 32, false));
+
+ // FPGA.USER1.INS
+ ins = field_read(8);
+ EC_FALSE(tap_reg_shift(hif, 8, false));
+
+ // FPGA.USER1.PC
+ pc = field_read(32);
+ EC_FALSE(tap_reg_shift(hif, 32, false));
+
+ // FPGA.USER1.WAIT
+ wait = field_read(1);
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+
+ // FPGA.USER1.HALT
+ halt = field_read(1);
+ EC_FALSE(tap_reg_shift(hif, 1, true));
+
+ switch (ins)
+ {
+ case 0x00: mnem = "NOP"; break;
+ case 0x01: mnem = "#8"; break;
+ case 0x02: mnem = "#32"; break;
+ case 0x03: mnem = "@8"; break;
+ case 0x04: mnem = "@32"; break;
+ case 0x05: mnem = "!8"; break;
+ case 0x06: mnem = "!32"; break;
+ case 0x07: mnem = "R@"; break;
+ case 0x08: mnem = ">R"; break;
+ case 0x09: mnem = "R>"; break;
+ case 0x0a: mnem = "CALL"; break;
+ case 0x0b: mnem = ";"; break;
+ case 0x0c: mnem = "JMP"; break;
+ case 0x0d: mnem = "JZ"; break;
+ case 0x0e: mnem = "JN"; break;
+ case 0x0f: mnem = "JP"; break;
+ case 0x10: mnem = "+"; break;
+ case 0x11: mnem = "-"; break;
+ case 0x12: mnem = "&"; break;
+ case 0x13: mnem = "|"; break;
+ case 0x14: mnem = "^"; break;
+ case 0x15: mnem = "~"; break;
+ case 0x16: mnem = "DUP"; break;
+ case 0x17: mnem = "DROP"; break;
+ case 0x18: mnem = "SWAP"; break;
+ case 0x19: mnem = "IEN"; break;
+ case 0x1a: mnem = "IDIS"; break;
+ case 0x1b: mnem = "LSR"; break;
+ case 0x1c: mnem = "ASR"; break;
+ case 0x1d: mnem = "SHL"; break;
+ default: mnem = "???"; break;
+ }
+ printf("halt:%" PRIu64 " "
+ "wait:%" PRIu64 " "
+ "PC:0x%08" PRIx64 " "
+ "INS:0x%02" PRIx64 " "
+ "T:0x%08" PRIx64 " "
+ "N:0x%08" PRIx64 " "
+ "R:0x%08" PRIx64 " "
+ "%s\n",
+ halt, wait, pc, ins, t, n, r, mnem);
+
+ EC_NE(field_read(64), SENTINEL);
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool cpu_halt(HIF hif)
+{
+ assert(hif != hifInvalid);
+
+ // Select IR
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Select BYPASS in ROM and USER1 in FPGA
+ field_write(14, 0x02ff);
+ EC_FALSE(tap_reg_shift(hif, 14, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select DR
+ EC_FALSE(tap_idle_to_dr(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Shift out ROM's BYPASS and all of USER1 up to MSB (HALT bit)
+ EC_FALSE(tap_reg_shift(hif, 137, false));
+
+ // FPGA.USER1.WAIT
+ field_write(1, 0);
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+
+ // FPGA.USER1.HALT
+ field_write(1, 1);
+ EC_FALSE(tap_reg_shift(hif, 1, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool cpu_run(HIF hif)
+{
+ assert(hif != hifInvalid);
+
+ // Select IR
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Select BYPASS in ROM and USER1 in FPGA
+ field_write(14, 0x02ff);
+ EC_FALSE(tap_reg_shift(hif, 14, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select DR
+ EC_FALSE(tap_idle_to_dr(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Shift out ROM's BYPASS and all of USER1 up to MSB (HALT bit)
+ EC_FALSE(tap_reg_shift(hif, 138, false));
+
+ // FPGA.USER1.HALT
+ field_write(1, 0);
+ EC_FALSE(tap_reg_shift(hif, 1, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool cpu_step(HIF hif)
+{
+ assert(hif != hifInvalid);
+
+ // Select IR
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Select BYPASS in ROM and USER1 in FPGA
+ field_write(14, 0x02ff);
+ EC_FALSE(tap_reg_shift(hif, 14, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select DR
+ EC_FALSE(tap_idle_to_dr(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Shift out ROM's BYPASS and all of USER1 up to MSB (HALT bit)
+ EC_FALSE(tap_reg_shift(hif, 137, false));
+
+ // FPGA.USER1.WAIT
+ field_write(1, 1);
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+
+ // FPGA.USER1.HALT
+ field_write(1, 1);
+ EC_FALSE(tap_reg_shift(hif, 1, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select DR again
+ EC_FALSE(tap_idle_to_dr(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Shift out ROM's BYPASS and all of USER1 up to MSB (HALT bit)
+ EC_FALSE(tap_reg_shift(hif, 137, false));
+
+ // FPGA.USER1.WAIT
+ field_write(1, 0);
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+
+ // FPGA.USER1.HALT
+ field_write(1, 1);
+ EC_FALSE(tap_reg_shift(hif, 1, true));
+ EC_NE(field_read(64), SENTINEL);
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+// -----------------------------------------------------------------------------
+
+
int main(int argc, char **argv)
{
(void)argc;
// -------------------------------------------------------------
// Perform a scan to see what's on the chain
- EC_FALSE(scan(hif));
+ //EC_FALSE(scan(hif));
printf("\n\n");
- // Select IR
- EC_FALSE(tap_reset(hif));
- EC_FALSE(tap_reset_to_idle(hif));
- EC_FALSE(tap_idle_to_ir(hif));
-
- // Insert sentinel
- field_write(64, SENTINEL);
- EC_FALSE(tap_reg_shift(hif, 64, false));
-
- // Write first instruction
- field_write(8, 0xff);
- EC_FALSE(tap_reg_shift(hif, 7, false));
-
- // Write second instruction
- field_write(6, 0x03);
- EC_FALSE(tap_reg_shift(hif, 6, true));
-
- // Select DR
- EC_FALSE(tap_idle_to_dr(hif));
- field_write(64, SENTINEL);
- EC_FALSE(tap_reg_shift(hif, 64, false)); // Shift out sentinel
- EC_FALSE(tap_reg_shift(hif, 1, false)); // Shift out ROM BYPASS
- printf("USER1: 0x%1" PRIx64 "\n", field_read(4)); // Read USER1
- field_write(4, 0x3); // Write USER1
- EC_FALSE(tap_reg_shift(hif, 4, true)); // Shift out USER1
- EC_NE(field_read(64), SENTINEL); // Verify sentinel
+ EC_FALSE(cpu_halt(hif));
+ EC_FALSE(cpu_state(hif));
+ for (size_t i = 0; i < 20; i++)
+ {
+ EC_FALSE(cpu_step(hif));
+ EC_FALSE(cpu_state(hif));
+ }
// -------------------------------------------------------------
// Close JTAG session