Estoy trabajando en la generación de un tren de pulsos para controlar un motor que acepta un tren de pulsos como entrada. Cada pulso corresponde a un incremento de movimiento preestablecido; puedo establecer un pulso igual a 1/1000 grados (o lo que sea), y si le envío 20 pulsos, el motor se moverá 20/1000 grados.
El software que realiza todo el trabajo pesado y determina hacia dónde debe dirigirse el motor en cada momento está programado en LabVIEW. Este programa envía los comandos de posición y velocidad (como enteros de 32 bits) a una FPGA, que me gustaría utilizar para generar una serie de pulsos para decirle al motor lo lejos y lo rápido que debe moverse. Tengo un simple generador de pulsos que simplemente emite el número de pulsos necesarios a la velocidad de reloj de la FPGA (ver diagrama abajo). ¿Cómo puedo controlar la velocidad de estos pulsos en mi FPGA?
Estoy utilizando una FPGA Altera programada en Quartus II v9.0.
simular este circuito - Esquema creado con CircuitLab
Tenga en cuenta el terminal inversor para a = b?
en el comparador. La FPGA emitirá entonces los valores de pulse
y sign
para indicarle a mi motor cuánto debe girar y en qué dirección. Las entradas a la FPGA son el número entero de pulsos que queremos generar, ref[31..00]
y un indicador booleano de escritura, writeF
. Un programa controla varios motores, de ahí la necesidad de especificar cuándo los datos del bus ref[31..00]
es para un motor en particular. El bit más significativo del valor de referencia controlará la dirección del movimiento, así err31
se utiliza como entrada para el updown
terminal.
Como puede ver, el contador está contando el número de pulsos generados, utilizando pulse
como su entrada de reloj, pero pulse
sólo se genera a la velocidad de reloj de la FPGA. Dada una entrada adicional a mi FPGA para controlar la velocidad de los pulsos, ¿puedo hacer que la velocidad de los pulsos sea variable?
EDITAR: He cambiado mi circuito para que el reloj del sistema entre en el clock
entrada de mi contador, y mi pulse
se está utilizando como habilitación del reloj ( clock_en
) a este contador. Anteriormente tenía mi pulse
salida conectada directamente a mi clock
entrada, lo que es potencialmente malo. Voy a publicar mis conclusiones aquí cuando he implementado sugerencias.
Solución de contador variable VHDL
Estoy tratando de implementar el enfoque de David Kessner utilizando VHDL. Básicamente estoy creando un contador que puede incrementarse por números distintos de 1, y utilizando el rollover de este contador para determinar cuándo debo generar un pulso. El código se ve así hasta ahora:
--****************************************************************************
-- 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;
Tengo la intención de dar salida al MSB directamente, o tomar el MSB de este contador ( msb_o(k)
), pasarla a través de un flip flop D-Q de un solo bit para que también tenga msb_o(k-1)
y emitir un pulso cada vez que mi contador de variables se vuelque al ejecutarse:
PULSE = ~msb_o(k) * msb_o(k-1)
donde ~
denota una lógica NOT
y *
denota una lógica AND
. Este es el primer programa VHDL que he escrito, y lo escribí en gran parte usando este , este y este . ¿Alguien tiene alguna recomendación sobre cómo podría mejorar mi código? Lamentablemente no estoy recibiendo ningún pulso de mi FPGA todavía.
EDITAR: Actualizado el código VHDL a la implementación actual (2013-08-12). También se ha añadido este libro gratuito a la lista de referencias.
EDITAR 2: He actualizado mi código a la versión (final) que funciona.