1
\$\begingroup\$

I have a prototype of a simple monostable multivibrator components like this:

-- Libraries -------------------------------------------------------------------

--! Main library
library ieee;               
    --! std logic components        
    use ieee.std_logic_1164.all;

-- Entity ----------------------------------------------------------------------

--! Monostable multivibrator input and output signals:
--! \image html images/multivib_mono.png
entity entity_multivibmono is
    generic
    (
        --! The \p q and \p nq pulse length is this value x \p clk frequency
        pulse_len   :       natural
    );

    port 
    (   
        --! Clock signal. Events occur on rising edge.
        clk         : in    std_logic;  

        --! Non-inverting trigger input
        a           : in    std_logic;

        --! Inverting trigger input
        na          : in    std_logic;

        --! Active low logic reset input. When asserted, \p q = lo, \p nq = hi
        ncd         : in    std_logic;

        --! Non-inverting pulse output. the pulse level is hi
        q           : out   std_logic;

        --! Inverting pulse output. The pulse level is lo
        nq          : out   std_logic
    );

end entity_multivibmono;

-- Architecture ----------------------------------------------------------------

--! Monostable multivibrator implementation
architecture arch_multivibmono of entity_multivibmono is

    --! Enumeration tame for the finite state machine
    type state_t is (st_idle, st_pulse);

    --! A \p state_t instance
    signal st_current   :   state_t;

    --! Buffer signal for q output
    signal q_tmp        :   std_logic;

begin

    --! Multivibrator behavioral process
    process_multivibmono : process(clk, ncd, a, na)

        --! Counter variable 
        variable cnt    :   natural range 0 to pulse_len := 0;

        begin
            if (ncd = '0') then
                q_tmp <= '0';
                cnt := 0;
                st_current <= st_idle;

            elsif (falling_edge(na) or rising_edge(a)) then
                if ((a = '0') and (na = '1')) then
                    q_tmp <= '1'; -- beginning of the pulse
                    st_current <= st_pulse;
                    cnt := 0;
                end if;

            elsif (rising_edge(clk)) then
                case st_current is
                    when st_pulse =>
                        if (cnt < pulse_len) then
                            cnt := cnt + 1;
                        else
                            q_tmp <= '0'; -- end of the pulse
                            cnt := 0;
                            st_current <= st_idle;
                        end if;
                    when others => -- unexpected case
                        q_tmp <= '0';
                        cnt := 0;
                        st_current <= st_idle;
                end case;
            end if;
    end process;

    q <= q_tmp;
    nq <= not q_tmp;

end arch_multivibmono;

Please notice how this code part:

q_tmp <= '0';
cnt := 0;
st_current <= st_idle;

Occurs 3 times in the code. Is there a way in VHDL to encapsulate this somehow easily? I would appreciate all help.

\$\endgroup\$
  • \$\begingroup\$ You can have a look at VHDL procedures. Quote from Xilinx "procedures provide the ability to execute common pieces of code from several different places in a model." \$\endgroup\$ – Remco Vink Nov 9 '18 at 8:17
  • \$\begingroup\$ The thing is procedure requires input parameters. It cannot operate on the signals or variables defined within the architecture body. I fear this would only make the code more complicated instead of cleaning it up. \$\endgroup\$ – Bremen Nov 9 '18 at 8:34
  • \$\begingroup\$ Procedures can use signals defined in the architecture or a port. Procedures are always impure and allow side-effect programming (not recommended). You can specify sub-program parameters of class signal, constant or variable. The latter one can not be used if you want to call the procedure concurrently. \$\endgroup\$ – Paebbels Nov 9 '18 at 10:21
0
\$\begingroup\$

This code has many problems other than how "pretty" it is.

You are controlling signals based on edges on multiple signals, which is not synthesizable.

But to address your actual question — why do you have so many state variables for a simple multivibrator in the first place? For example, having both st_current and q_tmp is completely redundant; they always change in lock-step. And both of those variables could be eliminated by simply checking to see whether cnt is zero or not.

For example, you could change the last two lines to:

q  <= '0' when cnt = 0 else '1';
nq <= '1' when cnt = 0 else '0';
\$\endgroup\$
  • \$\begingroup\$ Hi, yes the code is ready yet. As for the q_tmp, is serves only as way of not having to assign q and nq everywhere. \$\endgroup\$ – Bremen Nov 9 '18 at 12:44
  • \$\begingroup\$ The point is, you could assign both q and nq based on st_current without introducing a redundant variable. \$\endgroup\$ – Dave Tweed Nov 9 '18 at 12:51
  • \$\begingroup\$ But this way there would be more line of code, since each time instead of assigning q_mp, I would have to assign q and nq \$\endgroup\$ – Bremen Nov 9 '18 at 13:00
  • \$\begingroup\$ Could you show in code what you have in mind for an optimal monostable multivibrator? \$\endgroup\$ – Bremen Nov 9 '18 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.