Básicamente, hay dos formas de hacer esto. El primero es usar el núcleo sintetizador de reloj nativo Xilinx. Una de las ventajas de esto es que las herramientas Xlinx reconocerán el reloj como tal y lo encaminarán a través de las rutas requeridas. Las herramientas también manejarán cualquier restricción de tiempo (no realmente aplicable en este caso, ya que es un reloj de 2Hz)
La segunda forma es usar un contador para contar la cantidad de pulsos de reloj más rápidos hasta que haya pasado la mitad de su período de reloj más lento. Por ejemplo, para su caso, la cantidad de pulsos de reloj rápidos que conforman un período de reloj de un ciclo de reloj lento es 50000000/2 = 25000000. Como queremos medio período de reloj, eso es 25000000/2 = 12500000 para cada medio ciclo . (la duración de cada alta o baja).
Así es como se ve en VHDL:
library IEEE;use IEEE.STD_LOGIC_1164.all;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.all;entity scale_clock isport(
clk_50Mhz :instd_logic;
rst :instd_logic;
clk_2Hz :outstd_logic);end scale_clock;architecture Behavioral of scale_clock issignal prescaler :unsigned(23downto0);signal clk_2Hz_i :std_logic;begin
gen_clk :process(clk_50Mhz, rst)begin-- process gen_clkif rst ='1'then
clk_2Hz_i <='0';
prescaler <=(others=>'0');elsif rising_edge(clk_50Mhz)then-- rising clock edgeif prescaler =X"BEBC20"then-- 12 500 000 in hex
prescaler <=(others=>'0');
clk_2Hz_i <=not clk_2Hz_i;else
prescaler <= prescaler +"1";endif;endif;endprocess gen_clk;
clk_2Hz <= clk_2Hz_i;end Behavioral;
Cosas a tener en cuenta:
El reloj generado es cero durante el reinicio. Esto está bien para algunas aplicaciones, y no para otras, solo depende de para qué necesita el reloj.
Las herramientas de síntesis Xilinx enrutarán el reloj generado como una señal normal.
2Hz es muy lento. Simular por un segundo llevará un tiempo. Es una pequeña cantidad de código, por lo que debería ser relativamente rápido simular incluso durante 1 segundo, pero si comienza a agregar código, el tiempo necesario para simular un ciclo de reloj de 2 Hz podría ser significativamente largo.
EDITAR: clk_2Hz_i se utiliza para almacenar en búfer la señal de salida. A VHDL no le gusta usar una señal a la derecha de una asignación cuando también es una salida.
No está mal, pero puede agregar / comparar sin firmar con entero, por lo que: if prescaler = 50_000_000/4 then ...y prescaler <= prescaler + 1;sería un poco más simple.
Brian Drummond
@StaceyAnne Al intentar esto, obtengo "No se puede leer desde el objeto 'fuera' clk_o; uso 'buffer' o 'inout'" ¿Me perdí algo?
evadiendo el
@evading, se necesita un búfer en la salida. A VHDL no le gusta el hecho de que clk_2Hzsea una salida, pero su valor se está leyendo en esta línea clk_2Hz <= not clk_2Hz;. He editado en la corrección.
stanri
+1 Gran ejemplo. Pero aquí es donde se muestra mi ignorancia (nuevo en VHDL). ¿Cuál es la diferencia entre prescaler <= (others => '0');y prescaler <= '0';?
cbmeeks
NVM! Extrañaba totalmente lo que othersse usaba cuando leía un libro VHDL que tengo. Es solo un atajo para declarar todos los "otros" bits a un valor común en lugar de usar algo como "000000000000000000 ....", etc.
cbmeeks
9
Usa un reloj preescalador.
Su valor de preescalador será su (clock_speed / deseado_clock_speed) / 2 so (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000 que en binario sería 101111101011110000100000.
Más simplemente: (50,000,000) / 2) / 2 = 12,500,000 convertir a binario -> 101111101011110000100000
Aquí hay un código de qué hacer: Use newClock para lo que necesite 2hz para ...
library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity ClockPrescaler isport(
clock :inSTD_LOGIC;-- 50 Mhz
Led :outSTD_LOGIC);end ClockPrescaler;architecture Behavioral of ClockPrescaler is-- prescaler should be (clock_speed/desired_clock_speed)/2 because you want a rising edge every periodsignal prescaler:STD_LOGIC_VECTOR(23downto0):="101111101011110000100000";-- 12,500,000 in binarysignal prescaler_counter:STD_LOGIC_VECTOR(23downto0):=(others=>'0');signal newClock :std_logic:='0';begin
Led <= newClock;
countClock:process(clock, newClock)beginif rising_edge(clock)then
prescaler_counter <= prescaler_counter +1;if(prescaler_counter > prescaler)then-- Iterate
newClock <=not newClock;
prescaler_counter <=(others=>'0');endif;endif;endprocess;end Behavioral;
Parece que estás generando dos relojes, uno de 0.5 Hz y uno de 1 Hz. (ya que su período de reloj es su prescaler * 2?). Además, el "+" dará un error, ya que está agregando slvs, y no estoy tan seguro de usar la propiedad de desbordamiento del complemento de esta manera en ningún caso. ¿por qué no simplemente ir newClock : std_logic := '0', contar hasta preescaler / 2 y asignar newClk <= not newClk?
Stan
Gracias, mi lógica estaba un poco apagada. Actualicé mi publicación inicial con un código probado ahora y algunas de sus sugerencias :)
MLM
Ugh - todos esos ceros y un comentario para decir lo que realmente es! ¿Por qué no usar el compilador para hacer eso por ti? ¿Y por qué no usar enteros de todos modos?
Martin Thompson
Puedo estar equivocado, pero creo que usar valores predeterminados al definir señales en arquitectura como en ": = (otros => '0')" no es sintetizable.
Arturs Vancans
Es sintetizable, pero básicamente solo funciona en FPGA basados en SRAM, como la mayoría de Xilinx, Altera o Lattice.
Yann Vernier
8
Por lo general, en realidad no desea registrar nada tan lento, solo cree una habilitación a la velocidad correcta y úsela en la lógica:
Tiene una interfaz de configuración gráfica donde puede especificar qué frecuencia desea. Generará un componente con su salida deseada como frecuencia.
Respuestas:
Básicamente, hay dos formas de hacer esto. El primero es usar el núcleo sintetizador de reloj nativo Xilinx. Una de las ventajas de esto es que las herramientas Xlinx reconocerán el reloj como tal y lo encaminarán a través de las rutas requeridas. Las herramientas también manejarán cualquier restricción de tiempo (no realmente aplicable en este caso, ya que es un reloj de 2Hz)
La segunda forma es usar un contador para contar la cantidad de pulsos de reloj más rápidos hasta que haya pasado la mitad de su período de reloj más lento. Por ejemplo, para su caso, la cantidad de pulsos de reloj rápidos que conforman un período de reloj de un ciclo de reloj lento es 50000000/2 = 25000000. Como queremos medio período de reloj, eso es 25000000/2 = 12500000 para cada medio ciclo . (la duración de cada alta o baja).
Así es como se ve en VHDL:
Cosas a tener en cuenta:
EDITAR: clk_2Hz_i se utiliza para almacenar en búfer la señal de salida. A VHDL no le gusta usar una señal a la derecha de una asignación cuando también es una salida.
fuente
if prescaler = 50_000_000/4 then ...
yprescaler <= prescaler + 1;
sería un poco más simple.clk_2Hz
sea una salida, pero su valor se está leyendo en esta líneaclk_2Hz <= not clk_2Hz;
. He editado en la corrección.prescaler <= (others => '0');
yprescaler <= '0';
?others
se usaba cuando leía un libro VHDL que tengo. Es solo un atajo para declarar todos los "otros" bits a un valor común en lugar de usar algo como "000000000000000000 ....", etc.Usa un reloj preescalador.
Su valor de preescalador será su (clock_speed / deseado_clock_speed) / 2 so (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000 que en binario sería 101111101011110000100000.
Más simplemente: (50,000,000) / 2) / 2 = 12,500,000 convertir a binario -> 101111101011110000100000
Aquí hay un código de qué hacer: Use newClock para lo que necesite 2hz para ...
fuente
newClock : std_logic := '0'
, contar hasta preescaler / 2 y asignarnewClk <= not newClk
?Por lo general, en realidad no desea registrar nada tan lento, solo cree una habilitación a la velocidad correcta y úsela en la lógica:
puede crear la habilitación así:
cree un par de constantes con la frecuencia de su reloj y la frecuencia de activación deseada y listo, con el código autodocumentado para arrancar.
fuente
Prefiero sugerir el uso de Xilinx primitice digital clock manager IP .
Tiene una interfaz de configuración gráfica donde puede especificar qué frecuencia desea. Generará un componente con su salida deseada como frecuencia.
Se puede encontrar en IP Wizard;
Y luego podrá especificar qué frecuencia desea:
fuente
Factor = frecuencia de señal de entrada / frecuencia de preescalador de salida.
CE = Reloj habilitado. Debe ser un pulso ancho de un reloj (clk) o alto si no se usa.
Q = Señal de salida de un pulso ancho de reloj con la frecuencia deseada.
fuente