- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm an analogue engineer with no experience in VHDL/FPGA's however im looking into using one to perform a few tasks. i have a DE0 development board which ive been playing about with. however i im a bit stuck with trying to get down in VHDL what im after. i have a pulse that goes high for 1 us and repeats every second, i have another pulse that also goes high for 2 us and repeats every second. the two rising edges can drift , what i'm trying to do is if the first pulse goes high and the second pulse goes high later than 10 us a 250 ns output will be pulsed. i think how the circuit will work will be if pulse 1 goes high start a counter that will count 500 clock pulses ( 50 MHz clk). If the second pulse goes high before the count reaches 500 reset an wait for next pulse. if the second pulse goes high after 500 clock cycles output a 250 ns pulse and reset. does this sound plausible? if so how do i go about implementing it.Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sounds feasible to me. Sorry im on my phone not so good for code examples. But counters are a staple of hdl so any tutorial should have one.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- I'm an analogue engineer --- Quote End --- Welcome to the "dark side"! Or perhaps we should thank you for coming over from the dark side :) --- Quote Start --- i have a DE0 development board which ive been playing about with. however i im a bit stuck with trying to get down in VHDL what im after. i have a pulse that goes high for 1 us and repeats every second, i have another pulse that also goes high for 2 us and repeats every second. the two rising edges can drift , what i'm trying to do is if the first pulse goes high and the second pulse goes high later than 10 us a 250 ns output will be pulsed. i think how the circuit will work will be if pulse 1 goes high start a counter that will count 500 clock pulses ( 50 MHz clk). If the second pulse goes high before the count reaches 500 reset an wait for next pulse. if the second pulse goes high after 500 clock cycles output a 250 ns pulse and reset. does this sound plausible? if so how do i go about implementing it. --- Quote End --- Since you are a beginner, I'll verbally walk you through some general ideas. 1. Learn to use Modelsim to simulate your design. This will make your life easier, as you'll be able to provide code when you get stuck. 2. 1s is a long time in a simulator, so learn to use VHDL generics to parameterize your circuits. For example, I have some logic like you describe for monitoring the 1pps output from a GPS unit. When simulating the design, I can change the generics to expect 1ms ticks or 100ms ticks. 3. External signals that are not synchronous to your FPGA clock need to be synchronized. You do this via a synchronizer component; multiple stages of flip-flops that are used to decrease the probability of metastability. 4. Learn how to write state machines. Signal generation in a state machine is often generically referred to as Moore (output depends on state) and Mealy (output depends on input and state). You can use a state machine to track your pulse logic, eg., got an edge, waiting for other pulse, etc. Take a shot at writing some VHDL code, eg., a testbench that generates your 1pps (or 100ms) pulse, and a synchronizer component that synchronizes that pulse to the DE0 clock. Then figure out a way to detect a rising-edge on that signal (hint, you can use a single register to delay the synchronized signal, and then logic operators and/nand/or/nor/xor/xnor to get a single clock pulse). That'll help you get familiar with Modelsim. Then you can start working on your real application. Come back to the forum when you get stuck, you'll get plenty of advice. Cheers, Dave
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the reply guys, sorry am a bit late back replying I've had a dreaded cold!
I have had a start at writing a bit of code that detects the edge of a pulse which I have simulated and seems to work. The bit i'm stuck with is adding the portion of code that starts the counter. The edge detection output is called "mon_prescale" what I would like to do is when this signal goes hi start a counter. however when I use then if.... etc in the same process as the edge detector it throws up an error???
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity mon_prescale is
port (
clk: in std_logic;
monitor: in std_logic;
mon_prescale: out std_logic
);
end mon_prescale;
architecture Behavioral of mon_prescale is
signal mon_delay: std_logic;
begin
CounterProcess: process(clk)
begin
mon_prescale <= monitor and not mon_delay;
if rising_edge(clk) then
mon_delay <= monitor;
end if;
end process;
end Behavioral;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Thanks for the reply guys, sorry am a bit late back replying I've had a dreaded cold! I have had a start at writing a bit of code that detects the edge of a pulse which I have simulated and seems to work. The bit i'm stuck with is adding the portion of code that starts the counter. The edge detection output is called "mon_prescale" what I would like to do is when this signal goes hi start a counter. however when I use then if.... etc in the same process as the edge detector it throws up an error???
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity mon_prescale is
port (
clk: in std_logic;
monitor: in std_logic;
mon_prescale: out std_logic
);
end mon_prescale;
architecture Behavioral of mon_prescale is
signal mon_delay: std_logic;
begin
CounterProcess: process(clk)
begin
mon_prescale <= monitor and not mon_delay;
if rising_edge(clk) then
mon_delay <= monitor;
end if;
end process;
end Behavioral;
--- Quote End --- for edge detection I will do this:
CounterProcess: process(clk)
begin
if rising_edge(clk) then
mon_delay <= monitor;
end if;
end process;
mon_prescale <= monitor and not mon_delay;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi djstar,
Glad to see you are thinking! A couple of comments; The error in your pulse generation code is that you have not used the correct syntax for a clocked process. Kaz has corrected your HDL. Note that Kaz's solution generates a combinatorial pulse. You could also have put that logic inside the process to generate a registered output, but in that case, you also need to initialize the value of the signals, eg.,
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mon_prescale is
port (
clk: in std_logic;
monitor: in std_logic;
mon_prescale: out std_logic
);
end entity;
architecture Behavioral of mon_prescale is
-- Registers and their default values
signal mon_delay: std_logic := '0';
signal mon_out: std_logic := '0';
begin
process(clk)
begin
if rising_edge(clk) then
mon_delay <= monitor;
mon_out <= monitor and (not mon_delay);
end if;
end process;
mon_prescale <= mon_out;
end architecture;
Note how I have added two signals internal to your logic. The signal mon_out appears to be redundant, since you could have used mon_prescale directly, however, then you would not have been able to assign a default value to the signal. An FPGA will encode this default value in its configuration bit-stream. A slight modification to this logic is to include a global reset signal (which in my opinion is a good idea)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mon_prescale is
port (
rstN: in std_logic;
clk: in std_logic;
monitor: in std_logic;
mon_prescale: out std_logic
);
end entity;
architecture Behavioral of mon_prescale is
-- Registers and their default values
signal mon_delay: std_logic := '0';
signal mon_out: std_logic := '0';
begin
process(clk, rstN)
begin
if (rstN = '0') then
mon_delay <= '0';
mon_out <= '0';
elsif rising_edge(clk) then
mon_delay <= monitor;
mon_out <= monitor and (not mon_delay);
end if;
end process;
mon_prescale <= mon_out;
end architecture;
In this case, when rstN asserts (I happen to have used an active low signal, but you can equally use active high) the outputs reset to zero. If you never asserted rstN in your simulation, then the outputs would still be zero due to the initial values assigned when the signals were created. Note: do not use the non-standard/deprecated libraries use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; instead use the standard library use IEEE.NUMERIC_STD.ALL; Also note that begin-entity and begin-architecture can be ended with end-entity and end-architecture as I have used in the code examples above. This makes it easier to copy and paste code, since you do not have to edit the entity or architecture name in two places if you've copied some code. Cheers, Dave

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