Por que não usar o IP do gerenciador de clock Xilinx?
Arturs Vancans
Respostas:
19
Basicamente, existem duas maneiras de fazer isso. O primeiro é usar o núcleo do sintetizador de relógio nativo Xilinx. Uma das vantagens disso é que as ferramentas do Xlinx reconhecem o relógio como tal e o direcionam pelos caminhos necessários. As ferramentas também lidam com qualquer restrição de tempo (não é realmente aplicável neste caso, pois é um relógio de 2 Hz)
A segunda maneira é usar um contador para contar o número de pulsos de clock mais rápidos até que metade do seu período de relógio mais lento tenha passado. Por exemplo, no seu caso, o número de pulsos de clock rápidos que compõem um período de relógio de um ciclo lento é 50000000/2 = 25000000. Como queremos um período de meio relógio, isso é 25000000/2 = 12500000 para cada meio ciclo . (a duração de cada alta ou baixa).
Aqui está o que parece em 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;
Coisas a serem observadas:
O relógio gerado é zero durante a redefinição. Isso é bom para alguns aplicativos e não para outros, depende apenas do que você precisa para o relógio.
O relógio gerado será roteado como um sinal normal pelas ferramentas de síntese do Xilinx.
2Hz é muito lento. Simular por um segundo vai demorar um pouco. É uma quantidade pequena de código, portanto, deve ser relativamente rápido simular até 1 segundo, mas se você começar a adicionar código, o tempo necessário para simular um ciclo de clock de 2 Hz pode ser significativamente longo.
EDIT: clk_2Hz_i é usado para armazenar em buffer o sinal de saída. O VHDL não gosta de usar um sinal à direita de uma atribuição quando também é uma saída.
Nada mal, mas você pode adicionar / comparar sem assinatura com número inteiro, então: if prescaler = 50_000_000/4 then ...e prescaler <= prescaler + 1;seria um pouco mais simples.
Brian Drummond
@StaceyAnne Ao tentar isso, recebo "Não é possível ler do objeto 'out' clk_o; use 'buffer' ou 'inout'", perdi alguma coisa?
fugindo
@evading, é necessário um buffer na saída. O VHDL não gosta do fato de clk_2Hzser uma saída, mas seu valor está sendo lido nesta linha clk_2Hz <= not clk_2Hz;. Eu editei na correção.
stanri
+1 Ótimo exemplo. Mas aqui é onde minha ignorância mostra (novo no VHDL). Qual é a diferença entre prescaler <= (others => '0');e prescaler <= '0';?
Cbmeeks 28/01
NVM! Perdi totalmente o que othersera usado ao ler um livro de VHDL que tenho. É apenas um atalho para declarar todos os "outros" bits para um valor comum em vez de usar algo como "000000000000000000 ....", etc.
cbmeeks
9
Use um prescaler de relógio.
Seu valor de pré-calibrador será seu (velocidade do relógio / velocidade do relógio desejada) / 2, para (50Mhz (50.000.000) / 2hz (2)) / 2 = 12.500.000, que em binário seria 101111101011110000100000.
Mais simplesmente: (50.000.000) / 2) / 2 = 12.500.000 converter em binário -> 101111101011110000100000
Aqui está um código do que fazer: Use newClock para o que você precisar de 2 hz 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 você está gerando dois relógios, um de 0,5 Hz e um de 1 Hz? (como o período do seu relógio é o seu pré-calibrador * 2?). Além disso, o "+" dará um erro, já que você está adicionando slvs, e não tenho tanta certeza sobre o uso da propriedade overflow do add dessa maneira em qualquer caso. por que não apenas ir newClock : std_logic := '0', contar até prescaler / 2 e atribuir newClk <= not newClk?
stanri
Obrigado, minha lógica estava um pouco errada. Eu atualizei meu post inicial com algum código testado agora e algumas de suas sugestões :)
MLM
Ugh - todos esses e zeros e um comentário para dizer o que realmente é! Por que não usar o compilador para fazer isso por você ??? E por que não usar números inteiros de qualquer maneira?
Martin Thompson
Posso estar errado, mas acho que o uso de valores padrão ao definir sinais na arquitetura como em ": = (others => '0')" não é sintetizado.
Arturs Vancans
É sintetizável, mas basicamente funciona apenas em FPGAs baseados em SRAM, como a maioria dos Xilinx, Altera ou Lattice.
Yann Vernier
8
Na verdade, você normalmente não quer marcar nada tão lento, basta criar uma habilitação na taxa correta e usá-la na lógica:
Possui interface de configurações gráficas onde você pode especificar qual frequência deseja. Ele irá gerar um componente com a saída desejada como frequência.
Pode ser encontrado no Assistente de IP;
E então você poderá especificar qual frequência deseja:
Respostas:
Basicamente, existem duas maneiras de fazer isso. O primeiro é usar o núcleo do sintetizador de relógio nativo Xilinx. Uma das vantagens disso é que as ferramentas do Xlinx reconhecem o relógio como tal e o direcionam pelos caminhos necessários. As ferramentas também lidam com qualquer restrição de tempo (não é realmente aplicável neste caso, pois é um relógio de 2 Hz)
A segunda maneira é usar um contador para contar o número de pulsos de clock mais rápidos até que metade do seu período de relógio mais lento tenha passado. Por exemplo, no seu caso, o número de pulsos de clock rápidos que compõem um período de relógio de um ciclo lento é 50000000/2 = 25000000. Como queremos um período de meio relógio, isso é 25000000/2 = 12500000 para cada meio ciclo . (a duração de cada alta ou baixa).
Aqui está o que parece em VHDL:
Coisas a serem observadas:
EDIT: clk_2Hz_i é usado para armazenar em buffer o sinal de saída. O VHDL não gosta de usar um sinal à direita de uma atribuição quando também é uma saída.
fonte
if prescaler = 50_000_000/4 then ...
eprescaler <= prescaler + 1;
seria um pouco mais simples.clk_2Hz
ser uma saída, mas seu valor está sendo lido nesta linhaclk_2Hz <= not clk_2Hz;
. Eu editei na correção.prescaler <= (others => '0');
eprescaler <= '0';
?others
era usado ao ler um livro de VHDL que tenho. É apenas um atalho para declarar todos os "outros" bits para um valor comum em vez de usar algo como "000000000000000000 ....", etc.Use um prescaler de relógio.
Seu valor de pré-calibrador será seu (velocidade do relógio / velocidade do relógio desejada) / 2, para (50Mhz (50.000.000) / 2hz (2)) / 2 = 12.500.000, que em binário seria 101111101011110000100000.
Mais simplesmente: (50.000.000) / 2) / 2 = 12.500.000 converter em binário -> 101111101011110000100000
Aqui está um código do que fazer: Use newClock para o que você precisar de 2 hz para ...
fonte
newClock : std_logic := '0'
, contar até prescaler / 2 e atribuirnewClk <= not newClk
?Na verdade, você normalmente não quer marcar nada tão lento, basta criar uma habilitação na taxa correta e usá-la na lógica:
você pode criar o enable assim:
crie algumas constantes com a sua frequência de clock e a freqüência de ativação desejada e pronto, com código de auto-documentação para inicializar.
fonte
Prefiro sugerir o uso do IP do gerenciador de relógio digital Xilinx primitice .
Possui interface de configurações gráficas onde você pode especificar qual frequência deseja. Ele irá gerar um componente com a saída desejada como frequência.
Pode ser encontrado no Assistente de IP;
E então você poderá especificar qual frequência deseja:
fonte
Fator = frequência de sinal de entrada / frequência de pré-calibrador de saída.
CE = Ativar relógio. Deve ser um pulso amplo de um relógio (clk) ou alto, se não for usado.
Q = Sinal de saída de um pulso amplo com a freqüência desejada.
fonte