FPGARelated.com
Forums

simple line drive generator doesn't work properly

Started by ombz 6 years ago3 replieslatest reply 6 years ago56 views

Hi guys

I don't have any real-world experience with synthesizable VHDL and FPGA's but I've been really curious about it for a long time. So I've found an old experimenter's board at home and thought I'd give it a try. It's a Digilent Nexsys2 featuring a Xilinx Spartan 3E. I am using Xilinx PlanAhead 14.7.

I've managed to write some VHDL code to "statically" check all the basic user I/O's on the board: buttons, sliders, LED's and 7-segment display. So far so good.

What I ultimately wish to do:

(1) generate a clock signal CLKP with frequency Fp
(2) count the number of periods (or "pulses") of CLKP
(3) use CLKP as input of an 1:8 demultiplexer connected to an 8-bit output bus; all outputs are connected to '0' expected the one selected by 3-bit selection SEL
(4) every N pulses of CLKP, the selection of the demultiplexer shall be incremented by 1, i.e. the CLKP will jump to the next output line (and wrap over to OUT[0] from OUT[7])

So far I don't use any simulation tools because I've thought I could directly debug stuff using the board. Currently, steps (1) and (3) seem to work independently, but not step (2) and I can't figure out why. Step (4) is linked to step (2), so this fails as well. I feel like there might be something fundamental I don't understand at this moment that's why I post here. I hope you guys can help out -- as this must be very basic stuff to you. :) The signal names above don't exactly correspond to the names in the VHDL code for "readability" of this post.

For simplicity, here's not the whole code, but just the one where I can reproduce a problem with step (2) easily. On the LED array I would expect a sequence like:

"00000000"
"00000001"
"00000010"
"00000011"
"00000100"
etc.

The observed sequence is quite different and somehow random.

entity main is

    Port (

        leds : OUT std_logic_vector(7 downto 0);
        reset : IN std_logic;
        clk : IN std_logic
    );

end main;


architecture behavioral of main is

    -- hi-freq counter @clk freq = 50 MHz
    signal clk_count_d : integer;
    signal clk_count_rst : std_logic;

    -- low-freq counter @approx. one second period
    constant clk_count_rst_period : integer := 25000000; -- toggle @2 Hz
    signal lofreq_clk : std_logic;
    signal lofreq_clk_count_d : unsigned(7 downto 0);

begin

    -- hi-freq
    process (clk, reset, clk_count_rst)
    begin
        if (reset='1' or clk_count_rst='1') then
            clk_count_d <= 0;
        elsif (clk'event and clk='1') then
            clk_count_d <= clk_count_d + 1;
        end if;
    end process;

    -- lo-freq
    process (clk_count_d, reset)
    begin
        if (reset='1') then
            lofreq_clk <= '0';
            clk_count_rst <= '1';
            lofreq_clk_count_d <= x"00";
        elsif (clk_count_d=clk_count_rst_period) then
            lofreq_clk <= not lofreq_clk;
            clk_count_rst <= '1';
            lofreq_clk_count_d <= lofreq_clk_count_d + 1;
        else
            clk_count_rst <= '0';
        end if;
    end process;

    -- output logic
    leds <= std_logic_vector(lofreq_clk_count_d);

end behavioral;


Thanks a lot for your help. Also hints on coding style and general design advises are very welcome. :) For example, I wonder if it's a good thing to use "integer" and what is the synthesized representation of that integer? Is it unsigned 32 bits? How does the synthesizer figure out what to make out of an integer? Would it be better to use signed/unsigned/std_logic[_vector] wherever possible?

Have a nice Sunday!

-Andy


[ - ]
Reply by martinthompsonAugust 7, 2018

Your second process does not match the synchronous template that the tools expect , so all bets are off.


If you make your second process synchronous to your fast clock, and put the 

elsif (clk_count_d=clk_count_rst_period) then

bit inside an "if rising_edge(clk) then" clause, you'll then have a synchronous process that the tools should be able to synthesise OK for you.


[ - ]
Reply by ombzAugust 7, 2018

Oh yeah totally! Things are working now. And something new I've learned. :) Also figured I could pack in the whole counting at low freq within the fast clock process (why didn't think of this in the first place?); but this seems to be the less efficient solution as the max clock freq considerably dropped even though it's still far above the clock freq I'm using.

Thanks a lot for your help!


[ - ]
Reply by martinthompsonAugust 7, 2018

If you are still using signals for the low-speed counter your fmax should still be the same.  Putting the counter description in the process still describes the same hardware.  If you've used variables then depending on whether you update the variable before or after you test it, you'll get different fmax (and 0 or 1 additional cycles of delay)

Either way you are not describing the same hardware as your first attempt... I always find working code goes slower than non-working code - it seems to be a price I have to pay :)