| 1 | 42 | ja_rd | --##############################################################################
 | 
      
         | 2 |  |  | -- This file was generated automatically from '/src/mips_tb2_template.vhdl'.
 | 
      
         | 3 |  |  | -- 
 | 
      
         | 4 |  |  | --------------------------------------------------------------------------------
 | 
      
         | 5 |  |  | -- Simulation test bench TB2 -- not synthesizable.
 | 
      
         | 6 |  |  | --
 | 
      
         | 7 |  |  | -- Simulates the CPU core connected to a simulated external static RAM and an
 | 
      
         | 8 |  |  | -- internal BRAM block through a stub (i.e. empty).
 | 
      
         | 9 |  |  | -- BRAM is initialized with the program object code, and SRAM is initialized 
 | 
      
         | 10 |  |  | -- with data secions from program. 
 | 
      
         | 11 |  |  | -- The makefile for the source samples include targets to build simulation test 
 | 
      
         | 12 |  |  | -- benches using this template, use them as usage examples.
 | 
      
         | 13 |  |  | --
 | 
      
         | 14 |  |  | -- The memory setup is meant to test the basic 'dummy' cache. 
 | 
      
         | 15 |  |  | -- 
 | 
      
         | 16 |  |  | -- Console output (at addresses compatible to Plasma's) is logged to text file
 | 
      
         | 17 |  |  | -- "hw_sim_console_log.txt".
 | 
      
         | 18 |  |  | -- IMPORTANT: The code that echoes UART TX data to the simulation console does
 | 
      
         | 19 |  |  | -- line buffering; it will not print anything until it gets a CR (0x0d), and
 | 
      
         | 20 |  |  | -- will ifnore LFs (0x0a). Bear this in mind if you see no output when you 
 | 
      
         | 21 |  |  | -- expect it.
 | 
      
         | 22 |  |  | --
 | 
      
         | 23 |  |  | -- WARNING: Will only work on Modelsim; uses custom library SignalSpy.
 | 
      
         | 24 |  |  | --##############################################################################
 | 
      
         | 25 |  |  |  
 | 
      
         | 26 |  |  | library ieee,modelsim_lib;
 | 
      
         | 27 |  |  | use ieee.std_logic_1164.all;
 | 
      
         | 28 |  |  | use ieee.std_logic_arith.all;
 | 
      
         | 29 |  |  | use ieee.std_logic_unsigned.all;
 | 
      
         | 30 |  |  | use work.mips_pkg.all;
 | 
      
         | 31 |  |  |  
 | 
      
         | 32 |  |  |  
 | 
      
         | 33 |  |  | use work.mips_pkg.all;
 | 
      
         | 34 |  |  |  
 | 
      
         | 35 |  |  | use modelsim_lib.util.all;
 | 
      
         | 36 |  |  | use std.textio.all;
 | 
      
         | 37 |  |  | use work.txt_util.all;
 | 
      
         | 38 |  |  |  
 | 
      
         | 39 |  |  | entity @entity_name@ is
 | 
      
         | 40 |  |  | end;
 | 
      
         | 41 |  |  |  
 | 
      
         | 42 |  |  |  
 | 
      
         | 43 |  |  | architecture @arch_name@ of @entity_name@ is
 | 
      
         | 44 |  |  |  
 | 
      
         | 45 |  |  | -------------------------------------------------------------------------------
 | 
      
         | 46 |  |  | -- Simulation parameters
 | 
      
         | 47 |  |  |  
 | 
      
         | 48 |  |  | -- Master clock period
 | 
      
         | 49 |  |  | constant T : time           := 20 ns;
 | 
      
         | 50 |  |  | -- Time the UART is unavailable after writing to the TX register
 | 
      
         | 51 |  |  | -- WARNING: slite does not simulate this. The logs may be different when > 0.0!
 | 
      
         | 52 |  |  | constant SIMULATED_UART_TX_TIME : time := 0.0 us;
 | 
      
         | 53 |  |  |  
 | 
      
         | 54 |  |  | -- Simulation length in clock cycles 
 | 
      
         | 55 |  |  | -- 2000 is enough for 'hello' sample, 22000 enough for 10 digits of pi
 | 
      
         | 56 |  |  | constant SIMULATION_LENGTH : integer := @sim_len@;
 | 
      
         | 57 |  |  |  
 | 
      
         | 58 |  |  | -- Simulated external SRAM size in 32-bit words 
 | 
      
         | 59 |  |  | constant SRAM_SIZE : integer := @xram_size@;
 | 
      
         | 60 |  |  | -- Ext. SRAM address length (memory is 16 bits wide so it needs an extra address bit)
 | 
      
         | 61 |  |  | constant SRAM_ADDR_SIZE : integer := log2(SRAM_SIZE)+1;
 | 
      
         | 62 |  |  |  
 | 
      
         | 63 |  |  |  
 | 
      
         | 64 |  |  | -- BRAM table and interface signals --------------------------------------------
 | 
      
         | 65 |  |  | constant BRAM_SIZE : integer := @code_table_size@;
 | 
      
         | 66 |  |  | constant BRAM_ADDR_SIZE : integer := @code_addr_size@;
 | 
      
         | 67 |  |  | subtype t_bram_address is std_logic_vector(BRAM_ADDR_SIZE-1 downto 0);
 | 
      
         | 68 |  |  | -- (this table holds one byte-slice; the RAM will have 4 of these)
 | 
      
         | 69 |  |  | type t_bram is array(0 to BRAM_SIZE-1) of std_logic_vector(7 downto 0);
 | 
      
         | 70 |  |  |  
 | 
      
         | 71 |  |  | signal bram_rd_addr :       t_bram_address;
 | 
      
         | 72 |  |  | signal bram_wr_addr :       t_bram_address;
 | 
      
         | 73 |  |  | signal bram_rd_data :       t_word;
 | 
      
         | 74 |  |  | signal bram_wr_data :       t_word;
 | 
      
         | 75 |  |  | signal bram_byte_we :       std_logic_vector(3 downto 0);
 | 
      
         | 76 |  |  |  
 | 
      
         | 77 |  |  | -- bram0 is LSB, bram3 is MSB
 | 
      
         | 78 |  |  | signal bram3 : t_bram := (@code3@);
 | 
      
         | 79 |  |  | signal bram2 : t_bram := (@code2@);
 | 
      
         | 80 |  |  | signal bram1 : t_bram := (@code1@);
 | 
      
         | 81 |  |  | signal bram0 : t_bram := (@code0@);
 | 
      
         | 82 |  |  |  
 | 
      
         | 83 |  |  | -- This is a 16-bit SRAM split in 2 byte slices; so each slice will have two
 | 
      
         | 84 |  |  | -- bytes for each word of SRAM_SIZE
 | 
      
         | 85 |  |  | type t_sram is array(0 to SRAM_SIZE*2-1) of std_logic_vector(7 downto 0);
 | 
      
         | 86 |  |  | signal sram1 : t_sram := (@data31@);
 | 
      
         | 87 |  |  | signal sram0 : t_sram := (@data20@);
 | 
      
         | 88 |  |  |  
 | 
      
         | 89 |  |  |  
 | 
      
         | 90 |  |  | signal data_uart :          std_logic_vector(31 downto 0);
 | 
      
         | 91 |  |  | signal data_uart_status :   std_logic_vector(31 downto 0);
 | 
      
         | 92 |  |  | signal uart_tx_rdy :        std_logic := '1';
 | 
      
         | 93 |  |  | signal uart_rx_rdy :        std_logic := '1';
 | 
      
         | 94 |  |  |  
 | 
      
         | 95 |  |  | --------------------------------------------------------------------------------
 | 
      
         | 96 |  |  |  
 | 
      
         | 97 |  |  | signal clk :                std_logic := '0';
 | 
      
         | 98 |  |  | signal reset :              std_logic := '1';
 | 
      
         | 99 |  |  | signal interrupt :          std_logic := '0';
 | 
      
         | 100 |  |  | signal done :               std_logic := '0';
 | 
      
         | 101 |  |  |  
 | 
      
         | 102 |  |  | -- interface to asynchronous 16-bit-wide external SRAM
 | 
      
         | 103 |  |  | signal sram_address :       std_logic_vector(SRAM_ADDR_SIZE-1 downto 1);
 | 
      
         | 104 |  |  | signal sram_databus :       std_logic_vector(15 downto 0);
 | 
      
         | 105 |  |  | signal sram_byte_we_n :     std_logic_vector(1 downto 0);
 | 
      
         | 106 |  |  | signal sram_oe_n :          std_logic;
 | 
      
         | 107 |  |  |  
 | 
      
         | 108 |  |  | -- interface cpu-cache
 | 
      
         | 109 |  |  | signal cpu_data_rd_addr :   t_word;
 | 
      
         | 110 |  |  | signal cpu_data_rd_vma :    std_logic;
 | 
      
         | 111 |  |  | signal cpu_data_rd :        t_word;
 | 
      
         | 112 |  |  | signal cpu_code_rd_addr :   t_pc;
 | 
      
         | 113 |  |  | signal cpu_code_rd :        t_word;
 | 
      
         | 114 |  |  | signal cpu_code_rd_vma :    std_logic;
 | 
      
         | 115 |  |  | signal cpu_data_wr_addr :   t_pc;
 | 
      
         | 116 |  |  | signal cpu_data_wr :        t_word;
 | 
      
         | 117 |  |  | signal cpu_byte_we :        std_logic_vector(3 downto 0);
 | 
      
         | 118 |  |  | signal cpu_mem_wait :       std_logic;
 | 
      
         | 119 |  |  |  
 | 
      
         | 120 |  |  | -- interface to i/o
 | 
      
         | 121 |  |  | signal io_rd_data :         std_logic_vector(31 downto 0);
 | 
      
         | 122 |  |  | signal io_wr_data :         std_logic_vector(31 downto 0);
 | 
      
         | 123 |  |  | signal io_rd_addr :         std_logic_vector(31 downto 2);
 | 
      
         | 124 |  |  | signal io_wr_addr :         std_logic_vector(31 downto 2);
 | 
      
         | 125 |  |  | signal io_rd_vma :          std_logic;
 | 
      
         | 126 |  |  | signal io_byte_we :         std_logic_vector(3 downto 0);
 | 
      
         | 127 |  |  |  
 | 
      
         | 128 |  |  |  
 | 
      
         | 129 |  |  | --------------------------------------------------------------------------------
 | 
      
         | 130 |  |  | -- Logging signals
 | 
      
         | 131 |  |  |  
 | 
      
         | 132 |  |  | -- These are internal CPU signal mirrored using Modelsim's SignalSpy
 | 
      
         | 133 |  |  | signal rbank :              t_rbank;
 | 
      
         | 134 |  |  | signal pc, cp0_epc :        std_logic_vector(31 downto 2);
 | 
      
         | 135 |  |  | signal reg_hi, reg_lo :     t_word;
 | 
      
         | 136 |  |  | signal negate_reg_lo :      std_logic;
 | 
      
         | 137 |  |  | signal ld_upper_byte :      std_logic;
 | 
      
         | 138 |  |  | signal ld_upper_hword :     std_logic;
 | 
      
         | 139 |  |  | signal data_rd_vma :        std_logic;
 | 
      
         | 140 |  |  | signal code_rd_vma :        std_logic;
 | 
      
         | 141 |  |  | signal data_rd_address :    std_logic_vector(31 downto 0);
 | 
      
         | 142 |  |  |  
 | 
      
         | 143 |  |  |  
 | 
      
         | 144 |  |  | -- Log file
 | 
      
         | 145 |  |  | file l_file: TEXT open write_mode is "hw_sim_log.txt";
 | 
      
         | 146 |  |  |  
 | 
      
         | 147 |  |  | -- Console output log file
 | 
      
         | 148 |  |  | file con_file: TEXT open write_mode is "hw_sim_console_log.txt";
 | 
      
         | 149 |  |  |  
 | 
      
         | 150 |  |  | -- Maximum line size of for console output log. Lines longer than this will be
 | 
      
         | 151 |  |  | -- truncated.
 | 
      
         | 152 |  |  | constant CONSOLE_LOG_LINE_SIZE : integer := 1024*4;
 | 
      
         | 153 |  |  |  
 | 
      
         | 154 |  |  | -- Console log line buffer
 | 
      
         | 155 |  |  | signal con_line_buf :       string(1 to CONSOLE_LOG_LINE_SIZE);
 | 
      
         | 156 |  |  | signal con_line_ix :        integer := 1;
 | 
      
         | 157 |  |  |  
 | 
      
         | 158 |  |  | -- Debug signals ---------------------------------------------------------------
 | 
      
         | 159 |  |  |  
 | 
      
         | 160 |  |  |  
 | 
      
         | 161 |  |  | signal full_rd_addr :       std_logic_vector(31 downto 0);
 | 
      
         | 162 |  |  | signal full_wr_addr :       std_logic_vector(31 downto 0);
 | 
      
         | 163 |  |  | signal full_code_addr :     std_logic_vector(31 downto 0);
 | 
      
         | 164 |  |  |  
 | 
      
         | 165 |  |  |  
 | 
      
         | 166 |  |  | begin
 | 
      
         | 167 |  |  |  
 | 
      
         | 168 |  |  |     cpu: entity work.mips_cpu
 | 
      
         | 169 |  |  |     port map (
 | 
      
         | 170 |  |  |         interrupt   => '0',
 | 
      
         | 171 |  |  |  
 | 
      
         | 172 |  |  |         data_rd_addr=> cpu_data_rd_addr,
 | 
      
         | 173 |  |  |         data_rd_vma => cpu_data_rd_vma,
 | 
      
         | 174 |  |  |         data_rd     => cpu_data_rd,
 | 
      
         | 175 |  |  |  
 | 
      
         | 176 |  |  |         code_rd_addr=> cpu_code_rd_addr,
 | 
      
         | 177 |  |  |         code_rd     => cpu_code_rd,
 | 
      
         | 178 |  |  |         code_rd_vma => cpu_code_rd_vma,
 | 
      
         | 179 |  |  |  
 | 
      
         | 180 |  |  |         data_wr_addr=> cpu_data_wr_addr,
 | 
      
         | 181 |  |  |         data_wr     => cpu_data_wr,
 | 
      
         | 182 |  |  |         byte_we     => cpu_byte_we,
 | 
      
         | 183 |  |  |  
 | 
      
         | 184 |  |  |         mem_wait    => cpu_mem_wait,
 | 
      
         | 185 |  |  |  
 | 
      
         | 186 |  |  |         clk         => clk,
 | 
      
         | 187 |  |  |         reset       => reset
 | 
      
         | 188 |  |  |     );
 | 
      
         | 189 |  |  |  
 | 
      
         | 190 |  |  |     cache: entity work.mips_cache_stub
 | 
      
         | 191 |  |  |     generic map (
 | 
      
         | 192 |  |  |         BRAM_ADDR_SIZE => BRAM_ADDR_SIZE,
 | 
      
         | 193 |  |  |         SRAM_ADDR_SIZE => SRAM_ADDR_SIZE
 | 
      
         | 194 |  |  |     )
 | 
      
         | 195 |  |  |     port map (
 | 
      
         | 196 |  |  |         clk             => clk,
 | 
      
         | 197 |  |  |         reset           => reset,
 | 
      
         | 198 |  |  |  
 | 
      
         | 199 |  |  |         -- Interface to CPU core
 | 
      
         | 200 |  |  |         data_rd_addr    => cpu_data_rd_addr,
 | 
      
         | 201 |  |  |         data_rd         => cpu_data_rd,
 | 
      
         | 202 |  |  |         data_rd_vma     => cpu_data_rd_vma,
 | 
      
         | 203 |  |  |  
 | 
      
         | 204 |  |  |         code_rd_addr    => cpu_code_rd_addr,
 | 
      
         | 205 |  |  |         code_rd         => cpu_code_rd,
 | 
      
         | 206 |  |  |         code_rd_vma     => cpu_code_rd_vma,
 | 
      
         | 207 |  |  |  
 | 
      
         | 208 |  |  |         data_wr_addr    => cpu_data_wr_addr,
 | 
      
         | 209 |  |  |         byte_we         => cpu_byte_we,
 | 
      
         | 210 |  |  |         data_wr         => cpu_data_wr,
 | 
      
         | 211 |  |  |  
 | 
      
         | 212 |  |  |         mem_wait        => cpu_mem_wait,
 | 
      
         | 213 |  |  |  
 | 
      
         | 214 |  |  |         -- interface to FPGA i/o devices
 | 
      
         | 215 |  |  |         io_rd_data      => io_rd_data,
 | 
      
         | 216 |  |  |         io_wr_data      => io_wr_data,
 | 
      
         | 217 |  |  |         io_rd_addr      => io_rd_addr,
 | 
      
         | 218 |  |  |         io_wr_addr      => io_wr_addr,
 | 
      
         | 219 |  |  |         io_rd_vma       => io_rd_vma,
 | 
      
         | 220 |  |  |         io_byte_we      => io_byte_we,
 | 
      
         | 221 |  |  |  
 | 
      
         | 222 |  |  |         -- interface to synchronous 32-bit-wide FPGA BRAM
 | 
      
         | 223 |  |  |         bram_rd_data    => bram_rd_data,
 | 
      
         | 224 |  |  |         bram_wr_data    => bram_wr_data,
 | 
      
         | 225 |  |  |         bram_rd_addr    => bram_rd_addr,
 | 
      
         | 226 |  |  |         bram_wr_addr    => bram_wr_addr,
 | 
      
         | 227 |  |  |         bram_byte_we    => bram_byte_we,
 | 
      
         | 228 |  |  |  
 | 
      
         | 229 |  |  |         -- interface to asynchronous 16-bit-wide external SRAM
 | 
      
         | 230 |  |  |         sram_address    => sram_address,
 | 
      
         | 231 |  |  |         sram_databus    => sram_databus,
 | 
      
         | 232 |  |  |         sram_byte_we_n  => sram_byte_we_n,
 | 
      
         | 233 |  |  |         sram_oe_n       => sram_oe_n
 | 
      
         | 234 |  |  |     );
 | 
      
         | 235 |  |  |  
 | 
      
         | 236 |  |  |     ---------------------------------------------------------------------------
 | 
      
         | 237 |  |  |     -- Master clock: free running clock used as main module clock
 | 
      
         | 238 |  |  |     run_master_clock:
 | 
      
         | 239 |  |  |     process(done, clk)
 | 
      
         | 240 |  |  |     begin
 | 
      
         | 241 |  |  |         if done = '0' then
 | 
      
         | 242 |  |  |             clk <= not clk after T/2;
 | 
      
         | 243 |  |  |         end if;
 | 
      
         | 244 |  |  |     end process run_master_clock;
 | 
      
         | 245 |  |  |  
 | 
      
         | 246 |  |  |     drive_uut:
 | 
      
         | 247 |  |  |     process
 | 
      
         | 248 |  |  |     variable l : line;
 | 
      
         | 249 |  |  |     begin
 | 
      
         | 250 |  |  |         wait for T*4;
 | 
      
         | 251 |  |  |         reset <= '0';
 | 
      
         | 252 |  |  |  
 | 
      
         | 253 |  |  |         wait for T*SIMULATION_LENGTH;
 | 
      
         | 254 |  |  |  
 | 
      
         | 255 |  |  |         -- Flush console output to log console file (in case the end of the
 | 
      
         | 256 |  |  |         -- simulation caugh an unterminated line in the buffer)
 | 
      
         | 257 |  |  |         if con_line_ix > 1 then
 | 
      
         | 258 |  |  |             write(l, con_line_buf(1 to con_line_ix));
 | 
      
         | 259 |  |  |             writeline(con_file, l);
 | 
      
         | 260 |  |  |         end if;
 | 
      
         | 261 |  |  |  
 | 
      
         | 262 |  |  |         print("TB0 finished");
 | 
      
         | 263 |  |  |         done <= '1';
 | 
      
         | 264 |  |  |         wait;
 | 
      
         | 265 |  |  |  
 | 
      
         | 266 |  |  |     end process drive_uut;
 | 
      
         | 267 |  |  |  
 | 
      
         | 268 |  |  |     full_rd_addr <= cpu_data_rd_addr;
 | 
      
         | 269 |  |  |     full_wr_addr <= cpu_data_wr_addr & "00";
 | 
      
         | 270 |  |  |     full_code_addr <= cpu_code_rd_addr & "00";
 | 
      
         | 271 |  |  |  
 | 
      
         | 272 |  |  |     data_ram_block:
 | 
      
         | 273 |  |  |     process(clk)
 | 
      
         | 274 |  |  |     begin
 | 
      
         | 275 |  |  |         if clk'event and clk='1' then
 | 
      
         | 276 |  |  |             if reset='0' then
 | 
      
         | 277 |  |  |                 bram_rd_data <=
 | 
      
         | 278 |  |  |                     bram3(conv_integer(unsigned(bram_rd_addr))) &
 | 
      
         | 279 |  |  |                     bram2(conv_integer(unsigned(bram_rd_addr))) &
 | 
      
         | 280 |  |  |                     bram1(conv_integer(unsigned(bram_rd_addr))) &
 | 
      
         | 281 |  |  |                     bram0(conv_integer(unsigned(bram_rd_addr)));
 | 
      
         | 282 |  |  |  
 | 
      
         | 283 |  |  |                 if bram_byte_we(3)='1' then
 | 
      
         | 284 |  |  |                     bram3(conv_integer(unsigned(bram_wr_addr))) <= cpu_data_wr(31 downto 24);
 | 
      
         | 285 |  |  |                 end if;
 | 
      
         | 286 |  |  |                 if bram_byte_we(2)='1' then
 | 
      
         | 287 |  |  |                     bram2(conv_integer(unsigned(bram_wr_addr))) <= cpu_data_wr(23 downto 16);
 | 
      
         | 288 |  |  |                 end if;
 | 
      
         | 289 |  |  |                 if bram_byte_we(1)='1' then
 | 
      
         | 290 |  |  |                     bram1(conv_integer(unsigned(bram_wr_addr))) <= cpu_data_wr(15 downto  8);
 | 
      
         | 291 |  |  |                 end if;
 | 
      
         | 292 |  |  |                 if bram_byte_we(0)='1' then
 | 
      
         | 293 |  |  |                     bram0(conv_integer(unsigned(bram_wr_addr))) <= cpu_data_wr( 7 downto  0);
 | 
      
         | 294 |  |  |                 end if;
 | 
      
         | 295 |  |  |             end if;
 | 
      
         | 296 |  |  |         end if;
 | 
      
         | 297 |  |  |     end process data_ram_block;
 | 
      
         | 298 |  |  |  
 | 
      
         | 299 |  |  |     sram_databus <=
 | 
      
         | 300 |  |  |         sram1(conv_integer(unsigned(sram_address))) &
 | 
      
         | 301 |  |  |         sram0(conv_integer(unsigned(sram_address)))   when sram_oe_n='0'
 | 
      
         | 302 |  |  |         else (others => 'Z');
 | 
      
         | 303 |  |  |  
 | 
      
         | 304 |  |  |     -- Do a very basic simulation of an external SRAM
 | 
      
         | 305 |  |  |     simulated_sram:
 | 
      
         | 306 |  |  |     process(sram_byte_we_n, sram_address)
 | 
      
         | 307 |  |  |     begin
 | 
      
         | 308 |  |  |         -- FIXME should add OE\ to control logic
 | 
      
         | 309 |  |  |         if sram_byte_we_n'event or sram_address'event then
 | 
      
         | 310 |  |  |             if sram_byte_we_n(1)='0' then
 | 
      
         | 311 |  |  |                 sram1(conv_integer(unsigned(sram_address))) <= sram_databus(15 downto  8);
 | 
      
         | 312 |  |  |             end if;
 | 
      
         | 313 |  |  |             if sram_byte_we_n(0)='0' then
 | 
      
         | 314 |  |  |                 sram0(conv_integer(unsigned(sram_address))) <= sram_databus( 7 downto  0);
 | 
      
         | 315 |  |  |             end if;
 | 
      
         | 316 |  |  |         end if;
 | 
      
         | 317 |  |  |     end process simulated_sram;
 | 
      
         | 318 |  |  |  
 | 
      
         | 319 |  |  |  
 | 
      
         | 320 |  |  |     simulated_io:
 | 
      
         | 321 |  |  |     process(clk)
 | 
      
         | 322 |  |  |     variable i : integer;
 | 
      
         | 323 |  |  |     variable uart_data : integer;
 | 
      
         | 324 |  |  |     begin
 | 
      
         | 325 |  |  |         if clk'event and clk='1' then
 | 
      
         | 326 |  |  |  
 | 
      
         | 327 |  |  |             if io_byte_we/="0000" then
 | 
      
         | 328 |  |  |                 if io_wr_addr(31 downto 28)=X"2" then
 | 
      
         | 329 |  |  |                     -- Write to UART
 | 
      
         | 330 |  |  |  
 | 
      
         | 331 |  |  |                     -- If we're simulating the UART TX time, pulse RDY low
 | 
      
         | 332 |  |  |                     if SIMULATED_UART_TX_TIME > 0 us then
 | 
      
         | 333 |  |  |                         uart_tx_rdy <= '0', '1' after SIMULATED_UART_TX_TIME;
 | 
      
         | 334 |  |  |                     end if;
 | 
      
         | 335 |  |  |  
 | 
      
         | 336 |  |  |                     -- TX data may come from the high or low byte (opcodes.s
 | 
      
         | 337 |  |  |                     -- uses high byte, no_op.c uses low)
 | 
      
         | 338 |  |  |                     if io_byte_we(0)='1' then
 | 
      
         | 339 |  |  |                         uart_data := conv_integer(unsigned(io_wr_data(7 downto 0)));
 | 
      
         | 340 |  |  |                     else
 | 
      
         | 341 |  |  |                         uart_data := conv_integer(unsigned(io_wr_data(31 downto 24)));
 | 
      
         | 342 |  |  |                     end if;
 | 
      
         | 343 |  |  |  
 | 
      
         | 344 |  |  |                     -- UART TX data goes to output after a bit of line-buffering
 | 
      
         | 345 |  |  |                     -- and editing
 | 
      
         | 346 |  |  |                     if uart_data = 10 then
 | 
      
         | 347 |  |  |                         -- CR received: print output string and clear it
 | 
      
         | 348 |  |  |                         print(con_file, con_line_buf(1 to con_line_ix));
 | 
      
         | 349 |  |  |                         con_line_ix <= 1;
 | 
      
         | 350 |  |  |                         for i in 1 to con_line_buf'high loop
 | 
      
         | 351 |  |  |                            con_line_buf(i) <= ' ';
 | 
      
         | 352 |  |  |                         end loop;
 | 
      
         | 353 |  |  |                     elsif uart_data = 13 then
 | 
      
         | 354 |  |  |                         -- ignore LF
 | 
      
         | 355 |  |  |                     else
 | 
      
         | 356 |  |  |                         -- append char to output string
 | 
      
         | 357 |  |  |                         if con_line_ix < con_line_buf'high then
 | 
      
         | 358 |  |  |                             con_line_buf(con_line_ix) <= character'val(uart_data);
 | 
      
         | 359 |  |  |                             con_line_ix <= con_line_ix + 1;
 | 
      
         | 360 |  |  |                         end if;
 | 
      
         | 361 |  |  |                     end if;
 | 
      
         | 362 |  |  |                 end if;
 | 
      
         | 363 |  |  |             end if;
 | 
      
         | 364 |  |  |         end if;
 | 
      
         | 365 |  |  |     end process simulated_io;
 | 
      
         | 366 |  |  |  
 | 
      
         | 367 |  |  |     -- UART read registers; only status, and hardwired, for the time being
 | 
      
         | 368 |  |  |     data_uart <= data_uart_status;
 | 
      
         | 369 |  |  |     data_uart_status <= X"0000000" & "00" & uart_tx_rdy & uart_rx_rdy;
 | 
      
         | 370 |  |  |  
 | 
      
         | 371 |  |  |  
 | 
      
         | 372 |  |  |     signalspy_rbank:
 | 
      
         | 373 |  |  |     process
 | 
      
         | 374 |  |  |     begin
 | 
      
         | 375 |  |  |         init_signal_spy("/@entity_name@/cpu/p1_rbank", "rbank", 0, -1);
 | 
      
         | 376 |  |  |         init_signal_spy("/@entity_name@/cpu/p0_pc_reg", "pc", 0, -1);
 | 
      
         | 377 |  |  |         init_signal_spy("/@entity_name@/cpu/mult_div/upper_reg", "reg_hi", 0, -1);
 | 
      
         | 378 |  |  |         init_signal_spy("/@entity_name@/cpu/mult_div/lower_reg", "reg_lo", 0, -1);
 | 
      
         | 379 |  |  |         init_signal_spy("/@entity_name@/cpu/mult_div/negate_reg", "negate_reg_lo", 0, -1);
 | 
      
         | 380 |  |  |         init_signal_spy("/@entity_name@/cpu/cp0_epc", "cp0_epc", 0, -1);
 | 
      
         | 381 |  |  |         init_signal_spy("/@entity_name@/cpu/p2_ld_upper_byte", "ld_upper_byte", 0, -1);
 | 
      
         | 382 |  |  |         init_signal_spy("/@entity_name@/cpu/p2_ld_upper_byte", "ld_upper_hword", 0, -1);
 | 
      
         | 383 |  |  |         init_signal_spy("/@entity_name@/cpu/data_rd_vma", "data_rd_vma", 0, -1);
 | 
      
         | 384 |  |  |         init_signal_spy("/@entity_name@/cpu/code_rd_vma", "code_rd_vma", 0, -1);
 | 
      
         | 385 |  |  |         wait;
 | 
      
         | 386 |  |  |     end process signalspy_rbank;
 | 
      
         | 387 |  |  |  
 | 
      
         | 388 |  |  |  
 | 
      
         | 389 |  |  |     log_cpu_activity:
 | 
      
         | 390 |  |  |     process(clk)
 | 
      
         | 391 |  |  |     variable prev_rbank : t_rbank := (others => X"00000000");
 | 
      
         | 392 |  |  |     variable ri : std_logic_vector(7 downto 0);
 | 
      
         | 393 |  |  |     variable full_pc : t_word := (others => '0');
 | 
      
         | 394 |  |  |     variable prev_pc : t_word := (others => '0');
 | 
      
         | 395 |  |  |     variable prev_hi : t_word := (others => '0');
 | 
      
         | 396 |  |  |     variable prev_lo : t_word := (others => '0');
 | 
      
         | 397 |  |  |     variable prev_epc : std_logic_vector(31 downto 2) := (others => '0');
 | 
      
         | 398 |  |  |     variable wr_data : t_word := (others => '0');
 | 
      
         | 399 |  |  |     variable temp : t_word := (others => '0');
 | 
      
         | 400 |  |  |     variable size : std_logic_vector(7 downto 0) := X"00";
 | 
      
         | 401 |  |  |     variable prev_vma_data : std_logic := '0';
 | 
      
         | 402 |  |  |     variable prev_rd_addr : t_word := (others => '0');
 | 
      
         | 403 |  |  |     variable prev_rd_data : t_word := (others => '0');
 | 
      
         | 404 |  |  |     variable rd_size : std_logic_vector(7 downto 0) := X"00";
 | 
      
         | 405 |  |  |     begin
 | 
      
         | 406 |  |  |         -- we'll be sampling control & data signals at falling edge, when 
 | 
      
         | 407 |  |  |         -- they're stable
 | 
      
         | 408 |  |  |         if clk'event and clk='0' then
 | 
      
         | 409 |  |  |             if reset='0' then
 | 
      
         | 410 |  |  |                 -- log loads (data only)
 | 
      
         | 411 |  |  |                 -- IMPORTANT: memory reads should be logged first because we're
 | 
      
         | 412 |  |  |                 -- logging them the cycle after they actually happen. If you put
 | 
      
         | 413 |  |  |                 -- the log code after any other log, the order of the operations 
 | 
      
         | 414 |  |  |                 -- will appear wrong in the log even though it is not.
 | 
      
         | 415 |  |  |                 if prev_vma_data='1' and cpu_mem_wait='0' then
 | 
      
         | 416 |  |  |                     if ld_upper_hword='1' then
 | 
      
         | 417 |  |  |                         rd_size := X"04";
 | 
      
         | 418 |  |  |                     elsif ld_upper_byte='1' then
 | 
      
         | 419 |  |  |                         rd_size := X"02";
 | 
      
         | 420 |  |  |                     else
 | 
      
         | 421 |  |  |                         rd_size := X"01";
 | 
      
         | 422 |  |  |                     end if;
 | 
      
         | 423 |  |  |                     print(l_file, "("& hstr(prev_pc) &") ["& hstr(prev_rd_addr) &"] <"&
 | 
      
         | 424 |  |  |                           "**"&
 | 
      
         | 425 |  |  |                           --hstr(rd_size)& 
 | 
      
         | 426 |  |  |                           ">="& hstr(cpu_data_rd)& " RD");
 | 
      
         | 427 |  |  |                 end if;
 | 
      
         | 428 |  |  |  
 | 
      
         | 429 |  |  |                 prev_rd_data := cpu_data_rd;
 | 
      
         | 430 |  |  |                 if cpu_mem_wait='0' then
 | 
      
         | 431 |  |  |                     prev_vma_data := data_rd_vma;
 | 
      
         | 432 |  |  |                     prev_rd_addr := full_rd_addr;
 | 
      
         | 433 |  |  |                 end if;
 | 
      
         | 434 |  |  |  
 | 
      
         | 435 |  |  |                 -- log register changes
 | 
      
         | 436 |  |  |                 ri := X"00";
 | 
      
         | 437 |  |  |                 for i in 0 to 31 loop
 | 
      
         | 438 |  |  |                     if prev_rbank(i)/=rbank(i) then
 | 
      
         | 439 |  |  |                         print(l_file, "("& hstr(full_pc)& ") ["& hstr(ri)& "]="& hstr(rbank(i)));
 | 
      
         | 440 |  |  |                     end if;
 | 
      
         | 441 |  |  |                     ri := ri + 1;
 | 
      
         | 442 |  |  |                 end loop;
 | 
      
         | 443 |  |  |  
 | 
      
         | 444 |  |  |                 -- log aux register changes, only when pipeline is not stalled
 | 
      
         | 445 |  |  |                 if prev_lo /= reg_lo and reg_lo(0)/='U' and code_rd_vma='1' then
 | 
      
         | 446 |  |  |                     -- we're observing the value of reg_lo, but the mult core
 | 
      
         | 447 |  |  |                     -- will output the negated value in some cases. We
 | 
      
         | 448 |  |  |                     -- have to mimic that behavior.
 | 
      
         | 449 |  |  |                     if negate_reg_lo='1' then
 | 
      
         | 450 |  |  |                         -- negate reg_lo before displaying
 | 
      
         | 451 |  |  |                         prev_lo := not reg_lo;
 | 
      
         | 452 |  |  |                         prev_lo := prev_lo + 1;
 | 
      
         | 453 |  |  |                         print(l_file, "("& hstr(full_pc)& ") [LO]="& hstr(prev_lo));
 | 
      
         | 454 |  |  |                     else
 | 
      
         | 455 |  |  |                         print(l_file, "("& hstr(full_pc)& ") [LO]="& hstr(reg_lo));
 | 
      
         | 456 |  |  |                     end if;
 | 
      
         | 457 |  |  |                 end if;
 | 
      
         | 458 |  |  |                 if prev_hi /= reg_hi and reg_hi(0)/='U' and code_rd_vma='1' then
 | 
      
         | 459 |  |  |                     print(l_file, "("& hstr(full_pc)& ") [HI]="& hstr(reg_hi));
 | 
      
         | 460 |  |  |                 end if;
 | 
      
         | 461 |  |  |                 if prev_epc /= cp0_epc and cp0_epc(31)/='U'  then
 | 
      
         | 462 |  |  |                     temp := cp0_epc & "00";
 | 
      
         | 463 |  |  |                     print(l_file, "("& hstr(full_pc)& ") [EP]="& hstr(temp));
 | 
      
         | 464 |  |  |                 end if;
 | 
      
         | 465 |  |  |  
 | 
      
         | 466 |  |  |                 -- 'remember' last value of hi and lo only when pipeline is not
 | 
      
         | 467 |  |  |                 -- stalled; that's because we don't want to be tracking the
 | 
      
         | 468 |  |  |                 -- changing values when mul/div is running (because the SW 
 | 
      
         | 469 |  |  |                 -- simulator doesn't)
 | 
      
         | 470 |  |  |                 if code_rd_vma='1' then
 | 
      
         | 471 |  |  |                     prev_hi := reg_hi;
 | 
      
         | 472 |  |  |                     prev_lo := reg_lo;
 | 
      
         | 473 |  |  |                 end if;
 | 
      
         | 474 |  |  |  
 | 
      
         | 475 |  |  |  
 | 
      
         | 476 |  |  |                 full_pc := pc & "00";
 | 
      
         | 477 |  |  |                 prev_pc := full_pc;
 | 
      
         | 478 |  |  |                 prev_rbank := rbank;
 | 
      
         | 479 |  |  |                 prev_epc := cp0_epc;
 | 
      
         | 480 |  |  |  
 | 
      
         | 481 |  |  |                 -- log writes
 | 
      
         | 482 |  |  |                 if cpu_byte_we/="0000" then
 | 
      
         | 483 |  |  |                     wr_data := X"00000000";
 | 
      
         | 484 |  |  |                     if cpu_byte_we(3)='1' then
 | 
      
         | 485 |  |  |                         wr_data(31 downto 24) := cpu_data_wr(31 downto 24);
 | 
      
         | 486 |  |  |                     end if;
 | 
      
         | 487 |  |  |                     if cpu_byte_we(2)='1' then
 | 
      
         | 488 |  |  |                         wr_data(23 downto 16) := cpu_data_wr(23 downto 16);
 | 
      
         | 489 |  |  |                     end if;
 | 
      
         | 490 |  |  |                     if cpu_byte_we(1)='1' then
 | 
      
         | 491 |  |  |                         wr_data(15 downto  8) := cpu_data_wr(15 downto  8);
 | 
      
         | 492 |  |  |                     end if;
 | 
      
         | 493 |  |  |                     if cpu_byte_we(0)='1' then
 | 
      
         | 494 |  |  |                         wr_data( 7 downto  0) := cpu_data_wr( 7 downto  0);
 | 
      
         | 495 |  |  |                     end if;
 | 
      
         | 496 |  |  |                     size := "0000" & cpu_byte_we; -- mask, really
 | 
      
         | 497 |  |  |                     print(l_file, "("& hstr(full_pc) &") ["& hstr(full_wr_addr) &"] |"& hstr(size)& "|="& hstr(wr_data)& " WR" );
 | 
      
         | 498 |  |  |                 end if;
 | 
      
         | 499 |  |  |  
 | 
      
         | 500 |  |  |                 if full_code_addr(31 downto 28)="1111" then
 | 
      
         | 501 |  |  |                     print(l_file, "ERROR: Code addressed upper memory area" );
 | 
      
         | 502 |  |  |                 end if;
 | 
      
         | 503 |  |  |  
 | 
      
         | 504 |  |  |             end if;
 | 
      
         | 505 |  |  |         end if;
 | 
      
         | 506 |  |  |     end process log_cpu_activity;
 | 
      
         | 507 |  |  |  
 | 
      
         | 508 |  |  | end architecture @arch_name@;
 |