código Verilog simula pero no se ejecuta como se predijo en FPGA
Pregunta
Hice una simulación del comportamiento de mi código, y funciona perfectamente. Los resultados se predijo. Cuando sintetizo mi código y subirlo a una FPGA Spartan 3e y tratar de analizar el uso de ChipScope, los resultados no son ni siquiera cerca de lo que hubiera esperado. ¿Qué he hecho mal? http://pastebin.com/XWMekL7r
Solución
Su problema es con las líneas 13-16, donde se define valores iniciales para los registros 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 es un equivalente a escribir una declaración "inicial" asignación de estos valores, que no es sintetizable - no hay tal cosa como un valor por defecto en el hardware. Cuando usted pone su diseño interior de un FPGA, todos estos registros se enfrentará a valores aleatorios.
En lugar de ello, es necesario inicializar los contadores / estados siempre dentro de su bloque, cuando se restablece es alto.
always @(posedge clk or posedge reset)
if (reset) begin
previousstate <= 0;
presentstate <= 1;
... etc ...
end
respuesta a las preguntas de seguimiento:
Al inicializar el código de esa manera, nada sucede en el hardware - que se ignora por completo, al igual que si has puesto en un comunicado pantalla $. La herramienta de síntesis salta sobre toda simulación se limita a construir, mientras que por lo general le da una especie de advertencia al respecto (que realmente depende de la herramienta).
Ahora, el bloqueo y sin bloqueo pregunta requiere una respuesta muy larga :). Voy a dirigir a este artículo de SNUG-2000, que es probablemente el mejor papel que se ha escrito sobre el tema. Responde a la pregunta, así como muchos otros en el tema. Después, se entiende por qué el uso de declaraciones de bloqueo en la lógica secuencial se considera una mala práctica, y por qué su código funciona bien con el bloqueo de las declaraciones de todos modos.
http://cs.haifa.ac.il /courses/verilog/cummings-nonblocking-snug99.pdf
Más respuestas:
El "patrón" habitual para la creación de la lógica como la suya es tener dos bloques, uno siempre que define la lógica, y uno que definen los fracasos. En el primer caso, se utilizan los estados de bloqueo para implementar la lógica, y en este último se enganche en (o reiniciar) el valor generado. Por lo tanto, algo como esto:
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;
Tenga en cuenta que estoy usando un restablecimiento sincrónica, pero se puede usar asíncrono, si es necesario.
Otros consejos
Las líneas 13-16 son correctos. "Reg [6: 0] fib_number_cnt = 1;" No es lo mismo que usar la declaración "inicial". Leer Xilinx guía para la síntesis descripción más detallada de cómo inicializar los registros.