Pergunta

Eu fiz uma simulação comportamental do meu código, e ele funciona perfeitamente. Os resultados são como é previsto. Quando eu sintetizar meu código e enviá-lo para uma 3e espartano FPGA e tentar analisar usando ChipScope, os resultados não são nem perto do que eu teria esperado. O que eu fiz de forma incorreta? http://pastebin.com/XWMekL7r

Foi útil?

Solução

Seu problema é com linhas 13-16, onde você definir valores iniciais para os registos de estado:

 reg    [OUTPUT_WIDTH-1:0] previousstate = 0;              
 reg    [OUTPUT_WIDTH-1:0] presentstate = 1;
 reg    [6:0] fib_number_cnt = 1;  
 reg    [OUTPUT_WIDTH-1:0] nextstate = 1; 

Este é um equivalente a escrever uma declaração "inicial" de atribuir esses valores, que não é synthesizable - não existe tal coisa como um valor padrão no hardware. Quando você colocar o seu projeto dentro de um FPGA, todos esses registros vai assumir valores aleatórios.

Em vez disso, você precisa para inicializar esses contadores / estados dentro do seu sempre bloquear, quando reinicialização é alta.

always @(posedge clk or posedge reset)
  if (reset) begin
     previousstate <= 0;
     presentstate <= 1;
     ... etc ...
  end

Resposta às perguntas de acompanhamento:

Quando você inicializar um código como esse, nada acontece em hardware - ele é completamente ignorado, como se você colocar em um comunicado $ display. Os saltos ferramenta de síntese sobre todas as construções só de simulação, enquanto geralmente dando-lhe algum tipo de aviso sobre isso (que realmente depende da ferramenta).

Agora, bloqueio e sem bloqueio questão exige uma resposta muito longa :). Vou encaminhá-lo para este papel de SNUG-2000, que é provavelmente o melhor papel já escrito sobre o assunto. Ele responde a sua pergunta, assim como muitos outros sobre o tema. Depois disso, você vai entender por que usar instruções de bloqueio na lógica seqüencial é considerado uma má prática, e por que seu código funciona bem com o bloqueio declarações de qualquer maneira.

http://cs.haifa.ac.il /courses/verilog/cummings-nonblocking-snug99.pdf


Mais respostas:

O "padrão" usual para a criação de lógica como o seu é ter dois sempre blocos, um que define a lógica, e uma definição da aleta. No primeiro caso, você usa o bloqueio declarações para implementar a lógica, e no último você trava (ou redefinir) o valor gerado. Então, algo como isto:

wire some_input;

// Main logic (use blocking statements)
reg state, next_state;
always @*
  if (reset) next_state = 1'b0;
  else begin
    // your state logic
    if (state) next_state = some_input;
    else next_state = 1'b0;
  end

// Flops (use non-blocking)
always @(posedge clock)
  if (reset) state <= 1'b0;
  else state <= next_state;

Note que eu estou usando um reset síncrono, mas você pode usar assíncrono, se necessário.

Outras dicas

Linhas 13-16 estão corretas. "Reg [6: 0] fib_number_cnt = 1;" não é o mesmo que usar declaração "inicial". Leia Xilinx síntese guia para descrição mais detalhada de como inicializar os registros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top