I am working on generating a pulse train to control a motor that accepts a pulse train as an input. Each pulse corresponds to a pre-set movement increment; I can set one pulse equal to 1/1000 degree (or whatever), and if I send it 20 pulses, the motor will move 20/1000 degree.
The software that performs all the heavy lifting and determines where the motor needs to be commanded to go at any given time is programmed in LabVIEW. This program then sends position and speed commands (as 32-bit integers) to an FPGA, which I would like to use to generate a series of pulses to tell the motor how far and how fast to move. I have a simple pulse generator that just puts out the required number of pulses at the FPGA's clock speed (see diagram below). How can I control the speed of these pulses in my FPGA?
I am using an Altera FPGA programmed in Quartus II v9.0.
simulate this circuit – Schematic created using CircuitLab
Note the inverting terminal for a = b?
on the comparator. The FPGA will then output the values of pulse
and sign
to tell my motor how far to turn and in what direction. Inputs to the FPGA are the integer number of pulses we want to generate, ref[31..00]
, and a boolean write flag, writeF
. Multiple motors are controlled by one program, thus the need to specify when the data on the bus ref[31..00]
is for a particular motor. The most significant bit of the reference value will control the direction of movement, thus err31
is used as the input to the updown
terminal.
As you can see, the counter is counting the number of pulses generated, using pulse
as its clock input, but pulse
is only being generated at the FPGA's clock speed. Given an additional input to my FPGA to control pulse rate, can I make the pulse rate variable?
EDIT: I changed my circuit so that the system clock is going in to the clock
input of my counter, and my pulse
output is being used as the clock enable (clock_en
) signal to this counter. Previously I had my pulse
output plugged straight in to my clock
input, which is potentially bad. I will post my findings here when I have implemented suggestions.
VHDL Variable Counter Solution
I am trying to implement David Kessner's approach using VHDL. Basically I am creating a counter that can increment by numbers other than 1, and using the rollover of this counter to determine when I should generate a pulse. The code looks like this so far:
--****************************************************************************
-- Load required libraries
--****************************************************************************
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--****************************************************************************
-- Define the inputs, outputs, and parameters
--****************************************************************************
entity var_count is
generic(N: integer :=32); -- for generic counter size
port(
inc_i : in std_logic_vector(N-1 downto 0);
load_i : in std_logic;
clk_i : in std_logic;
clear_i : in std_logic;
clk_en_i : in std_logic;
count_en_i : in std_logic;
msb_o : out std_logic
);
end var_count;
--****************************************************************************
-- Define the behavior of the counter
--****************************************************************************
architecture behavior of var_count is
-- Define our count variable. No need to initialize in VHDL.
signal count : unsigned(N-1 downto 0) := to_unsigned(0, N);
signal incr : unsigned(N-1 downto 0) := to_unsigned(0, N);
begin
-- Define our clock process
clk_proc : process(clk_i, clear_i, load_i)
begin
-- Asynchronous clear
if clear_i = '1' then
count <= to_unsigned(0, N);
end if;
-- Asynchronous load
if load_i = '1' then
incr <= unsigned(inc_i);
end if;
-- Define processes synch'd with clock.
if rising_edge(clk_i) and clk_en_i = '1' then
if count_en_i = '1' then -- increment the counter
-- count <= count + unsigned(inc_i);
count <= count + incr;
end if;
end if;
end process clk_proc;
-- Output the MSB for the sake of generating a nice easy square wave.
msb_o <= count(count'left);
end behavior;
I intend to either output the MSB directly, or to take the MSB from the this counter (msb_o(k)
), pass it through a single-bit D-Q flip flop so that I also have msb_o(k-1)
, and output a pulse every time my variable counter rolls over by executing:
PULSE = ~msb_o(k) * msb_o(k-1)
where ~
denotes logical NOT
, and *
denotes logical AND
. This is the first VHDL program I have written, and I wrote it largely using this, this, and this. Does anybody have any recommendations as to how I could improve my code? Unfortunately I am not getting any pulses out of my FPGA still.
EDIT: Updated the VHDL code to the current implementation (2013-08-12). Also adding this free book to the list of references.
EDIT 2: Updated my code to the (final) working version.