Pourquoi ne pas utiliser l'IP du gestionnaire d'horloge Xilinx?
Arturs Vancans
Réponses:
19
Fondamentalement, il existe deux façons de procéder. La première consiste à utiliser le cœur du synthétiseur d'horloge natif Xilinx. L'un des avantages de ceci est que les outils Xlinx reconnaîtront l'horloge en tant que telle et la dirigeront à travers les voies requises. Les outils géreront également toutes les contraintes de synchronisation (pas vraiment applicables dans ce cas, car il s'agit d'une horloge de 2 Hz)
La deuxième façon consiste à utiliser un compteur pour compter le nombre d'impulsions d'horloge plus rapides jusqu'à ce que la moitié de votre période d'horloge plus lente se soit écoulée. Par exemple, pour votre cas, le nombre d'impulsions d'horloge rapide qui composent une période d'horloge d'un cycle d'horloge lente est 50000000/2 = 25000000. Puisque nous voulons une demi-période d'horloge, c'est 25000000/2 = 12500000 pour chaque demi-cycle . (la durée de chaque haut ou bas).
Voici à quoi cela ressemble 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;
A noter:
L'horloge générée est nulle lors de la réinitialisation. C'est correct pour certaines applications, et pas pour d'autres, cela dépend juste de ce dont vous avez besoin pour l'horloge.
L'horloge générée sera acheminée en tant que signal normal par les outils de synthèse Xilinx.
2Hz est très lent. Simuler une seconde va prendre un certain temps. C'est une petite quantité de code, donc il devrait être relativement rapide de simuler même pendant 1 seconde, mais si vous commencez à ajouter du code, le temps nécessaire pour simuler un cycle d'horloge de 2 Hz pourrait être considérablement long.
EDIT: clk_2Hz_i est utilisé pour mettre en mémoire tampon le signal de sortie. VHDL n'aime pas utiliser un signal à droite d'une affectation lorsqu'il s'agit également d'une sortie.
Pas mal, mais vous pouvez ajouter / comparer non signé avec un entier, donc: if prescaler = 50_000_000/4 then ...et ce prescaler <= prescaler + 1;serait un peu plus simple.
Brian Drummond
@StaceyAnne En essayant cela, j'obtiens "Impossible de lire à partir de l'objet 'out' clk_o; utilisez 'buffer' ou 'inout'" ai-je manqué quelque chose?
éluder le
@evading, un tampon sur la sortie est nécessaire. VHDL n'aime pas le fait qu'il clk_2Hzs'agit d'une sortie, mais pourtant sa valeur est lue sur cette ligne clk_2Hz <= not clk_2Hz;. J'ai édité le correctif.
stanri
+1 Excellent exemple. Mais c'est là que mon ignorance montre (nouveau sur VHDL). Quelle est la difference entre prescaler <= (others => '0');et prescaler <= '0';?
cbmeeks
NVM! J'ai totalement raté ce qui othersétait utilisé lors de la lecture d'un livre VHDL que j'ai. C'est juste un raccourci pour déclarer tous les "autres" bits à une valeur commune au lieu d'utiliser quelque chose comme "000000000000000000 ....", etc.
cbmeeks
9
Utilisez un détartreur d'horloge.
Votre valeur de pré-échelle sera votre (vitesse_horloge / vitesse_horloge souhaitée) / 2 donc (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000 qui en binaire serait 1011111010111100000000000.
Plus simplement: (50 000 000) / 2) / 2 = 12 500 000 converti en binaire -> 101111101011110000100000
Voici un code de quoi faire: Utilisez newClock pour tout ce dont vous avez besoin de 2hz pour ...
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;
Il semble que vous génériez deux horloges, l'une de 0,5 Hz et l'autre de 1 Hz? (puisque votre période d'horloge est votre prescaler * 2?). En outre, le "+" donnera une erreur, car vous ajoutez des slvs, et je ne suis pas sûr d'utiliser la propriété overflow de l'add de cette manière dans tous les cas. pourquoi ne pas simplement aller newClock : std_logic := '0', compter jusqu'à prescaler / 2 et assigner newClk <= not newClk?
stanri
Merci, ma logique était un peu décalée. J'ai mis à jour mon message initial avec du code testé maintenant et quelques-unes de vos suggestions :)
MLM
Ugh - tous ceux et zéros et un commentaire pour dire ce que c'est vraiment! Pourquoi ne pas utiliser le compilateur pour faire ça pour vous ??? Et pourquoi ne pas utiliser des entiers de toute façon?
Martin Thompson
Je peux me tromper, mais je pense que l'utilisation de valeurs par défaut lors de la définition de signaux dans l'architecture comme dans ": = (others => '0')" n'est pas synthétisable.
Arturs Vancans
Il est synthétisable, mais ne fonctionne que sur les FPGA basés sur SRAM, comme la plupart de Xilinx, Altera ou Lattice.
Yann Vernier
8
En général, vous ne voulez pas cadencer quelque chose de lent, créez simplement une activation au taux correct et utilisez-le dans la logique:
créez quelques constantes avec votre fréquence d'horloge et la fréquence d'activation souhaitée et vous partez, avec du code auto-documenté pour démarrer.
Il a une interface de paramètres graphiques où vous pouvez spécifier quelle fréquence vous voulez. Il générera un composant avec votre sortie souhaitée comme fréquence.
Il peut être trouvé dans IP Wizard;
Et puis vous pourrez spécifier quelle fréquence voulez-vous:
Réponses:
Fondamentalement, il existe deux façons de procéder. La première consiste à utiliser le cœur du synthétiseur d'horloge natif Xilinx. L'un des avantages de ceci est que les outils Xlinx reconnaîtront l'horloge en tant que telle et la dirigeront à travers les voies requises. Les outils géreront également toutes les contraintes de synchronisation (pas vraiment applicables dans ce cas, car il s'agit d'une horloge de 2 Hz)
La deuxième façon consiste à utiliser un compteur pour compter le nombre d'impulsions d'horloge plus rapides jusqu'à ce que la moitié de votre période d'horloge plus lente se soit écoulée. Par exemple, pour votre cas, le nombre d'impulsions d'horloge rapide qui composent une période d'horloge d'un cycle d'horloge lente est 50000000/2 = 25000000. Puisque nous voulons une demi-période d'horloge, c'est 25000000/2 = 12500000 pour chaque demi-cycle . (la durée de chaque haut ou bas).
Voici à quoi cela ressemble en VHDL:
A noter:
EDIT: clk_2Hz_i est utilisé pour mettre en mémoire tampon le signal de sortie. VHDL n'aime pas utiliser un signal à droite d'une affectation lorsqu'il s'agit également d'une sortie.
la source
if prescaler = 50_000_000/4 then ...
et ceprescaler <= prescaler + 1;
serait un peu plus simple.clk_2Hz
s'agit d'une sortie, mais pourtant sa valeur est lue sur cette ligneclk_2Hz <= not clk_2Hz;
. J'ai édité le correctif.prescaler <= (others => '0');
etprescaler <= '0';
?others
était utilisé lors de la lecture d'un livre VHDL que j'ai. C'est juste un raccourci pour déclarer tous les "autres" bits à une valeur commune au lieu d'utiliser quelque chose comme "000000000000000000 ....", etc.Utilisez un détartreur d'horloge.
Votre valeur de pré-échelle sera votre (vitesse_horloge / vitesse_horloge souhaitée) / 2 donc (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000 qui en binaire serait 1011111010111100000000000.
Plus simplement: (50 000 000) / 2) / 2 = 12 500 000 converti en binaire -> 101111101011110000100000
Voici un code de quoi faire: Utilisez newClock pour tout ce dont vous avez besoin de 2hz pour ...
la source
newClock : std_logic := '0'
, compter jusqu'à prescaler / 2 et assignernewClk <= not newClk
?En général, vous ne voulez pas cadencer quelque chose de lent, créez simplement une activation au taux correct et utilisez-le dans la logique:
vous pouvez créer l'activer ainsi:
créez quelques constantes avec votre fréquence d'horloge et la fréquence d'activation souhaitée et vous partez, avec du code auto-documenté pour démarrer.
la source
Je préférerais plutôt utiliser l' IP du gestionnaire d'horloge numérique de primitice Xilinx .
Il a une interface de paramètres graphiques où vous pouvez spécifier quelle fréquence vous voulez. Il générera un composant avec votre sortie souhaitée comme fréquence.
Il peut être trouvé dans IP Wizard;
Et puis vous pourrez spécifier quelle fréquence voulez-vous:
la source
Facteur = fréquence-signal-entrée / fréquence-prescaler-sortie.
CE = Horloge activée. Il doit s'agir d'une impulsion large d'une horloge (clk) ou élevée si elle n'est pas utilisée.
Q = Signal de sortie d'une impulsion large d'horloge avec la fréquence souhaitée.
la source