He estado luchando con un programa Verilog muy simple. Es un registro de desplazamiento de 4 bits que gira en cada ciclo de reloj y controla cuatro LED. (Como puede ver, soy nuevo en FPAG y HDL).
El problema : el código siguiente se sintetiza sin advertencias y se programa con éxito en la FPGA. Luego, al iniciar, no pasa nada, los LED permanecen oscuros. La i_Switch_1
entrada se agregó para hacer que suceda algo y, de hecho, cuando presiono el interruptor, los LED comienzan a girar.
Aquí está el código de Verilog:
Versión 1 (error)
module top
(input i_Clk,
input i_Switch_1,
output o_LED_1,
output o_LED_2,
output o_LED_3,
output o_LED_4
);
reg [3:0]shift_reg;
initial
shift_reg = 4'b0001; // has no effect
always @(posedge i_Clk)
begin
shift_reg <= i_Switch_1 ? 4'b0001 : {shift_reg[2:0], shift_reg[3]};
end
assign o_LED_1 = shift_reg[0];
assign o_LED_2 = shift_reg[1];
assign o_LED_3 = shift_reg[2];
assign o_LED_4 = shift_reg[3];
endmodule
Evaluación : mi conclusión hasta ahora es que shift_reg
no se inicializa a 1. La vista RTL a continuación muestra que no se sintetiza ninguna inicialización.
Leí en muchos lugares que el bloque inicial es sintetizable, así que ahora estoy realmente desconcertado.
Pregunta 1 : ¿Es correcta mi evaluación?
Pregunta 2 : Suponiendo que mi evaluación sea correcta, ¿cuál es el remedio? He probado varias cosas y ninguna funciona:
shift_reg==0
comparación (versión 2 a continuación)is_init
bandera (versión 3 a continuación)Estoy empezando a creer que estoy haciendo algo fundamentalmente mal. ¿¿Qué está pasando??
Versión 2 (falla)
shift_reg <= (shift_reg==0 || i_Switch_1) ? 1 : {shift_reg[2:0], shift_reg[3]}
Versión 3 (falla)
reg is_init;
initial
is_init = 0; // Must have this or else the is_init gets optimized out!
always @(posedge i_Clk)
begin
if(~is_init || i_Switch_1) begin
is_init <= 1;
shift_reg <= 4'b0001;
end
else begin
is_init <= 1;
shift_reg <= {shift_reg[2:0], shift_reg[3]};
end
end
Configuración : LatticeSemi iCE40HX1K (placa nandland go) usando iCEcube2, la herramienta de síntesis es Synplify Pro.
--
Actualizar
Esto aquí funciona:
Versión 4 (éxito)
reg [3:0]shift_reg = 0;
always @(posedge i_Clk)
begin
case(shift_reg)
1: shift_reg <= 2;
2: shift_reg <= 4;
4: shift_reg <= 8;
8: shift_reg <= 1;
default:
shift_reg <= 1;
endcase
end
En muchos casos, las FPGA no admiten valores iniciales de encendido que no sean 0. Sé que todas las FPGA de Altera con las que he trabajado no lo hacen. De hecho, según la hoja de datos de su FPGA, este es el caso:
Cada DFF también se conecta a una señal de reinicio global que se afirma automáticamente inmediatamente después de la configuración del dispositivo.
El restablecimiento global sugiere 0, se establecería si resultara en 1.
Para evitar esto, lo que hacen algunas herramientas de síntesis es algo que se llama empujar burbujas: todo lo que debería inicializarse en 1 se inicializa en 0 y se agrega una puerta no a la salida. Sin embargo, parece que en su caso la herramienta de síntesis no está haciendo esto correctamente. De hecho, puedes probarlo manualmente si quieres:
...
shift_reg <= {shift_reg[2:1], !shift_reg[0], shift_reg[3]};
...
assign o_LED_1 = !shift_reg[0];
Aunque eso no es particularmente útil a largo plazo.
También puede probar la forma alternativa de especificar el valor inicial y ver si la herramienta de síntesis hace un mejor trabajo:
reg [3:0] shift_reg = 4'b0001;
--
De todos modos, generalmente no tendemos a confiar en un valor inicial para los registros y la lógica. En su lugar, tenemos una señal de reinicio global y cláusulas de reinicio en la lógica. Esto nos permite poder establecer todos los registros en un estado conocido en cualquier momento sin tener que hacer un ciclo de encendido.
En su ejemplo con el interruptor, parece que su código con el interruptor infirió correctamente una señal de reinicio ( R_PAT
supongo) que es impulsada como se esperaba por i_Switch_1
. Sin embargo, generalmente usamos un formato algo diferente para las señales de reinicio:
always @ (posedge clock) begin
if (reset) begin
// Do stuff here when in reset
end else begin
// Do stuff here when not in reset
end
end
La declaración procesal estructurada 'inicial' no es sintetizable. Para inicializar el valor cuando su fpga se enciende, puede iniciar el valor del registro dando el valor en el momento de la declaración. p.ej.
reg [3:0]shift_reg= 4'b0000;
Prakash Darji