I created a 60 second countdown timer in VHDL and connected it to the 7-seg displays on a nexys3 FPGA boar but it doesn't work. This is a project for my college class.
I'm not really skilled at VHDL or digital electronics at all, but I've managed to put together some code using college materials and a bit of internet. It doesn't work. It starts at 60, goes down to 59, next clock pulse goes to 68, counts down to 59 and back to 68 in a repeating pattern.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity kv_zad is
port(
rst, clk: in std_logic;
an: out std_logic_vector(3 downto 0) := "1100";
seg: inout std_logic_vector(6 downto 0) :="0000000"
);
end kv_zad;
architecture Behavioral of kv_zad is
signal temp_jed: std_logic_vector(3 downto 0);
signal temp_dek: std_logic_vector(3 downto 0);
signal clk_o: std_logic;
signal clk_rf: std_logic;
signal a: std_logic;
begin
s1: entity work.freqGen generic map(100_000_000) port map(clk, clk_o);
s2: entity work.freqGen generic map(500_000) port map(clk, clk_rf);
process(clk_rf)
begin
if (clk_rf'event and clk_rf='1') then
a <= not a;
end if;
end process;
process(rst, clk_o)
begin
if (rst = '0') then
temp_jed <= "0000";
temp_dek <= "0110";
if (clk_o'event and clk_o='1') then
if (temp_jed = "0000" and temp_dek = "0000") then
temp_jed <= "0000";
temp_dek <= "0000";
elsif (temp_jed = "0000") then
temp_dek <= temp_dek - 1;
temp_jed <= "1001";
else
temp_jed <= temp_jed - 1;
end if;
end if;
else
temp_jed <= "0000";
temp_dek <= "0110";
end if;
end process;
with a select
an <= "1110" when '0',
"1101" when '1';
process(temp_jed, temp_dek)
begin
if (a='0') then
case temp_jed is
when "0000" => seg <= "0000001";
when "0001" => seg <= "1001111";
when "0010" => seg <= "0010010";
when "0011" => seg <= "0000110";
when "0100" => seg <= "1101100";
when "0101" => seg <= "0100100";
when "0110" => seg <= "0100000";
when "0111" => seg <= "0001111";
when "1000" => seg <= "0000000";
when "1001" => seg <= "0000100";
when others => seg <= "0110000";
end case;
elsif (a='1') then
case temp_dek is
when "0000" => seg <= "0000001";
when "0001" => seg <= "1001111";
when "0010" => seg <= "0010010";
when "0011" => seg <= "0000110";
when "0100" => seg <= "1101100";
when "0101" => seg <= "0100100";
when "0110" => seg <= "0100000";
when others => seg <= "0110000";
end case;
end if;
end process;
end Behavioral;
the an output controls which of the 4 7-seg displays should be on and seg is the number I want to output to the display. temp_jed are the ones and temp_dek are the tens digits. I don't know why it behaves like it does, I've asked my professor and he said the logic looks fine to him and told me to figure it out. I don't know if I'm making a stupid logic mistake or am I doing something wrong with the syntax and the processes? Any help would be GREATLY appreciated.
There's a missing others choice or expression type conversion missing in the selected signal assignment state targeting
an:IEEE Std 1076-1993
9.5.2 Selected signal assignments
8.8 Case statement
That type conversion can be of the form
with To_bit(a) select... with the conversion function defined in IEEE package std_logic_1164 in lieu of an others choice.Your question is also missing a minimal, complete, and verifiable example demonstrating the problem which here would imply a testbench driving
rstandclkas well as an entity declaration and architecture body for freqGen which would be required to have been analyzed into the working library prior to the component instantiations with the reserved word entity.There's something peculiar about this process:
At first look this doesn't appear synthesis eligible having an asynchronous assignment outside of the clock edge condition that isn't an asynchronous reset. Also note the clock edge condition is evaluated only when reset = '0' in a nested if statement.
A two decade counter comprised of counters temp_jed and temp_dek would have temp_dek only increment when temp_jed is going from "1001" to "000"
The design model (freqGen and the testbench) has been modified to use a slower clock while running for the same time in seconds. The idea is to not store gigabyte range waveform dump files during simulation filled almost entirely with clock transitions. Ideally the generic constants to the two freqGen instances could be fed through generics in kv_zad from the testbench ignoring any slight of hand in freqGen. Also the anode selects can be fed from bits up stream in a single counter used for the decade counters decrement. This would be done by suing a modulo counter for the anode switch rate providing an enable to a ganged modulo counter to get to the decade counter update rate divided by two to get the decade counter update clock. Here the digit refresh rate for the multiplexed anode switched display looks way to high. Your Nexsys 3 userguide should address what's actually needed.
It's also not a good idea to use mode inout ports in the top level entity of a design specification undergoing synthesis.
There's no reason to do arithmetic on std_logic_vector values here. The results aren't output on ports.
The entire genned together model for simulation:
The added generic scale can be removed from the component instantiations. It has a default value of 1.
The model produced a simulation waveform:
This was done using ghdl and gtkwave on a 2020 Macbook Air M1 running MacOS Ventura 13.4, the restrictive SSD size the reason for trying to hold down the waveform dump file sizes. A simulation with a 100 MHz clock was very slow and had a 14 GB waveform dump file size before scaling the clock by 1000. The simulation speed up was also appreciated.