jtag: Apply Martin Strubel JTAG implementation for ZPU
[zpu.git] / zpu / hdl / zealot / testbenches / hwdbg_small1_tb.vhdl
blob1685634b95598581ef5ddd9a7e6d779838c84ef0
1 ------------------------------------------------------------------------------
2 ----                                                                      ----
3 ----  Testbench for the ZPU Small connection to the FPGA                  ----
4 ----                                                                      ----
5 ----  http://www.opencores.org/                                           ----
6 ----                                                                      ----
7 ----  Description:                                                        ----
8 ----  This is a testbench to simulate the ZPU_Small1 core as used in the  ----
9 ----  *_small1.vhdl                                                       ----
10 ----                                                                      ----
11 ----  ...plus the JTAG debugger proof of concept for the Small core.
12 ----
13 ----  To Do:                                                              ----
14 ----  -                                                                   ----
15 ----                                                                      ----
16 ----  Author:                                                             ----
17 ----    - Salvador E. Tropea, salvador inti.gob.ar                        ----
18 ----    Modifications for core debug signal testing
19 ----    - Martin Strubel <hackfin@section5.ch>
20 ----                                                                      ----
21 ------------------------------------------------------------------------------
22 ----                                                                      ----
23 ---- Copyright (c) 2008 Salvador E. Tropea <salvador inti.gob.ar>         ----
24 ---- Copyright (c) 2008 Instituto Nacional de TecnologĂ­a Industrial       ----
25 ----                                                                      ----
26 ---- Distributed under the BSD license                                    ----
27 ----                                                                      ----
28 ------------------------------------------------------------------------------
29 ----                                                                      ----
30 ---- Design unit:      HWDbg_Small1_TB(Behave) (Entity and architecture)        ----
31 ---- File name:        small1_tb.vhdl                                     ----
32 ---- Note:             None                                               ----
33 ---- Limitations:      None known                                         ----
34 ---- Errors:           None known                                         ----
35 ---- Library:          work                                               ----
36 ---- Dependencies:     IEEE.std_logic_1164                                ----
37 ----                   IEEE.numeric_std                                   ----
38 ----                   zpu.zpupkg                                         ----
39 ----                   zpu.txt_util                                       ----
40 ----                   work.zpu_memory                                    ----
41 ---- Target FPGA:      Spartan 3 (XC3S1500-4-FG456)                       ----
42 ---- Language:         VHDL                                               ----
43 ---- Wishbone:         No                                                 ----
44 ---- Synthesis tools:  N/A                                                ----
45 ---- Simulation tools: Isim
46 ---- Text editor:      gvim
47 ----                                                                      ----
48 ------------------------------------------------------------------------------
50 library IEEE;
51 use IEEE.std_logic_1164.all;
52 use IEEE.numeric_std.all;
54 library zpu;
55 use zpu.zpupkg.all;
56 use zpu.txt_util.all;
58 library work;
59 use work.zpu_memory.all;
61 entity HWDbg_Small1_TB is
62 end entity HWDbg_Small1_TB;
64 architecture Behave of HWDbg_Small1_TB is
65    constant WORD_SIZE  : natural:=32; -- 32 bits data path
66    constant ADDR_W     : natural:=18;  -- 18 bits address space=256 kB, 128 kB I/O
67    constant BRAM_W     : natural:=14; -- 15 bits RAM space=32 kB
68    constant D_CARE_VAL : std_logic:='0'; -- Fill value
69    constant CLK_FREQ   : positive:=50; -- 50 MHz clock
70    constant CLK_S_PER  : time:=1 us/(2.0*real(CLK_FREQ)); -- Clock semi period
71    constant BRATE      : positive:=115200;
73    -- Opcode to leave emulation:
74    constant OPCODE_LEAVE_EMULATION  : unsigned(3 downto 0) := OPCODE_BREAK;
76    component tap
77     generic (EMUDAT_SIZE : natural;
78       EMUIR_SIZE : natural);
79     port (
80       emu : out  std_logic;
81       tck : in  std_logic;
82       trst : in  std_logic;
83       tms : in  std_logic;
84       tdi : in  std_logic;
85       tdo : out  std_logic;
86       emuexec     : out std_logic; -- Execute opcode on rising edge
87       emurequest  : out std_logic; -- Emulation request to core
88       emuack      : in std_logic; -- Core has acknowledged EMULATION request
89       emurdy      : in std_logic; -- Core ready to execute next instruction
90       -- Program Counter without going to emulation.
91       dbgpc       : in std_logic_vector(32-1 downto 0);
93       emudata_i   : in std_logic_vector(32-1 downto 0);
94       emudata_o   : out std_logic_vector(32-1 downto 0);
95       emudat_wr   : in std_logic;
96       emudat_rd   : in std_logic;
97       emuir       : out std_logic_vector(OPCODE_W-1 downto 0)
98       );
99     end component;
101    component ZPU_Small1 is
102       generic(
103          WORD_SIZE  : natural:=32;  -- 32 bits data path
104          D_CARE_VAL : std_logic:='0'; -- Fill value
105          CLK_FREQ   : positive:=50; -- 50 MHz clock
106          BRATE      : positive:=115200; -- RS232 baudrate
107          ADDR_W     : natural:=16;  -- 16 bits address space=64 kB, 32 kB I/O
108          BRAM_W     : natural:=15); -- 15 bits RAM space=32 kB
109       port(
110          clk_i      : in  std_logic;  -- CPU clock
111          rst_i      : in  std_logic;  -- Reset
113          -- Emulation pins:
114          emureq_i     : in std_logic;
115          emuexec_i    : in std_logic;
116          emuack_o     : out std_logic;
117          emurdy_o     : out std_logic;
118          emuir        : in std_logic_vector(OPCODE_W-1 downto 0);
120          break_o    : out std_logic;  -- Break executed
121          dbg_o      : out zpu_dbgo_t; -- Debug info
122          rs232_tx_o : out std_logic;  -- UART Tx
123          rs232_rx_i : in  std_logic); -- UART Rx
124    end component ZPU_Small1;
126    signal clk          : std_logic;
127    signal reset        : std_logic:='1';
129    signal emureq       : std_logic := '0';
130    signal emuexec      : std_logic := '0';
131    signal emuack       : std_logic;
132    signal emurdy       : std_logic := '0';
133    signal emuir        : std_logic_vector(OPCODE_W-1 downto 0);
135    signal break        : std_logic := '0';
136    signal dbg          : zpu_dbgo_t; -- Debug info
137    signal rs232_tx     : std_logic;
138    signal rs232_rx     : std_logic;
141    -- Auxiliary signals
142    signal terminate       : std_logic := '0';
143    signal mismatch       : std_logic := '0';
144    signal finish       : std_logic;
145    signal save_sp      : unsigned(31 downto 0);
147 begin
149    zpu : ZPU_Small1
150       generic map(
151          WORD_SIZE => WORD_SIZE, D_CARE_VAL => D_CARE_VAL,
152          CLK_FREQ => CLK_FREQ, BRATE => BRATE, ADDR_W => ADDR_W,
153          BRAM_W => BRAM_W)
154       port map(
155          clk_i => clk, rst_i => reset, rs232_tx_o => rs232_tx,
156          emureq_i => emureq, emuexec_i => emuexec,
157          emuack_o => emuack, emurdy_o => emurdy,
158          emuir => emuir,
159          rs232_rx_i => rs232_rx, break_o => break, dbg_o => dbg);
161    trace_mod : Trace
162       generic map(
163          ADDR_W => ADDR_W, WORD_SIZE => WORD_SIZE,
164          LOG_FILE => "dbg_small1_trace.log")
165       port map(
166          clk_i => clk, dbg_i => dbg, emu_i => emuack, stop_i => '0',
167             busy_i => '0');
169    do_clock:
170    process
171    begin
172       clk <= '0';
173       wait for CLK_S_PER;
174       clk <= '1';
175       wait for CLK_S_PER;
176       if finish='1' then
177          print("* Finish asserted, end of test");
178          if terminate = '1' then
179             print("* Reason: Terminate");
180          end if;
181          if mismatch = '1' then
182             print("* Reason: Mismatch");
183          end if;
184          if break = '1' then
185             print("* Reason: Breakpoint");
186          end if;
187          wait;
188       end if;
189    end process do_clock;
191    do_reset:
192    process
193    begin
194       wait until rising_edge(clk);
195       reset <= '0';
196    end process do_reset;
198 do_emulation:
199    process
200    procedure execute_opcode(
201       code: unsigned(OPCODE_W-1 downto 0)
202      )
203    is begin
204       emuir <= std_logic_vector(code);
206       wait until rising_edge(clk);
207       emuexec <= '1';
208       wait until rising_edge(clk);
209       emuexec <= '0';
210       wait for 200ns;
211    end execute_opcode;
213    procedure push_imm32(
214      imm: unsigned(31 downto 0)
215      )
216    is begin
217       execute_opcode(OPCODE_IM & "000" & imm(31 downto 28));
218       execute_opcode(OPCODE_IM & imm(27 downto 21));
219       execute_opcode(OPCODE_IM & imm(20 downto 14));
220       execute_opcode(OPCODE_IM & imm(13 downto 7));
221       execute_opcode(OPCODE_IM & imm(6 downto 0));
222    end push_imm32;
224    procedure getsp
225    is begin
226       execute_opcode(OPCODE_SHORT & OPCODE_PUSHSP); -- Restore context
227       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
228       print("sp: " & hstr(dbg.stk_a));
229       -- execute_opcode(OPCODE_LOADSP & '1' & x"1"); -- Restore context
230       execute_opcode(OPCODE_SHORT & OPCODE_POPSP); -- Restore context
231    end getsp;
233    procedure mem_read(
234      addr: unsigned(31 downto 0)
235    )
236    is begin
237       execute_opcode(OPCODE_SHORT & OPCODE_PUSHSP); -- Restore context
238       -- Save current SP for for reference. Note the dbg.sp is not yet
239       -- updated to the above command.
240       save_sp <= dbg.sp;
241       push_imm32(addr);
242       execute_opcode(OPCODE_SHORT & OPCODE_LOAD); -- Load indirect
243       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
244       print("value: " & hstr(dbg.stk_a));
245       execute_opcode(OPCODE_LOADSP & '1' & x"1"); -- Restore context
246       execute_opcode(OPCODE_SHORT & OPCODE_POPSP); -- Restore context
247       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
249       if (dbg.sp /= save_sp) then
250          mismatch <= '1';
251          print("* ERROR: Stack pointers don't match");
252          print("sp: " & hstr(dbg.sp) & "  SAVE_SP: " & hstr(save_sp));
253       end if;
256    end mem_read;
258    begin
259       wait for 400ns;
260       emuir <= "00001011"; -- NOP
261       -- emureq <= '1';
263       -- It is IMPORTANT to wait after an emu request
264       wait until emurdy = '1' and break ='1';
265       wait for 100ns;
267 ----------------------------------------------------------------------------
269       -- Single stepping:
270       emureq <= '1';
271       wait for 100ns;
273       for i in 0 to 200 loop
274          getsp;
275          execute_opcode(OPCODE_SHORT & OPCODE_LEAVE_EMULATION);
276       end loop;
279 ----------------------------------------------------------------------------
280       -- Save context here:
282       execute_opcode(OPCODE_SHORT & OPCODE_PUSHSP); -- Restore context
283       -- Save current SP for for reference. Note the dbg.sp is not yet
284       -- updated to the above command.
285       save_sp <= dbg.sp;
287       -- Now do your stuff and count the pushes, including the above
289       -- MEMORY READ {
291       push_imm32(x"000008d8");
292       
293       -- execute_opcode(OPCODE_LOADSP & '1' & x"0");
294       execute_opcode(OPCODE_SHORT & OPCODE_LOAD); -- Load indirect
296       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
297       print("value: " & hstr(dbg.stk_a));
299       -- Now we should see the data from the address above in
300       -- dbg.stk_a
301       -- }
304       -- Restore old stack:
306       -- RESTORE
307       -- execute_opcode(OPCODE_SHORT & OPCODE_PUSHSP);
308       -- Fix up stack:
309       -- execute_opcode(OPCODE_IM & "000" & x"8");
310       -- execute_opcode(OPCODE_SHORT & OPCODE_ADD);
311       execute_opcode(OPCODE_LOADSP & '1' & x"1"); -- Restore context
312       execute_opcode(OPCODE_SHORT & OPCODE_POPSP); -- Restore context
313       -- push_imm32(save_sp);
315       -- Need one NOP to update dbg.sp (for sanity check):
316       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
318       if (dbg.sp /= save_sp) then
319          mismatch <= '1';
320          print("* MEM_READ ERROR: Stack pointers don't match");
321          print("sp: " & hstr(dbg.sp) & "  SAVE_SP: " & hstr(save_sp));
322       end if;
324 ----------------------------------------------------------------------------
325 -- MEMORY WRITE
326       execute_opcode(OPCODE_SHORT & OPCODE_PUSHSP); -- Restore context
327       -- Save current SP for for reference. Note the dbg.sp is not yet
328       -- updated to the above command.
329       save_sp <= dbg.sp;
331       push_imm32(x"deadbeef");
332       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
333       push_imm32(x"000008d8");
334       execute_opcode(OPCODE_SHORT & OPCODE_STORE); -- Store indirect
336       execute_opcode(OPCODE_LOADSP & '1' & x"0"); -- Restore context
337       execute_opcode(OPCODE_SHORT & OPCODE_POPSP); -- Restore context
339       -- Need one NOP to update dbg.sp (for sanity check):
340       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
342       if (dbg.sp /= save_sp) then
343          mismatch <= '1';
344          print("* MEM_WRITE ERROR: Stack pointers don't match");
345          print("sp: " & hstr(dbg.sp) & "  SAVE_SP: " & hstr(save_sp));
346       end if;
348 ----------------------------------------------------------------------------
349 -- VERIFY:
350       mem_read(x"000008d8");
352 ----------------------------------------------------------------------------
353 -- SET PC
354       push_imm32(x"00000000");
355       execute_opcode(OPCODE_SHORT & OPCODE_POPPC); -- Restore context
356 ----------------------------------------------------------------------------
358       wait for 100ns;
359       execute_opcode(OPCODE_SHORT & OPCODE_NOP);
360       getsp;
362       terminate <= '1';
363       wait;
366    end process;
369 finish <= mismatch or terminate; -- or break;
371 end architecture Behave; -- Entity: HWDbg_Small1_TB