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 dónde debe ordenarse el motor para ir en cualquier momento dado está programado en LabVIEW. Este programa luego envía comandos de posición y velocidad (como enteros de 32 bits) a un FPGA, que me gustaría usar para generar una serie de pulsos para decirle al motor qué tan lejos y qué tan rápido debe moverse. Tengo un generador de impulsos simple que solo emite el número requerido de impulsos a la velocidad de reloj del FPGA (vea el diagrama a continuación). ¿Cómo puedo controlar la velocidad de estos pulsos en mi FPGA?
Estoy usando un FPGA de Altera programado en Quartus II v9.0.
Observe el terminal inversor para a = b?
en el comparador. El FPGA luego emitirá los valores de pulse
y sign
para decirle a mi motor qué tan lejos girar y en qué dirección. Las entradas al FPGA son el número entero de pulsos que queremos generar, ref[31..00]
, y un indicador de escritura booleano, writeF
. Un solo programa controla varios motores, por lo que es necesario especificar cuándo los datos en el bus ref[31..00]
corresponden a un motor en particular. El bit más significativo del valor de referencia controlará la dirección del movimiento, por lo que se usa err31
como entrada para el terminal updown
.
Como puede ver, el contador está contando el número de pulsos generados, utilizando pulse
como su entrada de reloj, pero pulse
solo se genera a la velocidad de reloj del FPGA. Dada una entrada adicional a mi FPGA para controlar la frecuencia del pulso, ¿puedo hacer que la frecuencia del pulso sea variable?
EDITAR: cambié mi circuito para que el reloj del sistema ingrese a la entrada clock
de mi contador, y mi salida pulse
se use como habilitación del reloj ( clock_en
) señal a este contador. Anteriormente tenía mi salida pulse
conectada directamente a mi entrada clock
, lo cual es potencialmente malo. Publicaré mis hallazgos aquí cuando haya implementado sugerencias.
Solución de contador variable VHDL
Estoy tratando de implementar el enfoque de David Kessner usando VHDL. Básicamente, estoy creando un contador que puede incrementarse en números distintos a 1, y estoy usando la rotación 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 emitir el MSB directamente o tomar el MSB de este contador ( msb_o(k)
), pasarlo a través de un flip-flop DQ 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 desplaza ejecutando:
PULSE = ~msb_o(k) * msb_o(k-1)
donde ~
denota NOT
lógico, y *
denota AND
lógico. Este es el primer programa de VHDL que he escrito, y lo escribí en gran parte usando this , este y this . ¿Alguien tiene alguna recomendación sobre cómo podría mejorar mi código? Desafortunadamente, no estoy recibiendo ningún impulso de mi FPGA.
EDITAR: se actualizó el código VHDL a la implementación actual (2013-08-12). También agregue este libro gratuito a la lista de referencias.
EDIT 2: actualicé mi código a la versión de trabajo (final).