]> git.the-white-hart.net Git - vhdl/commitdiff
Add simulated STM host
authorrs <>
Tue, 11 Nov 2025 20:56:22 +0000 (14:56 -0600)
committerrs <>
Tue, 11 Nov 2025 20:56:22 +0000 (14:56 -0600)
libraries/simulated/dev_stmhost.vhd [new file with mode: 0644]

diff --git a/libraries/simulated/dev_stmhost.vhd b/libraries/simulated/dev_stmhost.vhd
new file mode 100644 (file)
index 0000000..b2876b4
--- /dev/null
@@ -0,0 +1,209 @@
+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;