- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I just started with FPGAs and thus I am trying to improve my VHDL skills. Recently I am building a design that generates a pulse which is meant to start a ADC conversion. My idea is to use a counter which controls the pulse length. Unfortunately, the counter seems to start but never reaches the value at which the pulse should end. After several hours of trying I have no clue what is going wrong. May you could have a look at my code. So this is my counter:library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity counter is
generic
(
n : natural := 1
);
port
(
clock : in std_logic;
clock_enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector((n-1) downto 0)
);
end;
architecture behaviour of counter is
signal counter_value : std_logic_vector((n-1) downto 0) := (others => '0');
begin
process(clock, reset)
begin
if (reset = '1') then
counter_value <= (others => '0');
elsif (rising_edge(clock)) then
if (clock_enable = '1') then
counter_value <= counter_value + 1;
end if;
end if;
end process;
output <= counter_value;
end behaviour;
And here is my ADC design file, which uses the counter: library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ti_ads1675 is
port
(
-- ports required by the TI ADS1675
start : out std_logic;
-- ports required by the avalon-mm interface
clock : in std_logic;
reset_n : in std_logic;
read : in std_logic;
write: in std_logic;
address: in std_logic;
writedata : in std_logic_vector(31 downto 0);
readdata : out std_logic_vector(31 downto 0)
);
end ti_ads1675;
architecture rtl of ti_ads1675 is
component counter is
generic
(
n : natural := 1
);
port
(
clock : in std_logic;
clock_enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(n downto 0)
);
end component;
-- counter related signals
signal counter_clock_enable : std_logic := '0';
signal counter_reset : std_logic := '1';
signal counter_value : std_logic_vector(31 downto 0);
-- general signals
signal control_register : std_logic_vector(31 downto 0) := x"00000000";
signal data_register : std_logic_vector(31 downto 0);
begin
counter_inst : component counter
generic map
(
n => 32
)
port map
(
clock => clock,
clock_enable => counter_clock_enable,
reset => counter_reset,
output => counter_value
);
registers : process (clock)
begin
if (rising_edge(clock)) then
-- reset registers
if (reset_n = '0') then
data_register <= x"00000000";
control_register <= x"00000000";
readdata <= x"00000000";
-- read register contents
elsif (read = '1') then
if (address = '0') then
readdata <= data_register;
elsif (address = '1') then
readdata <= control_register;
end if;
-- write register contents
elsif (write = '1') then
if (address = '0') then
data_register <= writedata;
elsif (address = '1') then
control_register <= writedata;
end if;
end if;
end if;
end process registers;
--------------------------
-- gererate start pulse --
--------------------------
process (control_register(2), counter_value)
begin
if (rising_edge(control_register(2))) then
counter_reset <= '0';
counter_clock_enable <= '1';
start <= '1';
elsif (counter_value = x"0000ffff") then
start <= '0';
counter_clock_enable <= '0';
counter_reset <= '1';
control_register(2) <= '0';
end if;
end process;
end rtl;
I have absolutely no clue what is wrong here. The counter itself works, so I think I made a (logic?) fault in my ADC design file. I am thankful for any tips or hints. Regards Michael
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
At least one problem is in line:if (rising_edge(control_register(2))) then
do not use rising_edge function to detect rising edge of general signal of your design. rising_edge function ment to be used for CLOCK edge detection. Regards,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is the culprit code:
--------------------------
-- gererate start pulse --
--------------------------
process (control_register(2), counter_value)
begin
if (rising_edge(control_register(2))) then
counter_reset <= '0';
counter_clock_enable <= '1';
start <= '1';
elsif (counter_value = x"0000ffff") then
start <= '0';
counter_clock_enable <= '0';
counter_reset <= '1';
control_register(2) <= '0';
end if;
end process;
This is not good code, so I have no idea what the synthesisor made of it. Did you look at the RTL and technology diagram? You should clock this with "clock", and make an edge detector circuit with control_register(2) -
process(clock)
begin
if rising_edge(clk) then
control_register2_r <= control_register(2);
if control_register2_r = '0' and control_register(2) = '1' then -- you have a rising_ege on the signal
Do you have a testbench to test this code in the simualtor? And as you're trying to improve your VHDL skills - stop using std_logic_arith and std_logic_unsigned. They are non-standard VHDL libraries. Use numeric_std instead.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thank you for your fast replies. I'll have a closer look at your suggestions and try to change my code accordingly. I'll report the outcome...
... with your help I just go the design running. I build an edge detector an used it to start my counter. Here is the code:library ieee;
use ieee.std_logic_1164.all;
entity edge_detector is
port
(
clock : in std_logic;
signal_in : in std_logic;
output : out std_logic
);
end edge_detector;
architecture behavioral of edge_detector is
signal signal_delayed : std_logic;
begin
process (clock)
begin
if (rising_edge(clock)) then
signal_delayed <= signal_in;
end if;
end process;
output <= signal_in and (not signal_delayed);
end behavioral;
And following the updated code snippet of the ADC-Design: process(control_register_start_edge, counter_value)
begin
if (control_register_start_edge = '1') then
counter_reset <= '0';
counter_clock_enable <= '1';
start <= '1';
elsif (counter_value = x"00000004") then
start <= '0';
counter_clock_enable <= '0';
counter_reset <= '1';
end if;
end process;
I was able to verify the design with ModelSim and even used the 'start' signal to blink an LED on my BeMicro CV ;) No I am looking for a intelligent way to reset my register bit to '0' again. My first idea was to use a reset signal which would be detected in my r/w register process... So after all, thank you for your help!
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page