OpenCores
URL https://opencores.org/ocsvn/p9813_rgb_led_string_driver/p9813_rgb_led_string_driver/trunk

Subversion Repositories p9813_rgb_led_string_driver

[/] [p9813_rgb_led_string_driver/] [trunk/] [rtl/] [VHDL/] [testbench/] [sim_control_port_pack.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------
-- Package of simulation control port components
--
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
package sim_control_port_pack is
 
  component sim_uart_control_port
  generic(
    INPUT_FILE     :  string;
    OUTPUT_FILE    :  string;
    POR_DURATION   :    time;  -- Duration of internal reset signal activity
    POR_ASSERT_LOW : boolean;  -- Determine polarity of reset signal
    CLKRATE        : integer;  -- Control Port clock rate default.
    UART_BAUDRATE  : integer;  -- UART Speed, in bits per second.
    UART_PARITY    : integer;  -- ODD parity
    LINE_LENGTH    : integer   -- Length of buffer to hold file input bytes
  );
  port(
    test_rst : out std_logic;
    test_clk : out std_logic;
    uart_tx  : out std_logic;  -- async. Serial line to FPGA
    uart_rx  : in  std_logic   -- async. Serial line from FPGA
  );
  end component;
 
  component sim_bus_control_port
  generic(
    -- relating to file I/O
    INPUT_FILE      :  string;
    OUTPUT_FILE     :  string;
    POR_DURATION    :    time;  -- Duration of internal reset signal activity
    POR_ASSERT_LOW  : boolean;  -- Determine polarity of reset signal
    CLKRATE         : integer;  -- Control Port clock rate
    LINE_LENGTH     : integer;  -- Length of buffer to hold file input bytes
    -- relating to the bus controller
    ADR_DIGITS      : natural; -- # of hex digits for address
    DAT_DIGITS      : natural; -- # of hex digits for data
    QTY_DIGITS      : natural; -- # of hex digits for quantity
    CMD_BUFFER_SIZE : natural; -- # of chars in the command buffer
    WATCHDOG_VALUE  : natural; -- # of sys_clks before ack is expected
    DISPLAY_FIELDS  : natural  -- # of fields/line
  );
  port(
    -- Clock and reset stimulus
    test_rst : out std_logic;
    test_clk : out std_logic;
 
    -- System Bus IO
    ack_i    : in  std_logic;
    err_i    : in  std_logic;
    dat_i    : in  unsigned(4*DAT_DIGITS-1 downto 0);
    dat_o    : out unsigned(4*DAT_DIGITS-1 downto 0);
    rst_o    : out std_logic;
    stb_o    : out std_logic;
    cyc_o    : out std_logic;
    adr_o    : out unsigned(4*ADR_DIGITS-1 downto 0);
    we_o     : out std_logic
  );
  end component;
 
 
end sim_control_port_pack;
 
package body sim_control_port_pack is
end sim_control_port_pack;
 
-------------------------------------------------------------------------------
-- Simulation UART ASCII Control Port
-------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Date  : Jan. 02, 2014 Transferred component into package file, wrote
--                       short description.
--
-- Description
-------------------------------------------------------------------------------
-- This is a component meant for simulation only.  It allows commands to be
-- read in from a file, parsed, and characters representing the desired
-- command are then sent out in asynchronous serial form, via a UART.
--
-- There is a delay specified with each command in the input file, which
-- determines how much time elapses between the current command and the
-- subsequent one.  Care must therefore be exercised when setting up the
-- simulation command input file, since commands which do not have
-- sufficient delay can cause subsequent commands to be ignored.
--
--   DESCRIPTION OF STIMULUS FILE I/O
--   --------------------------------
-- The stimulus file I/O introduces a "wrapper" around the characters which are fed
-- as stimulus into the command processor of the bus controller.  This is done so that
-- each command, after being issued, can be followed up with the requested delay before
-- issuing the next command.  Also, the structure of the stimulus input file contains
-- provisions for different types of stimulus, although only the 'd' and 'b' types are
-- implemented here:
--
--   'u' type = UART bus command with delay
--
-- The related module, "sim_bus_control_port" uses the 'b' type:
--
--   'b' type = binary bus command with delay
--   'd' type = delay only; no command
--
-- The line is terminated with one of these characters:
--   ';' (Sends a Carriage Return, 0x0D)
--   '\' (Sends an Escape character, 0x1B)
--   '-' (Sends a Carriage Return, and ignores the remainder of the line as a comment)
 
 
library IEEE ;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
 
library std ;
use std.textio.all;
 
library work;
use work.function_pack.all;
use work.uart_sqclk_pack.all;
use work.sim_support_pack.all;
 
entity sim_uart_control_port is
  generic(
    INPUT_FILE     : string  := ".\uart_sim_in.txt";
    OUTPUT_FILE    : string  := ".\uart_sim_out.txt";
    POR_DURATION   :   time  :=    500 ns;  -- Duration of internal reset signal activity
    POR_ASSERT_LOW : boolean :=     false;  -- Determines polarity of reset output
    CLKRATE        : integer := 100000000;  -- Control Port clock rate default.
    UART_BAUDRATE  : integer :=    921600;  -- UART Speed, in bits per second.
    UART_PARITY    : integer :=         2;  -- ODD parity
    LINE_LENGTH    : integer :=        40   -- Length of buffer to hold file input bytes
  );
  port(
    test_rst : out std_logic;  -- Programmable polarity
    test_clk : out std_logic;  -- Programmable frequency
    uart_tx  : out std_logic;  -- HS async. Serial line to FPGA
    uart_rx  : in  std_logic   -- HS async. Serial line from FPGA
  );
end sim_uart_control_port;
 
architecture beh of sim_uart_control_port is
 
---- Constants
constant BS_CHAR_U : unsigned(7 downto 0) := str2u("08",8);
constant CR_CHAR_U : unsigned(7 downto 0) := str2u("0D",8);
constant LF_CHAR_U : unsigned(7 downto 0) := str2u("0A",8);
constant ES_CHAR_U : unsigned(7 downto 0) := str2u("1B",8); -- Escape character
 
---- Components
 
---- State Machine
TYPE   TST_STATE_TYPE IS (IDLE, UART_TX_OP);
signal tst_state        : TST_STATE_TYPE;
 
---- Stimulus related signals
type   cmd_bytes_array is array (integer range 0 to LINE_LENGTH-1) of unsigned(7 downto 0);
signal cmd_bytes    : cmd_bytes_array;
signal cmd_byte_cnt : integer;
signal tx_length    : integer;
signal new_stim     : boolean := false;
signal stim_kind    : character;
 
-- Internal signals
signal ctlr_test_clk_i  : std_logic := '0';
signal nhreset_internal : std_logic := '0';
 
  -- Clock generator signals
signal uart_dds_phase  : unsigned(15 downto 0);
signal uart_clk        : std_logic;
 
  -- UART signals
signal tx_wr       : std_logic;
signal tx_data     : unsigned(7 downto 0);
signal tx_done     : std_logic;
signal tx_done_qld : std_logic; -- Qualified tx_done, stays low when tx_wr is high.
signal rx_wr       : std_logic;
signal rx_data     : unsigned(7 downto 0);
signal rx_done     : std_logic;
signal parity      : unsigned(1 downto 0);  -- Parity setting.
signal uart_rate   : unsigned(15 downto 0); -- Bit rate setting.
 
 
BEGIN
 
  test_clk    <= ctlr_test_clk_i;
 
  -------------------------
  -- Controller Clock Process
  -- Generates the Control Port clock
  ctlr_clk : process
    variable PS_PER_SECOND : real := 1.0E+12;
    variable half_period : time := integer(PS_PER_SECOND/(2.0*real(CLKRATE))) * 1 ps;
  begin
     --wait for 1/2 of the clock period;
     wait for half_period;
     ctlr_test_clk_i <= not (ctlr_test_clk_i);
  end process;
 
-------------------------
-- Reset Process
-- Causes reset to go inactive after a given time.
  rst_gen : process
  begin
    wait for POR_DURATION; -- Maybe wait long enough for the PLL to lock...
    nhreset_internal <= '1';
  end process;
  test_rst <= nhreset_internal when (POR_ASSERT_LOW) else not nhreset_internal;
 
-------------------------
-- Stimulus Process
-- Reads text input file and forms stimulus needed for the simulation.
  stim_proc: process(ctlr_test_clk_i, nhreset_internal)
    file s_file : text is in INPUT_FILE;
    variable time_mark    : time := 0 ns; -- Last NOW time when file IO was parsed
    variable time_val     : time := 0 ns; -- Relative time of next file IO parsing.
    variable line_1       : line;
    variable line_2       : line;
    variable item_count   : integer;
    variable line_num     : integer;
    variable line_done    : boolean;
    variable stim_done    : boolean;
    variable good         : boolean;
    variable temp_char    : character;
    variable stim_kind_v  : character; -- variable version readable immediately in display_stim
    variable cmd_found    : boolean;
    variable dchar_i      : integer;
 
    -- returns true is the character is a valid hexadecimal character.
    function is_hex(c : character) return boolean is
    begin
      case c is
        when '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
             'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 
             'e' | 'f' =>
          return(true);
        when others =>
          return(false);
      end case;
    end is_hex;
 
    -- This prints the time and type of stimulus
    procedure display_stim is
    begin
      if (temp_char/='-') then
        write (line_2, string'(" [line "));
        write (line_2, line_num);
        write (line_2, string'(", at "));
        write (line_2, now, unit => ns);
        write (line_2, string'("]"));
        writeline (output, line_2);
      end if;
    end display_stim;
 
  begin
    if (nhreset_internal='0') then
      tx_length <= 0;
      line_num := 0;
    elsif (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      -- Default Values
      new_stim <= false;
      if (tst_state/=IDLE) then
        new_stim <= false;
      end if;
      -- Simulation Stimulus
      if (NOW > (time_val+time_mark)) then
        if not(endfile(s_file)) then
          readline(s_file, line_1);
          line_num   := line_num+1;
          stim_done  := false;
          cmd_found  := false;
          item_count := 0;
          stim_kind   <= 'z'; -- Default
          stim_kind_v := 'z';
          if (line_1'length=0) then
            line_done := true;
          else
            line_done  := false;
          end if;
          while (line_done = false) loop
            read(line_1, temp_char, good);
            if (temp_char = '-' or temp_char = ';' or temp_char = '\') then
              line_done := true;
            elsif (item_count=0 and temp_char/=' ') then
              stim_kind   <= temp_char;
              stim_kind_v := temp_char; -- Display stim uses this.  It cannot read stim_kind immediately.
              if (stim_kind_v='u') then
                write(line_2,string'("UART Command: "));
              elsif (stim_kind_v='d') then
                write(line_2,string'("UART Delay Token. "));
              else
                write(line_2,string'("UART Unknown stimulus type encountered.  No action taken."));
              end if;
              item_count  := item_count+1;
            elsif (item_count=1) then -- Time field read removes leading whitespace automatically.
              time_val := 0 ns;
              read(line_1, time_val);
              time_mark := NOW;
              item_count := item_count+1;
            end if;
            if (stim_kind_v='u') then
              if (item_count>1 and not line_done) then
                if (cmd_found) then
                  cmd_bytes(item_count-2) <= asciichar2u(temp_char);
                  write(line_2, temp_char); -- Keep record of cmd characters for display
                  item_count := item_count+1;
                else
                  if not is_space(temp_char) then
                    cmd_found := true;
                    cmd_bytes(item_count-2) <= asciichar2u(temp_char);
                    write(line_2, temp_char); -- Keep record of cmd characters for display
                    item_count := item_count+1;
                  end if;
                end if;
              elsif (item_count>1 and temp_char=';') then
                cmd_bytes(item_count-2) <= CR_CHAR_U;
                item_count := item_count+1;
              elsif (item_count>1 and temp_char='\') then
                cmd_bytes(item_count-2) <= ES_CHAR_U;
                item_count := item_count+1;
              end if;
            end if;
            if (good=false) then
              line_done := true;
            end if;
          end loop;
          if (stim_kind_v='u') then
            tx_length <= item_count-2;
            new_stim <= true;
          end if;
          display_stim;
        elsif not (stim_done) then
          write (line_2, string'("At "));
          write (line_2, now, unit => ns);
          write (line_2, string'(", UART control port finished reading stimulus file. "));
          writeline (output, line_2);
          stim_done := true;
        end if;
      end if;
    end if;
 
  end process;
 
-------------------------
-- Response Record Process
  response_proc: process(ctlr_test_clk_i)
    file o_file : text is out OUTPUT_FILE;
    variable line_1       : line;
    variable line_2       : line;
    variable good         : boolean;
    variable header_done  : boolean := false;
 
  begin
    if not header_done then
      write (line_2, string'("Simulation Results File"));
      writeline (o_file, line_2);
      header_done := true;
    end if;
    if (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      if (rx_wr='1') then
        if (rx_data=BS_CHAR_U) then
          write (line_2, string'("<BS>"));
        elsif (rx_data=CR_CHAR_U) then
          write (line_2, string'("<CR>"));
        elsif (rx_data=LF_CHAR_U) then
          write (line_2, string'("<LF>"));
          writeline (o_file, line_2);
--          write (line_2, string'("At "));
--          write (line_2, now, justified => RIGHT, field => 12, unit => us);
--          write (line_2, string'(", received line feed."));
--          writeline (o_file, line_2);
        else
--          write (line_2, u2string(rx_data,2)); -- For Hexadecimal output
          write (line_2, u2asciichar(rx_data)); -- For ASCII output
        end if;
      end if;
    end if;
 
  end process;
 
-------------------------
-- Control Port State Machine
-- For async., loads and awaits TX completion for the three TLM bytes.
-- For CMD, simply starts the transmitter and waits for completion.
  cp_fsm_proc: process(ctlr_test_clk_i, nhreset_internal)
  begin
    if (nhreset_internal='0') then
      tst_state  <= IDLE;
      tx_wr      <= '0';
      tx_data    <= (others=>'0');
      cmd_byte_cnt   <= 0;
    elsif (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      -- Default Values
      tx_wr      <= '0';
      tx_data    <= (others=>'0');
      case tst_state is
 
        when IDLE =>
          cmd_byte_cnt <= 0;
          if (new_stim) then
            if (stim_kind='u') then
              tst_state <= UART_TX_OP;
            end if;
          end if;
 
        when UART_TX_OP =>         -- Send out the bytes
          if (tx_done_qld = '1') then
            if (cmd_byte_cnt = tx_length) then
              cmd_byte_cnt <= 0;
              tst_state <= IDLE;
            else
              tx_wr   <= '1';
              cmd_byte_cnt <= cmd_byte_cnt+1;
              tx_data <= cmd_bytes(cmd_byte_cnt);
            end if;
          end if;
 
      end case;
    end if;                                      -- end if(FPGA_CLK = 1)
  end process;
 
  tx_done_qld <= (tx_done and not tx_wr);
 
-------------------------
-- UART without buffer
  tst_uart: entity work.uart_sqclk
    port map ( 
 
      sys_rst_n     => nhreset_internal,
      sys_clk       => ctlr_test_clk_i,
      sys_clk_en    => '1',
 
      -- rate and parity
      parity_i      => parity,
      rate_clk_i    => uart_clk,
 
      -- serial I/O
      tx_stream     => uart_tx,
      rx_stream     => uart_rx,
 
      --control and status
      tx_wr_i       => tx_wr,
      tx_dat_i      => tx_data,
      tx_done_o     => tx_done,
      rx_restart_i  => '0',
      rx_dat_o      => rx_data,
      rx_wr_o       => rx_wr,
      rx_done_o     => rx_done,
      frame_err_o   => open,
      parity_err_o  => open
    );
 
  -- UART settings
  parity    <= to_unsigned(UART_PARITY,parity'length);
  uart_rate <= to_unsigned(integer(real(2**16)*real(UART_BAUDRATE)/real(CLKRATE)),16);
 
  -------------------------
  -- UART Clock Process
  uart_dds: process(nhreset_internal,ctlr_test_clk_i)
  begin
    if (nhreset_internal = '0') then
      uart_dds_phase   <= (others=>'0');
    elsif (ctlr_test_clk_i'event and ctlr_test_clk_i='1') then
      uart_dds_phase <= uart_dds_phase + uart_rate;
    end if;
  end process uart_dds;
  uart_clk <= uart_dds_phase(15);
 
 
end beh;
 
 
 
 
---------------------------------------------------------------------------------------
-- Bus Controller for simulation use
---------------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Date  : Dec. 27, 2013
-- Update: 12/27/13 Copied code from async_syscon_pack.vhd, Wrote some description
--                  Began merging in file I/O code from "uart_ascii_control_port_sim.vhd"
--
-- Description
---------------------------------------------------------------------------------------
-- This Bus Controller for simulation use combines a "ascii_syscon" module with a
-- "uart_ascii_control_port_sim" module, resulting in a single module that can use
-- file I/O for stimulus input and response output, while providing the parameterized
-- capabilities of the async_syscon module.  The purpose for combining these modules
-- is to eliminate the serial interface between them, thereby dramatically decreasing
-- simulation run times.
--
--   DESCRIPTION OF STIMULUS FILE I/O
--   --------------------------------
-- The stimulus file I/O introduces a "wrapper" around the characters which are fed
-- as stimulus into the command processor of the bus controller.  This is done so that
-- each command, after being issued, can be followed up with the requested delay before
-- issuing the next command.  Also, the structure of the stimulus input file contains
-- provisions for different types of stimulus, although only the 'd' and 'b' types are
-- implemented here:
--
--   'b' type = binary bus command with delay
--   'd' type = delay only; no command
--
-- The related module, "sim_uart_control_port" uses the 'u' type:
--
--   'u' type = UART bus command with delay
--
--   DESCRIPTION OF ASYNC_SYSCON DERIVED FUNCTIONALITY
--   -------------------------------------------------
-- This is a state-machine driven parallel 8-bit ASCII character interface to a "Wishbone"
-- type of bus.  It is intended to be used as a "Wishbone system controller"
-- for debugging purposes.  Specifically, the unit allows the user to send
-- text commands to the unit, in order to generate read and
-- write cycles on the Wishbone compatible bus.  The command structure is
-- quite terse and spartan in nature, this is for the sake of the logic itself.
-- Because the menu-driven command structure is supported without the use of
-- dedicated memory blocks (in order to maintain cross-platform portability
-- as much as possible) the menus and command responses were kept as small
-- as possible.  In most cases, the responses from the unit to the user
-- consist of a "newline" and one or two visible characters.  The command
-- structure consists of the following commands and responses:
--
-- Command Syntax              Purpose
-- ---------------             ---------------------------------------
-- w aaaa dddd dddd dddd...    Write data items "dddd" starting at address "aaaa"
--                             using sequential addresses.
--                             (If the data field is missing, nothing is done).
-- w0 aaaa dddd dddd dddd...   Write data items "dddd" at address "aaaa"
--                             without incrementing the address.
--                             (If the data field is missing, nothing is done).
-- f aaaa dddd xx              "Fill": Write data "dddd" starting at address "aaaa"
--                             perform this "xx" times at sequential addresses.
--                             (The quantity field is optional, default is 1).
-- f0 aaaa dddd xx             "Fill": Write data "dddd" starting at address "aaaa"
--                             perform this "xx" times at the same address.
--                             (The quantity field is optional, default is 1).
-- r aaaa xx                   Read data starting from address "aaaa."
--                             Perform this "xx" times at sequential addresses.
--                             (The quantity field is optional, default is 1).
-- r0 aaaa xx                  Read data from address "aaaa."
--                             Perform this "xx" times, using the same address.
--                             (The quantity field is optional, default is 1).
-- i                           Send a reset pulse to the system. (initialize).
--
-- <COMMENT_CHAR>              "Single Line" type Comment token.  Characters
--                             after the token are ignored until <ENTER>.
--                             This enables applications which send
--                             files to the unit to include comments for
--                             display and as an aid to understanding.
--                             The comment token is a constant, change it
--                             to be whatever makes sense!
--
-- Response from               Meaning
-- --------------------------  ---------------------------------------
-- OK                          Command received and performed.  No errors.
-- ?                           Command buffer full, without receiving "enter."
-- C?                          Command not recognized.
-- A?                          Address field syntax error.
-- D?                          Data field syntax error.
-- Q?                          Quantity field syntax error.
-- !                           No "ack_i", or else "err_i" received from bus.
-- B!                          No "bg_i" received from master.
--
-- NOTES on the operation of this unit:
--
-- - The unit generates a command prompt which is "-> ".
-- - Capitalization is not important.
-- - Each command is terminated by the "enter" key (0x0d character).
--   Commands are executed as soon as "enter" is received.
-- - Trailing parameters need not be re-entered.  Their values will
--   remain the same as their previous settings.
-- - Use of the backspace key is supported, so mistakes can be corrected.
-- - The length of the command line is limited to a fixed number of
--   characters, as configured by parameter.
-- - Fields are separated by white space, including "tab" and/or "space"
-- - All numerical fields are interpreted as hexadecimal numbers.
--   Decimal is not supported.
-- - Numerical field values are retained between commands.  If a "r" is issued
--   without any fields following it, the previous values will be used.  A
--   set of "quantity" reads will take place at sequential addresses.
--   If a "f" is issued without any fields following it, the previous data
--   value will be written "quantity" times at sequential addresses, starting
--   from the next location beyond where the last command ended.
-- - If the user does not wish to use "ack" functionality, simply tie the
--   "ack_i" input to logic 1, and then the ! response will never be generated.
-- - The data which is read in by the "r" command is displayed using lines
--   which begin with the address, followed by the data fields.  The number
--   of data fields displayed per line (following the address) is adjustable
--   by setting a parameter.  No other display format adjustments can be made.
-- - There is currently only a single watchdog timer.  It begins to count at
--   the time the "enter" is received to execute a command.  If the bus is granted
--   and the ack is received before the expiration of the timer, then the
--   cycle will complete normally.  Therefore, the watchdog timeout value
--   needs to include time for the request and granting of the bus, in
--   addition to the time needed for the actual bus cycle to complete.
--
--
-- Currently, there is only a single indicator (stb_o) generated during bus
-- output cycles which are generated from this unit.
-- The user can easily implement decoding logic based upon adr_o and stb_o
-- which would serve as multiple "stb_o" type signals for different cores
-- which would be sharing the same bus.
--
-- The data bus supported by this module is separate input/output type of bus.
-- However, if a single tri-state dat_io bus is desired, it can be added
-- to the module without too much trouble.  Supposedly the only difference
-- between the two forms of data bus is that one of them avoids using tri-state
-- at the cost of doubling the number of interconnects used to carry data back
-- and forth...  Some people say that tri-state should be avoided for use
-- in internal busses in ASICs.  Maybe they are right.
-- But in FPGAs tri-state seems to work pretty well, even for internal busses.
--
-- Parameters are provided to configure the width of the different command
-- fields.  To simplify the logic for binary to hexadecimal conversion, these
-- parameters allow adjustment in units of 1 hex digit, not anything smaller.
-- If your bus has 10 bits, for instance, simply set the address width to 3
-- which produces 12 bits, and then just don't use the 2 msbs of address
-- output.
--
-- No support for the optional Wishbone "retry" (rty_i) input is provided at
-- this time.
-- No support for "tagn_o" bits is provided at this time, although a register
-- might be added external to this module in order to implement to tag bits.
-- No BLOCK or RMW cycles are supported currently, so cyc_o is equivalent to
-- stb_o...
-- The output busses are not tri-stated.  The user may add tri-state buffers
-- external to the module, using "stb_o" to enable the buffer outputs.
--
---------------------------------------------------------------------------------------
 
library IEEE ;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
 
library std ;
use std.textio.all;
 
library work;
use work.function_pack.all;
use work.sim_support_pack.all;
use work.async_syscon_pack.all;
 
entity sim_bus_control_port is
  generic (
    -- relating to file I/O
    INPUT_FILE      : string  := ".\bus_sim_in.txt";
    OUTPUT_FILE     : string  := ".\bus_sim_out.txt";
    POR_DURATION    :   time  :=    500 ns;  -- Duration of internal reset signal activity
    POR_ASSERT_LOW  : boolean :=     false;  -- Determines polarity of reset output
    CLKRATE         : integer := 100000000;  -- Control Port clock rate default.
    LINE_LENGTH     : integer :=        40;  -- Length of buffer to hold file input bytes
    -- relating to the bus controller
    ADR_DIGITS      : natural :=         4; -- # of hex digits for address
    DAT_DIGITS      : natural :=         4; -- # of hex digits for data
    QTY_DIGITS      : natural :=         2; -- # of hex digits for quantity
    CMD_BUFFER_SIZE : natural :=        32; -- # of chars in the command buffer
    WATCHDOG_VALUE  : natural :=       200; -- # of sys_clks before ack is expected
    DISPLAY_FIELDS  : natural :=         8  -- # of fields/line
  );
  port(
    -- Clock and reset stimulus
    test_rst : out std_logic;  -- Programmable polarity
    test_clk : out std_logic;  -- Programmable frequency
 
    -- System Bus IO
    ack_i    : in  std_logic;
    err_i    : in  std_logic;
    dat_i    : in  unsigned(4*DAT_DIGITS-1 downto 0);
    dat_o    : out unsigned(4*DAT_DIGITS-1 downto 0);
    rst_o    : out std_logic;
    stb_o    : out std_logic;
    cyc_o    : out std_logic;
    adr_o    : out unsigned(4*ADR_DIGITS-1 downto 0);
    we_o     : out std_logic
  );
end sim_bus_control_port;
 
architecture beh of sim_bus_control_port is
-- File I/O Constants
constant BS_CHAR_U : unsigned(7 downto 0) := str2u("08",8);
constant CR_CHAR_U : unsigned(7 downto 0) := str2u("0D",8);
constant LF_CHAR_U : unsigned(7 downto 0) := str2u("0A",8);
 
-- File I/O Signals
-------------------
---- State Machine
TYPE   TST_STATE_TYPE IS (IDLE, CMD_CHAR_OP);
signal tst_state        : TST_STATE_TYPE;
 
---- Stimulus related signals
type   cmd_bytes_array is array (integer range 0 to LINE_LENGTH-1) of unsigned(7 downto 0);
signal cmd_bytes    : cmd_bytes_array;
signal cmd_byte_cnt : integer := 0;
signal tx_length    : integer;
signal new_stim     : boolean := false;
signal stim_kind    : character;
 
-- Internal signals
signal ctlr_test_clk_i  : std_logic := '0';
signal nhreset_internal : std_logic := '0';
 
-- System Controller Signals
signal cmd_char         : unsigned(7 downto 0);
signal cmd_we           : std_logic;
signal cmd_ack          : std_logic;
signal cmd_echo         : std_logic;
signal resp_char        : unsigned(7 downto 0);
signal resp_cyc         : std_logic;
signal resp_ack         : std_logic;
 
---------------------------------------------------------------------------------------
begin
 
-- File I/O Logic Statements
 
  test_clk    <= ctlr_test_clk_i;
 
  -------------------------
  -- Controller Clock Process
  -- Generates the Control Port clock
  ctlr_clk : process
    variable PS_PER_SECOND : real := 1.0E+12;
    variable half_period : time := integer(PS_PER_SECOND/(2.0*real(CLKRATE))) * 1 ps;
  begin
     --wait for 1/2 of the clock period;
     wait for half_period;
     ctlr_test_clk_i <= not (ctlr_test_clk_i);
  end process;
 
-------------------------
-- Reset Process
-- Causes reset to go inactive after a given time.
  rst_gen : process
  begin
    wait for POR_DURATION; -- Maybe wait long enough for the PLL to lock...
    nhreset_internal <= '1';
  end process;
  test_rst <= nhreset_internal when (POR_ASSERT_LOW) else not nhreset_internal;
 
-------------------------
-- Stimulus Process
-- Reads text input file and forms stimulus needed for the simulation.
  stim_proc: process(ctlr_test_clk_i, nhreset_internal)
    file s_file : text is in INPUT_FILE;
    variable time_mark    : time := 0 ns; -- Last NOW time when file IO was parsed
    variable time_val     : time := 0 ns; -- Relative time of next file IO parsing.
    variable line_1       : line;
    variable line_2       : line;
    variable item_count   : integer;
    variable line_num     : integer;
    variable line_done    : boolean;
    variable stim_done    : boolean;
    variable good         : boolean;
    variable temp_char    : character;
    variable stim_kind_v  : character; -- variable version readable immediately in display_stim
    variable cmd_found    : boolean;
 
    -- returns true is the character is a valid hexadecimal character.
    function is_hex(c : character) return boolean is
    begin
      case c is
        when '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
             'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 
             'e' | 'f' =>
          return(true);
        when others =>
          return(false);
      end case;
    end is_hex;
 
    -- This prints the time and type of stimulus
    procedure display_stim is
    begin
      if (temp_char/='-') then
        write (line_2, string'(" [line "));
        write (line_2, line_num);
        write (line_2, string'(", at "));
        write (line_2, now, unit => ns);
        write (line_2, string'("]"));
        writeline (output, line_2);
      end if;
    end display_stim;
 
  begin
    if (nhreset_internal='0') then
      tx_length <= 0;
      line_num := 0;
    elsif (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      -- Default Values
      new_stim <= false;
      if (tst_state/=IDLE) then
        new_stim <= false;
      end if;
      -- Simulation Stimulus
      if (NOW > (time_val+time_mark)) then
        if not(endfile(s_file)) then
          readline(s_file, line_1);
          line_num := line_num+1;
          stim_done  := false;
          cmd_found  := false;
          item_count := 0;
          stim_kind   <= 'z'; -- Default
          stim_kind_v := 'z';
          if (line_1'length=0) then
            line_done := true;
          else
            line_done  := false;
          end if;
          while (line_done = false) loop
            read(line_1, temp_char, good);
            if (temp_char = '-' or temp_char = ';') then
              line_done := true;
            elsif (item_count=0 and temp_char/=' ') then
              stim_kind   <= temp_char;
              stim_kind_v := temp_char; -- Display stim uses this.  It cannot read stim_kind immediately.
              if (stim_kind_v='b') then
                write (line_2, string'("Bus Command: "));
              elsif (stim_kind_v='d') then
                write (line_2, string'("Bus delay token. "));
              else
                write (line_2, string'("Bus unknown stimulus type encountered. No Action. "));
              end if;
              item_count  := item_count+1;
            elsif (item_count=1) then -- Time field read removes leading whitespace automatically.
              time_val := 0 ns;
              read(line_1, time_val);
              time_mark := NOW;
              item_count := item_count+1;
            end if;
            if (stim_kind_v='b') then
              if (item_count>1 and not line_done) then
                if (cmd_found) then
                  cmd_bytes(item_count-2) <= asciichar2u(temp_char);
                  write(line_2, temp_char); -- Keep record of cmd characters for display
                  item_count := item_count+1;
                else
                  if not is_space(temp_char) then
                    cmd_found := true;
                    cmd_bytes(item_count-2) <= asciichar2u(temp_char);
                    write(line_2, temp_char); -- Keep record of cmd characters for display
                    item_count := item_count+1;
                  end if;
                end if;
              elsif (item_count>1 and temp_char=';') then
                cmd_bytes(item_count-2) <= CR_CHAR_U;
                item_count := item_count+1;
              end if;
            end if;
            if (good=false) then
              line_done := true;
            end if;
          end loop;
          if (stim_kind_v='b') then
            tx_length <= item_count-2;
            new_stim <= true;
          end if;
          display_stim;
        elsif not (stim_done) then
          write (line_2, string'("At "));
          write (line_2, now, unit => ns);
          write (line_2, string'(", Bus control port finished reading stimulus file. "));
          writeline (output, line_2);
          stim_done := true;
        end if;
      end if;
    end if;
 
  end process;
 
-------------------------
-- Response Record Process
  response_proc: process(ctlr_test_clk_i)
    file o_file : text is out OUTPUT_FILE;
    variable line_1       : line;
    variable line_2       : line;
    variable good         : boolean;
    variable header_done  : boolean := false;
 
  begin
    if not header_done then
      write (line_2, string'("Simulation Results File"));
      writeline (o_file, line_2);
      header_done := true;
    end if;
    if (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      if (cmd_echo='1' and cmd_ack='1') then
        if (cmd_char=BS_CHAR_U) then
          write (line_2, string'("<BS>"));
        elsif (cmd_char=CR_CHAR_U) then
          write (line_2, string'("<CR>"));
        elsif (cmd_char=LF_CHAR_U) then
          write (line_2, string'("<LF>"));
          writeline (o_file, line_2);
        else
--          write (line_2, u2string(cmd_char,2)); -- For Hexadecimal output
          write (line_2, u2asciichar(cmd_char)); -- For ASCII output
        end if;
      elsif (cmd_echo='0' and resp_ack='1') then
        if (resp_char=BS_CHAR_U) then
          write (line_2, string'("<BS>"));
        elsif (resp_char=CR_CHAR_U) then
          write (line_2, string'("<CR>"));
        elsif (resp_char=LF_CHAR_U) then
          write (line_2, string'("<LF>"));
          writeline (o_file, line_2);
        else
--          write (line_2, u2string(resp_char,2)); -- For Hexadecimal output
          write (line_2, u2asciichar(resp_char)); -- For ASCII output
        end if;
      end if;
    end if;
 
  end process;
 
  resp_ack <= resp_cyc;
 
-------------------------
-- Control Port State Machine
  cp_fsm_proc: process(ctlr_test_clk_i, nhreset_internal)
  begin
    if (nhreset_internal='0') then
      tst_state      <= IDLE;
      cmd_byte_cnt   <= 0;
    elsif (ctlr_test_clk_i'event and ctlr_test_clk_i = '1') then
      -- Default Values
 
      -- State machine
      case tst_state is
 
        when IDLE =>
          cmd_byte_cnt <= 0;
          if (new_stim) then
            if (stim_kind='b') then
              tst_state <= CMD_CHAR_OP;
            end if;
          end if;
 
        when CMD_CHAR_OP => -- Send Command Character
          if (cmd_ack='1') then
            cmd_byte_cnt <= cmd_byte_cnt+1;
          else
            cmd_byte_cnt <= 0;
            tst_state <= IDLE;
          end if;
 
      end case;
    end if;                                      -- end if(FPGA_CLK = 1)
  end process;
 
  cmd_char <= cmd_bytes(cmd_byte_cnt);
  cmd_we <= '1' when tst_state=CMD_CHAR_OP and cmd_byte_cnt<tx_length else '0';
 
syscon1 : entity work.ascii_syscon
    generic map(
      ADR_DIGITS      => ADR_DIGITS, -- # of hex digits for address
      DAT_DIGITS      => DAT_DIGITS, -- # of hex digits for data
      QTY_DIGITS      => QTY_DIGITS, -- # of hex digits for quantity
      CMD_BUFFER_SIZE => CMD_BUFFER_SIZE, -- # of chars in the command buffer
      WATCHDOG_VALUE  => WATCHDOG_VALUE, -- # of sys_clks before ack is expected
      DISPLAY_FIELDS  => DISPLAY_FIELDS -- # of fields/line
    )
    port map(
 
      sys_rst_n    => nhreset_internal,
      sys_clk      => ctlr_test_clk_i,
      sys_clk_en   => '1',
 
      -- Parallel ASCII I/O
      cmd_char_i   => cmd_char,
      cmd_we_i     => cmd_we,
      cmd_ack_o    => cmd_ack,
      cmd_echo_o   => cmd_echo,
      resp_char_o  => resp_char,
      resp_cyc_o   => resp_cyc,
      resp_ack_i   => resp_ack,
      cmd_done_o   => open,
 
      -- Master Bus IO
      master_bg_i  => '1',
      master_adr_i => to_unsigned(0,4*ADR_DIGITS),
      master_dat_i => to_unsigned(0,4*DAT_DIGITS),
      master_dat_o => open,
      master_stb_i => '0',
      master_we_i  => '0',
      master_br_o  => open,
 
      -- System Bus IO
      ack_i        => ack_i,
      err_i        => err_i,
      dat_i        => dat_i,
      dat_o        => dat_o,
      rst_o        => rst_o,
      stb_o        => stb_o,
      cyc_o        => cyc_o,
      adr_o        => adr_o,
      we_o         => we_o
    );
 
 
 
end beh;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.