simple line drive generator doesn't work properly
Started by 6 years ago●3 replies●latest reply 6 years ago●56 viewsHi 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
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.
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!
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 :)