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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [rtl/] [sys_gen/] [tst_serloop/] [tb/] [tb_tst_serloop.vhd] - Rev 40

Go to most recent revision | Compare with Previous | Blame | View Log

-- $Id: tb_tst_serloop.vhd 476 2013-01-26 22:23:53Z mueller $
--
-- Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name:    tb_tst_serloop - sim
-- Description:    Generic test bench for sys_tst_serloop_xx
--
-- Dependencies:   vlib/simlib/simclkcnt
--                 vlib/serport/serport_uart_rxtx
--                 vlib/serport/serport_xontx
--
-- To test:        sys_tst_serloop_xx
--
-- Target Devices: generic
--
-- Revision History: 
-- Date         Rev Version  Comment
-- 2011-12-23   444   1.1    use new simclkcnt
-- 2011-11-13   425   1.0    Initial version
-- 2011-11-06   420   0.5    First draft
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
 
use work.slvtypes.all;
use work.simlib.all;
use work.serportlib.all;
 
entity tb_tst_serloop is
  port (
    CLKS : in slbit;                    -- clock for serport
    CLKH : in slbit;                    -- clock for humanio
    CLK_STOP : out slbit;               -- clock stop
    P0_RXD : out slbit;                 -- port 0 receive data (board view)
    P0_TXD : in slbit;                  -- port 0 transmit data (board view)
    P0_RTS_N : in slbit;                -- port 0 rts_n
    P0_CTS_N : out slbit;               -- port 0 cts_n
    P1_RXD : out slbit;                 -- port 1 receive data (board view)
    P1_TXD : in slbit;                  -- port 1 transmit data (board view)
    P1_RTS_N : in slbit;                -- port 1 rts_n
    P1_CTS_N : out slbit;               -- port 1 cts_n
    SWI : out slv8;                     -- hio switches
    BTN : out slv4                      -- hio buttons
  );
end tb_tst_serloop;
 
architecture sim of tb_tst_serloop is
 
  signal CLK_STOP_L  : slbit := '0';  
  signal CLK_CYCLE : integer := 0;
 
  signal UART_RESET : slbit := '0';
  signal UART_RXD : slbit := '1';
  signal UART_TXD : slbit := '1';
  signal CTS_N : slbit := '0';
  signal RTS_N : slbit := '0';
 
  signal CLKDIV : slv13 := (others=>'0');
  signal RXDATA : slv8 := (others=>'0');
  signal RXVAL : slbit := '0';
  signal RXERR : slbit := '0';
  signal RXACT : slbit := '0';
  signal TXDATA : slv8 := (others=>'0');
  signal TXENA : slbit := '0';
  signal TXBUSY : slbit := '0';
 
  signal UART_TXDATA : slv8 := (others=>'0');
  signal UART_TXENA : slbit := '0';
  signal UART_TXBUSY : slbit := '0';
 
  signal ACTPORT : slbit := '0';
  signal BREAK : slbit := '0';
 
  signal CTS_CYCLE : integer := 0;
  signal CTS_FRACT : integer := 0;
  signal XON_CYCLE : integer := 0;
  signal XON_FRACT : integer := 0;
 
  signal S2M_ACTIVE : slbit := '0';
  signal S2M_SIZE : integer := 0;
  signal S2M_ENAESC : slbit := '0';
  signal S2M_ENAXON : slbit := '0';
 
  signal M2S_XONSEEN : slbit := '0';
  signal M2S_XOFFSEEN : slbit := '0';
 
  signal R_XONRXOK : slbit := '1';
  signal R_XONTXOK : slbit := '1';
 
begin
 
  CLKCNT : simclkcnt port map (CLK => CLKS, CLK_CYCLE => CLK_CYCLE);
 
  UART : serport_uart_rxtx
    generic map (
      CDWIDTH => 13)
    port map (
      CLK    => CLKS,
      RESET  => UART_RESET,
      CLKDIV => CLKDIV,
      RXSD   => UART_RXD,
      RXDATA => RXDATA,
      RXVAL  => RXVAL,
      RXERR  => RXERR,
      RXACT  => RXACT,
      TXSD   => UART_TXD,
      TXDATA => UART_TXDATA,
      TXENA  => UART_TXENA,
      TXBUSY => UART_TXBUSY
    );
 
  XONTX : serport_xontx
    port map (
      CLK         => CLKS,
      RESET       => UART_RESET,
      ENAXON      => S2M_ENAXON,
      ENAESC      => S2M_ENAESC,
      UART_TXDATA => UART_TXDATA,
      UART_TXENA  => UART_TXENA,
      UART_TXBUSY => UART_TXBUSY,
      TXDATA      => TXDATA,
      TXENA       => TXENA,
      TXBUSY      => TXBUSY,
      RXOK        => R_XONRXOK,
      TXOK        => R_XONTXOK
    );
 
  proc_port_mux: process (ACTPORT, BREAK, UART_TXD, CTS_N,
                          P0_TXD, P0_RTS_N, P1_TXD, P1_RTS_N)
    variable eff_txd : slbit := '0';
  begin
 
    if BREAK = '0' then                 -- if no break active
      eff_txd := UART_TXD;                -- send uart
    else                                -- otherwise
      eff_txd := '0';                     -- force '0'
    end if;
 
    if ACTPORT = '0' then               -- use port 0
      P0_RXD   <= eff_txd;                -- write port 0 inputs
      P0_CTS_N <= CTS_N;
      UART_RXD <= P0_TXD;                 -- get port 0 outputs
      RTS_N    <= P0_RTS_N;
      P1_RXD   <= '1';                    -- port 1 inputs to idle state
      P1_CTS_N <= '0';
    else                                -- use port 1
      P1_RXD   <= eff_txd;                -- write port 1 inputs
      P1_CTS_N <= CTS_N;
      UART_RXD <= P1_TXD;                 -- get port 1 outputs
      RTS_N    <= P1_RTS_N;
      P0_RXD   <= '1';                    -- port 0 inputs to idle state
      P0_CTS_N <= '0';
    end if;
  end process proc_port_mux;
 
  proc_cts: process(CLKS)
    variable cts_timer : integer := 0;
  begin
 
    if rising_edge(CLKS) then    
      if CTS_CYCLE = 0 then               -- if cts throttle off
        CTS_N <= '0';                       -- cts permanently asserted
 
      else                                -- otherwise determine throttling
 
        if cts_timer>0 and cts_timer<CTS_CYCLE then  -- unless beyond ends
          cts_timer := cts_timer - 1;                  -- decrement
        else
          cts_timer := CTS_CYCLE-1;                    -- otherwise reload
        end if;
 
        if cts_timer < cts_fract then     -- if in lower 'fract' counts
          CTS_N <= '1';                     -- throttle: deassert CTS
        else                              -- otherwise
          CTS_N <= '0';                     -- let go: assert CTS
        end if;
 
      end if;
    end if;
 
  end process proc_cts;
 
  proc_xonrxok: process(CLKS)
    variable xon_timer : integer := 0;
  begin    
    if rising_edge(CLKS) then
      if XON_CYCLE = 0 then               -- if xon throttle off
        R_XONRXOK <= '1';                   -- xonrxok permanently asserted
 
      else                                -- otherwise determine throttling
 
        if xon_timer>0 and xon_timer<XON_CYCLE then  -- unless beyond ends
          xon_timer := xon_timer - 1;                  -- decrement
        else
          xon_timer := XON_CYCLE-1;                    -- otherwise reload
        end if;
 
        if xon_timer < xon_fract then     -- if in lower 'fract' counts
          R_XONRXOK <= '0';                 -- throttle: deassert xonrxok
        else                              -- otherwise
          R_XONRXOK <= '1';                 -- let go: assert xonrxok
        end if;
 
      end if;
    end if;
  end process proc_xonrxok;
 
  proc_xontxok: process(CLKS)
  begin    
    if rising_edge(CLKS) then
      if M2S_XONSEEN = '1' then
        R_XONTXOK <= '1';
      elsif M2S_XOFFSEEN = '1' then
        R_XONTXOK <= '0';
      end if;
    end if;
  end process proc_xontxok;
 
  proc_stim: process
    file fstim : text open read_mode is "tb_tst_serloop_stim";
    variable iline : line;
    variable oline : line;
    variable idelta : integer := 0;
    variable iactport : slbit := '0';
    variable iswi : slv8 := (others=>'0');
    variable btn_num : integer := 0;
    variable i_cycle : integer := 0;
    variable i_fract : integer := 0;
    variable nbyte : integer := 0;
    variable enaesc : slbit := '0';
    variable enaxon : slbit := '0';
    variable bcnt : integer := 0;
    variable itxdata : slv8 := (others=>'0');
    variable ok : boolean;
    variable dname : string(1 to 6) := (others=>' ');
 
    procedure waitclk(ncyc  : in integer) is
    begin 
     for i in 1 to ncyc loop
       wait until rising_edge(CLKS);
     end loop;  -- i
    end procedure waitclk;
 
  begin
 
    -- initialize some top level out signals
    SWI <= (others=>'0');
    BTN <= (others=>'0');
 
    wait until rising_edge(CLKS);
 
    file_loop: while not endfile(fstim) loop
 
      readline (fstim, iline);
 
      readcomment(iline, ok);
      next file_loop when ok;
 
      readword(iline, dname, ok);
      if ok then
        case dname is
          when "wait  " =>              -- wait  
            read_ea(iline, idelta);
            writetimestamp(oline, CLK_CYCLE, ": wait  ");
            write(oline, idelta, right, 5);
            writeline(output, oline);
            waitclk(idelta);
 
          when "port  " =>              -- switch rs232 port
            read_ea(iline, iactport);
            ACTPORT <= iactport;
            writetimestamp(oline, CLK_CYCLE, ": port  ");
            write(oline, iactport, right, 5);
            writeline(output, oline);             
 
          when "cts   " =>              -- setup cts throttling
            read_ea(iline, i_cycle);
            read_ea(iline, i_fract);
            CTS_CYCLE <= i_cycle;
            CTS_FRACT <= i_fract;
            writetimestamp(oline, CLK_CYCLE, ": cts   ");
            write(oline, i_cycle, right, 5);
            write(oline, i_fract, right, 5);
            writeline(output, oline);             
 
          when "xon   " =>              -- setup xon throttling
            read_ea(iline, i_cycle);
            read_ea(iline, i_fract);
            XON_CYCLE <= i_cycle;
            XON_FRACT <= i_fract;
            writetimestamp(oline, CLK_CYCLE, ": cts   ");
            write(oline, i_cycle, right, 5);
            write(oline, i_fract, right, 5);
            writeline(output, oline);             
 
          when "swi   " =>              -- new SWI settings
            read_ea(iline, iswi);
            read_ea(iline, idelta);
            writetimestamp(oline, CLK_CYCLE, ": swi   ");
            write(oline, iswi, right, 10);
              write(oline, idelta, right, 5);
            writeline(output, oline);             
            wait until rising_edge(CLKH);
            SWI <= iswi;
            wait until rising_edge(CLKS);
            waitclk(idelta);
 
          when "btn   " =>              -- BTN push (3 cyc down + 3 cyc wait)
            read_ea(iline, btn_num);
            read_ea(iline, idelta);
            if btn_num>=0 and btn_num<=3 then
              writetimestamp(oline, CLK_CYCLE, ": btn   ");
              write(oline, btn_num, right, 5);
              write(oline, idelta, right, 5);
              writeline(output, oline);                           
              wait until rising_edge(CLKH);
              BTN(btn_num) <= '1';      -- 3 cycle BTN pulse
              wait until rising_edge(CLKH);
              wait until rising_edge(CLKH);
              wait until rising_edge(CLKH);
              BTN(btn_num) <= '0';
              wait until rising_edge(CLKH);
              wait until rising_edge(CLKH);
              wait until rising_edge(CLKH);
              wait until rising_edge(CLKS);
              waitclk(idelta);
            else
              write(oline, string'("!! btn: btn number out of range"));
              writeline(output, oline);
            end if;
 
          when "expect" =>              -- expect n bytes data
            read_ea(iline, nbyte);
            read_ea(iline, enaesc);
            read_ea(iline, enaxon);
            writetimestamp(oline, CLK_CYCLE, ": expect");
            write(oline, nbyte, right, 5);
            write(oline, enaesc, right, 3);
            write(oline, enaxon, right, 3);
            writeline(output, oline);
 
            if nbyte > 0 then
              S2M_ACTIVE  <= '1';
              S2M_SIZE   <= nbyte;
            else
              S2M_ACTIVE  <= '0';
            end if;
            S2M_ENAESC <= enaesc;
            S2M_ENAXON <= enaxon;
            wait until rising_edge(CLKS);
 
          when "send  " =>              -- send n bytes data
            read_ea(iline, nbyte);
            read_ea(iline, enaesc);
            read_ea(iline, enaxon);
            writetimestamp(oline, CLK_CYCLE, ": send  ");
            write(oline, nbyte, right, 5);
            write(oline, enaesc, right, 3);
            write(oline, enaxon, right, 3);
            writeline(output, oline);
            bcnt := 0;
            itxdata := (others=>'0');
 
            wait until falling_edge(CLKS);
            while bcnt < nbyte loop
              while TXBUSY='1' or RTS_N='1' loop
                wait until falling_edge(CLKS);
              end loop;
 
              TXDATA <= itxdata;
              itxdata := slv(unsigned(itxdata) + 1);
              bcnt   := bcnt + 1;              
 
              TXENA  <= '1';
              wait until falling_edge(CLKS);
              TXENA  <= '0';             
              wait until falling_edge(CLKS);
            end loop;
            while TXBUSY='1' or RTS_N='1' loop -- wait till last char send...
              wait until falling_edge(CLKS);
            end loop;
            wait until rising_edge(CLKS);
 
          when "break " =>              -- send a break for n cycles
            read_ea(iline, idelta);
            writetimestamp(oline, CLK_CYCLE, ": break ");
            write(oline, idelta, right, 5);
            writeline(output, oline);
            -- send break for n cycles
            BREAK <= '1';
            waitclk(idelta);
            BREAK <= '0';
            -- wait for 3 bit cell width
            waitclk(3*to_integer(unsigned(CLKDIV)+1));
            -- send 'sync' character
            wait until falling_edge(CLKS);
            TXDATA <= "10000000";
            TXENA  <= '1';
            wait until falling_edge(CLKS);
            TXENA  <= '0';             
            wait until rising_edge(CLKS);
 
          when "clkdiv" =>              -- set new clock divider
            read_ea(iline, idelta);
            writetimestamp(oline, CLK_CYCLE, ": clkdiv");
            write(oline, idelta, right, 5);
            writeline(output, oline);
            CLKDIV <= slv(to_unsigned(idelta, CLKDIV'length));
            UART_RESET <= '1';
            wait until rising_edge(CLKS);
            UART_RESET <= '0';
 
          when others =>                -- unknown command
            write(oline, string'("?? unknown command: "));
            write(oline, dname);
            writeline(output, oline);
            report "aborting" severity failure;
        end case;
 
      else
        report "failed to find command" severity failure;
 
      end if;
 
      testempty_ea(iline);
    end loop;   -- file_loop
 
    writetimestamp(oline, CLK_CYCLE, ": DONE ");
    writeline(output, oline);
 
    -- extra wait for at least two character times (20 bit times)
    -- to allow tx and rx of the last character
    waitclk(20*(to_integer(unsigned(CLKDIV))+1));
 
    CLK_STOP_L <= '1';
 
    wait for 500 ns;                    -- allows dcm's to stop
 
    wait;                               -- suspend proc_stim forever
                                        -- clock is stopped, sim will end
 
  end process proc_stim;
 
  CLK_STOP <= CLK_STOP_L;
 
  proc_moni: process
    variable oline : line;
    variable dclk : integer := 0;
    variable active_1 : slbit := '0';
    variable irxdata : slv8 := (others=>'0');
    variable irxeff : slv8 := (others=>'0');
    variable irxval : slbit := '0';
    variable doesc : slbit := '0';
    variable bcnt : integer := 0;
    variable xseen : slbit := '0';
  begin
 
    loop 
      wait until falling_edge(CLKS);
 
      M2S_XONSEEN  <= '0';
      M2S_XOFFSEEN <= '0';
 
      if S2M_ACTIVE='1' and active_1='0' then -- start expect message
        irxdata := (others=>'0');
        bcnt := 0;
      end if;
 
      if S2M_ACTIVE='0' and active_1='1' then -- end expect message
        if bcnt = S2M_SIZE then
          writetimestamp(oline, CLK_CYCLE, ": OK: message seen");
        else
          writetimestamp(oline, CLK_CYCLE, ": FAIL: missing chars, seen=");
          write(oline, bcnt, right, 5);
          write(oline, string'("  expect="));
          write(oline, S2M_SIZE, right, 5);
        end if;
        writeline(output, oline);
      end if;
 
      active_1 := S2M_ACTIVE;
 
      if RXVAL = '1' then
        writetimestamp(oline, CLK_CYCLE, ": char: ");
        write(oline, RXDATA, right, 10);
        write(oline, string'(" ("));
        writeoct(oline, RXDATA, right, 3);
        write(oline, string'(") dt="));
        write(oline, dclk, right, 4);
 
        irxeff := RXDATA;
        irxval := '1';
        if doesc = '1' then
          irxeff := not RXDATA;
          irxval := '1';
          doesc  := '0';
          write(oline, string'("  eff="));
          write(oline, irxeff, right, 10);
          write(oline, string'(" ("));
          writeoct(oline, irxeff, right, 3);
          write(oline, string'(")"));
        elsif S2M_ENAESC='1' and RXDATA=c_serport_xesc then
          doesc  := '1';
          irxval := '0';
          write(oline, string'("  XESC seen"));
        end if;
 
        xseen := '0';
        if S2M_ENAXON = '1' then
          if RXDATA = c_serport_xon then
            write(oline, string'("  XON seen"));
            M2S_XONSEEN <= '1';
            xseen := '1';
          elsif RXDATA = c_serport_xoff then
            write(oline, string'("  XOFF seen"));
            M2S_XOFFSEEN <= '1';            
            xseen := '1';
          end if;
        end if;
 
        if S2M_ACTIVE='1' and irxval='1' and xseen='0' then
          if irxeff = irxdata then
            write(oline, string'("  OK"));
          else
            write(oline, string'("  FAIL: expect="));
            write(oline, irxdata, right, 10);
          end if;
          irxdata := slv(unsigned(irxdata) + 1);
          bcnt := bcnt + 1;
        end if;
 
        writeline(output, oline);
        dclk := 0;
 
      end if;
 
      if RXERR = '1' then
        writetimestamp(oline, CLK_CYCLE, ": FAIL: RXERR='1'");
        writeline(output, oline);                   
      end if;
 
      dclk := dclk + 1;
 
    end loop;
 
  end process proc_moni;
 
end sim;
 

Go to most recent revision | 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.