General > General Technical Chat
VHDL CODE QUESTION
(1/1)
Austin:
Hi ! I'm new to the forum.If I'm doing something wrong,please tell me.
I'm trying to make a 32bit counter in a FPGA.
What I want to do is measure pulse with.
I wrote the code below and came up with a question.
When the rst is 1 FPGA circuitry will try to do TMP<=cnt; and cnt <=X"00000000"; at the same time.
At least that's what I thought.
Whill this code run stably and reliably ?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Top is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
count : out STD_LOGIC_VECTOR(31 downto 0);
hold : out STD_LOGIC_VECTOR(31 downto 0)
);
end Top;
architecture Behavioral of Top is
signal cnt : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
signal TMP : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
begin
process(clk, rst)
begin
if rst = '1' then
TMP<=cnt;
cnt <=X"00000000";
elsif rising_edge(clk) then
cnt <= cnt + 1;
end if;
end process;
count <= cnt;
hold <= TMP;
end Behavioral;
Daixiwen:
This may work in a simulator at first, but on the next clock edge after you put rst to 1 the simulator will execute the process again, go into the if rst = '1' branch, and copy the value of cnt (now 0) into TMP.
In the actual implementation in an FPGA, TMP and cnt will be asynchronously connected together and TMP will continuously read cnt as long as rst = '1' so you will end up with TMP being 0 anyway.
The asynchronous branch with the if rst = '1' should only contain initial values for your signals, that should be applied during a reset. All the rest of the logic should be in the clock part of the process. I would suggest to have a separate 'load' signal to load the counter value, independently to the reset signal.
--- Code: ---entity Top is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
load : in STD_LOGIC;
count : out STD_LOGIC_VECTOR(31 downto 0);
hold : out STD_LOGIC_VECTOR(31 downto 0)
);
end Top;
architecture Behavioral of Top is
signal cnt : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
signal TMP : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
begin
process(clk, rst)
begin
if rst = '1' then
TMP<=X"00000000";
cnt <=X"00000000";
elsif rising_edge(clk) then
if load = '1' then
TMP <= cnt;
cnt <= X"00000000";
else
cnt <= cnt + 1;
end if;
end if;
end process;
count <= cnt;
hold <= TMP;
end Behavioral;
--- End code ---
A few other suggestions:
* avoid using STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED. Those are non standard packages, and will cause confusion if you ever need to mix unsigned and signed vector. Use NUMERIC_STD instead and the dedicated signed and unsigned types instead of std_logic_vector to make counters.
* if your 'load' pulse signal is external to the FPGA and not synchronized with the clock, you will need to register it a couple of times to avoid metastability problems. If you google "metastability filter" you should find some good articles on why this is necessary and how to implement them.EDIT: sorry I only noticed after I replied that the OP double posted his question
Navigation
[0] Message Index
Go to full version