--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.sim_utility.all;
+
+
+entity stmhost is
+ port (
+ -- Ports to peripheral
+ ifclk: out std_logic;
+ slcs: out std_logic;
+ flaga: out std_logic;
+ flagb: out std_logic;
+ slrd: in std_logic;
+ slwr: in std_logic;
+ sloe: in std_logic;
+ pktend: in std_logic;
+ fifoadr: in std_logic_vector(1 downto 0);
+ db: inout std_logic_vector(7 downto 0);
+
+ -- Values to enqueue/dequeue host-side
+ host_dl_data: in std_logic_vector(7 downto 0); -- Assign to trigger downloading of a byte
+ host_ul_count: in integer -- Assign to expect more upload bytes
+ );
+end stmhost;
+
+
+architecture behavioral of stmhost is
+
+ ----------------------------------------------------------------------------
+ -- Timing constants
+
+ constant T_IFCLK: time := 20.83 ns; -- IFCLK Period
+
+ constant T_SRD: time := 18.7 ns; -- SLRD to Clock Set-up Time
+ constant T_RDH: time := 0 ns; -- SLRD Hold Time
+ constant T_SWR: time := 18.7 ns; -- SLWR to Clock Set-up Time
+ constant T_WRH: time := 0 ns; -- SLWR Hold Time
+ constant T_SPE: time := 14.6 ns; -- PKTEND to Clock Set-up Time
+ constant T_PEH: time := 0 ns; -- Clock to PKTEND Hold Time
+ constant T_SFD: time := 9.2 ns; -- FIFO Data to Clock Set-up Time
+ constant T_FDH: time := 0 ns; -- Clock to FIFO Data Hold Time
+ constant T_SFA: time := 25 ns; -- FIFOADR[1:0] to Clock Set-up Time
+ constant T_FAH: time := 10 ns; -- Clock to FIFOADR[1:0] Hold Time
+
+ constant T_OEON: time := 10.5 ns; -- SLOE Turn-on to FIFO Data Valid
+ constant T_OEOFF: time := 10.5 ns; -- SLOE Turn-off to FIFO Data Hold
+ constant T_XFLG: time := 9.5 ns; -- Clock to FLAGS Output Propagation Delay
+ constant T_XFD_C: time := 11 ns; -- Clock to FIFO Output Propagation Delay
+ constant T_XFD_A: time := 14.3 ns; -- FIFOADR[1:0] to FIFODATA Output Propagation Delay
+
+ ----------------------------------------------------------------------------
+ -- Output value
+
+ shared variable dl_queue: queue_t;
+ shared variable head: integer := 0;
+ shared variable tail: integer := 0;
+
+ signal value: std_logic_vector(7 downto 0);
+ signal zmask_sloe: std_logic;
+
+ ----------------------------------------------------------------------------
+ -- Handshake signalling and bookkeeping
+
+ signal slcs_int: std_logic;
+
+ ----------------------------------------------------------------------------
+ -- Clock generation
+
+ signal ifclk_int: std_logic;
+ signal adr_gate: std_logic; -- For testing fifoadr setup and hold times
+ signal db_gate: std_logic; -- For testing DB setup and hold times
+
+begin
+
+ slcs_int <= '1';
+ slcs <= slcs_int;
+
+ ----------------------------------------------------------------------------
+ -- Output value
+
+ process
+ begin
+ dl_queue := queue_create;
+ wait;
+ end process;
+
+ process (ifclk_int, host_dl_data'quiet, host_ul_count'quiet)
+ variable temp: std_logic_vector(7 downto 0);
+ variable ul_expected: integer := 0;
+ begin
+ -- Host enqueues items to download
+ if not host_dl_data'quiet then
+ report "DL FIFO insert " & integer'image(to_integer(unsigned(host_dl_data)));
+ queue_enq(dl_queue, host_dl_data);
+ value <= queue_peek(dl_queue) after T_XFD_C;
+ end if;
+
+ -- Host sets number of expected upload bytes
+ if not host_ul_count'quiet then
+ report "UL FIFO expect " & integer'image(host_ul_count) & " more bytes";
+ ul_expected := ul_expected + host_ul_count;
+ end if;
+
+ -- Device access
+ if rising_edge(ifclk_int) then
+ -- Device downloads items
+ if slrd = '0' and queue_len(dl_queue) > 0 then
+ report "DL FIFO remove";
+ queue_deq(dl_queue, temp);
+ value <= queue_peek(dl_queue) after T_XFD_C;
+ end if;
+
+ -- Device uploads items
+ if slwr = '0' and ul_expected > 0 then
+ report "STM host received uploaded byte " & integer'image(to_integer(unsigned(db)));
+ ul_expected := ul_expected - 1;
+ end if;
+
+ -- Download queue empty flag
+ if queue_len(dl_queue) = 0 then
+ flaga <= '1' after T_XFLG;
+ else
+ flaga <= '0' after T_XFLG;
+ end if;
+
+ -- Upload queue full flag
+ if ul_expected = 0 then
+ flagb <= '1' after T_XFLG;
+ else
+ flagb <= '0' after T_XFLG;
+ end if;
+ end if;
+ end process;
+
+ e_zmask_sloe: entity work.delay_edges
+ generic map (D_RISE => T_OEOFF, D_FALL => T_OEON)
+ port map (sig_in => sloe, sig_out => zmask_sloe);
+
+ db <= (others => 'Z') when zmask_sloe = '1' else value;
+
+
+ ----------------------------------------------------------------------------
+ -- IFCLK generation
+
+ p_ifclk: process
+ begin
+ ifclk_int <= '1';
+ wait for T_IFCLK / 2;
+ ifclk_int <= '0';
+ wait for T_IFCLK / 2;
+ end process;
+ ifclk <= ifclk_int;
+
+
+ ----------------------------------------------------------------------------
+ -- Timing and usage assertions
+
+ process (slcs_int, slrd, slwr, fifoadr)
+ begin
+ -- Signals are only valid when SLCS asserted
+ if slcs_int = '1' then
+ assert not (slrd = '0' and slwr = '0')
+ report "SLRD and SLWR asserted at the same time"
+ severity error;
+
+ assert fifoadr /= "01" and fifoadr /= "11"
+ report "Invalid FIFOADR value"
+ severity error;
+
+ if slrd = '0' then
+ assert fifoadr = "00"
+ report "Reading from non-download FIFO"
+ severity error;
+ end if;
+
+ if slwr = '0' then
+ assert fifoadr = "10"
+ report "Writing to non-upload FIFO"
+ severity error;
+ end if;
+ end if;
+ end process;
+
+ e_setuphold_slrd: entity work.assert_setuphold
+ generic map (LEVEL => '1', T_SETUP => T_SRD, T_HOLD => T_RDH, NAME_REF => "IFCLK", NAME_SIG => "SLRD")
+ port map (ref => ifclk_int, sig => slrd, gate => slcs_int);
+
+ e_setuphold_slwr: entity work.assert_setuphold
+ generic map (LEVEL => '1', T_SETUP => T_SWR, T_HOLD => T_WRH, NAME_REF => "IFCLK", NAME_SIG => "SLWR")
+ port map (ref => ifclk_int, sig => slwr, gate => slcs_int);
+
+ e_setuphold_pktend: entity work.assert_setuphold
+ generic map (LEVEL => '1', T_SETUP => T_SPE, T_HOLD => T_PEH, NAME_REF => "IFCLK", NAME_SIG => "PKTEND")
+ port map (ref => ifclk_int, sig => pktend, gate => slcs_int);
+
+ db_gate <= '1' when sloe = '0' and slcs_int = '1' else '0';
+ e_setuphold_db: entity work.assert_setuphold_vec
+ generic map (LEVEL => '1', T_SETUP => T_SFD, T_HOLD => T_FDH, NAME_REF => "IFCLK", NAME_SIG => "DB")
+ port map (ref => ifclk_int, sig => db, gate => db_gate);
+
+ adr_gate <= '1' when (slrd = '0' or slwr = '0') and slcs_int = '1' else '0';
+ e_setup_adr: entity work.assert_setuphold_vec
+ generic map (LEVEL => '1', T_SETUP => T_SFA, T_HOLD => T_FAH, NAME_REF => "IFCLK", NAME_SIG => "FIFOADR")
+ port map (ref => ifclk_int, sig => fifoadr, gate => adr_gate);
+
+end behavioral;