0

I am trying to build a pulse generator that consists of two pulse generators driven by a mod-m counter. The counter loops through a cycle with a set time, and whenever it hits some specified times, the pulse generators will generate short, square wave pulses at those times.

This works in simulation, but when I implement this in my FPGA board, it will successfully run through one cycle of the square wave pulses, but then get stuck as if the counter is permanently stuck at 0 (outputs myag_q and byag_q are stuck at 0 and byag_l,myag_l are stuck at 1). I have simulated the counter by itself and know that it continues looping between 0 and M.

The code for the top-level module, mod-m counter and a pulse generator are listed below. The other pulse generator is very similar to the first. No need to check my user constraints file, because I'm sure I got the pin assignments correctly. I need a general idea of whether I have made any big mistakes in combining these modules/whether the last program (the pulse generator) is written correctly. Most importantly, I need to know if the way I'm using the counter to trigger pulses is correct.

Top-Level Module

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity trigger is
    Port ( clk, rst : in  STD_LOGIC;
              d: in STD_LOGIC_VECTOR(25 downto 0);
           myag_l, myag_q, byag_l, byag_q : out  STD_LOGIC);
end trigger;

architecture struc_arch of trigger is
signal counter: STD_LOGIC_VECTOR (25 downto 0);
begin

mini_yag: entity work.mini_yag(Behavioral)
port map(clk=>clk,rst=>rst,count=>counter,myag_l=>myag_l,myag_q=>myag_q);
big_yag: entity work.big_yag(Behavioral)
port map(clk=>clk,rst=>rst,d=>d,count=>counter,byag_l=>byag_l,byag_q=>byag_q);
baud: entity work.mod_m_counter(arch)
generic map(N=>26,M=>6434344)
port map(clk=>clk,reset=>rst,max_tick=>open,q=>counter);

end struc_arch;

Mod-M Counter

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity mod_m_counter is
     generic (
        N: integer := 4; -- number of bits
        M: integer := 10 -- mod-M
     );
    Port ( clk, reset : in  STD_LOGIC;
           max_tick : out  STD_LOGIC;
           q : out  STD_LOGIC_VECTOR (N-1 downto 0));
end mod_m_counter;

architecture arch of mod_m_counter is
    signal r_reg: unsigned (N-1 downto 0);
    signal r_next: unsigned (N-1 downto 0);
begin
    --register
    process(clk,reset)
    begin
        if (reset='1') then
            r_reg <= (others=>'0');
        elsif (clk'event and clk='1') then
            r_reg <= r_next;
        end if;
    end process;
    --next-state logic
    r_next <= (others=>'0') when r_reg=(M-1) else
                 r_reg + 1;
    --output logic
    q <= std_logic_vector(r_reg);
    max_tick <= '1' when r_reg=(M-1) else '0';
end arch;

A Pulse Generator

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity big_yag is
generic(
T1: unsigned :=to_unsigned(0,26); --Lamp On
T2: unsigned :=to_unsigned(138889,26); --Lamp Off
T3: unsigned :=to_unsigned(4305555,26); --Q-switch On
T4: unsigned :=to_unsigned(4343434,26); --Q-switch Off
T5: unsigned :=to_unsigned(6434343,26)  --Reset Sequence
);
Port( 
clk,rst : in STD_LOGIC;
d,count: in STD_LOGIC_VECTOR(25 downto 0);
byag_l,byag_q : out STD_LOGIC
);
end big_yag;

architecture Behavioral of big_yag is
signal delay,counter: unsigned (25 downto 0);
signal byag_l_reg,byag_l_next,byag_q_reg,byag_q_next: std_logic;
begin
delay <= unsigned(d);
counter <= unsigned(count);

--register
process(rst,clk)
begin
if rst='1' then
    byag_l_reg <= '0';
    byag_q_reg <= '0';
elsif (clk='1' and clk'event) then
    byag_l_reg <= byag_l_next;
    byag_q_reg <= byag_q_next;
end if;
end process;

--next state logic
byag_l_next <= '1' when counter = T1+delay else
               '0' when counter = T2+delay else
               byag_l_reg;
byag_q_next <= '0' when counter = T1+delay else
               '1' when counter = T3+delay else
               '0' when counter = T4+delay else
               byag_q_reg;

--output logic
byag_l <= byag_l_reg;
byag_q <= byag_q_reg;

end Behavioral;
Eugene Wu
  • 61
  • 8
  • My only comments would be : (1) My opinion : separating functionality into too many small processes (_next and _reg) serves only to increase code size, complexity, difficulty of understanding and scope for unreliability (2) Use of magic numbers (643434) increases scope for surprises : define constants in a package and use it consistently (3) Some unnecessary conversions would be avoided by better choice of types : e.g. Unsigned or even Natural for counter ports (4) If your pulse generators are so similar, why aren't you re-using one component? –  Jul 09 '15 at 09:36
  • and (5) "No need to check xxx ..." famous last words? –  Jul 09 '15 at 09:37
  • Thanks for the advice. Regarding (1), what alternative to _next and _reg could I use? The textbook I'm reading from exclusively used this set-up for FSM designs (separating into register, next-state logic, and output logic). – Eugene Wu Jul 09 '15 at 15:51
  • I think I know the textbook... there should be plenty of info about "VHDL single-process state machine" online, including here at Stack Exchange. Here's one I posted recently. –  Jul 09 '15 at 16:02

1 Answers1

0

Mismatches between simulation and reality usually boil down to one or more of the following problems:

  • The test bench does not provide the same stimulus as the real circuit does.
    • Example: Test bench simulates a button press as a simple 1 > 0 > 1 sequence, but a real button will not have such a 'clean' behavior.
  • The design did not pass timing constraints, or the design is not properly constrained.
  • There are race conditions or hazards in the design, caused by problems in the design of unclocked/asynchronous paths.
    • Example: your max_tick signal could glitch when reg_M changes.
  • There are problems with the design of any clock domain crossings.
scary_jeff
  • 4,314
  • 13
  • 27