Primero, gracias por la ayuda de ayer. Esta vez documentaré mi código correctamente.
Por lo tanto, se nos encargó crear un parquímetro que necesitara 4 entradas, una que suma 50 segundos, otra que suma 150 segundos, otra que suma 250 segundos y otra que suma 500 segundos. Cuando quedan más de 10 segundos, un led verde debe parpadear con un período de 2 segundos. Cuando quedan menos de 10 segundos, un led rojo debe parpadear con un período de 2 segundos, y cuando no quedan segundos, un led rojo debe parpadear con un período de 1 segundo. Se supone que cada ciclo de reloj sin entrada resta uno del medidor.
Tuvimos la tarea de usar un antirrebote, así como una máquina de estado de un solo pulso para las entradas y una pantalla de 7 segmentos para las salidas. Por lo tanto, utilicé una máquina de estado para mi suma y el parpadeo del LED, luego envié el contador a un convertidor binario a BCD y luego a una pantalla de BCD a 7 segmentos. Me pregunto si estropeé el reloj y de alguna manera la simulación ignora mis errores, haciendo que el FPGA no pueda usar correctamente mi código.
sin más preámbulos, aquí están mis fragmentos de código:
Módulo superior
module parkingmeter(clk,rst,b0,b1,b2,b3,out0,out1,out2,out3,GRNLED,REDLED);
input b0,b1,b2,b3,clk,rst;
output [6:0] out0,out1,out2,out3;
output GRNLED,REDLED;
wire outt0,outt1,outt2,outt3;
wire [15:0] counter;
wire [3:0] bcd0,bcd1,bcd2,bcd3;
wire clkout;
clockdivider onesec(clk,clkout);
add_sub yep(b0,clkout,rst,outt0);
add_sub yesh(b1,clkout,rst,outt1);
add_sub yeah(b2,clkout,rst,outt2);
add_sub ok(b3,clk,rst,outt3);
controlparker Second(outt0,outt1,outt2,outt3,clkout,rst,counter,REDLED,GRNLED);
EC Third(counter,bcd0,bcd1,bcd2,bcd3,out0,out1,out2,out3);
endmodule
mi modulo de rebote
module cleandebounce(clk,rst,I0,out);
input clk,rst,I0;
output out;
reg f0,f1;
always @ (posedge clk, posedge rst) begin
if (rst==1) begin
f0 <= I0;
f1 <= f0;
end else begin
f0 <= 0;
f1 <= 0;
end
end
assign out = f1;
endmodule
Mi máquina de estado de un solo pulso
module add_sub(in,clk,rst,out);
input in,clk,rst;
output reg out = 1'b0;
reg state = 1'b0;
wire outt;
cleandebounce one(clk,rst,in,outt);
always @ (posedge clk,posedge rst) begin
case(state)
1'b0: begin
if (rst==1) begin
out <= 0;
if (outt == 1) begin
out <= 1'b1;
state <= 1'b1;
end else state <= 1'b0;
end else begin
out <= 1'b0;
state <= 1'b0;
end
end
1'b1: begin
out <= 1'b0;
if (outt == 1) begin
out <= 1'b0;
state <= 1'b1;
end else state <= 1'b0;
end
endcase
end
endmodule
Y mi módulo para agregar las entradas, así como para encender y apagar los leds.
module controlparker(B0,B1,B2,B3,clk,rst,counter,REDLED,GRNLED);
input B0,B1,B2,B3,clk,rst;
output reg [15:0] counter = 16'b0000000000000000;
reg state = 1'b0;
reg [2:0] area = 3'b000;
output reg REDLED = 0;
output reg GRNLED = 0;
always @ (posedge clk, posedge rst) begin
case(state)
0: begin
if (rst==1) begin
if (counter > 0)
counter <= counter - 1;
if (counter > 9999)begin
counter <= 9999;
end
state <= 1;
end else begin
counter <= 0;
state <= 0;
end
end
1: begin
if (B0 == 1) begin
counter <= counter + 16'b00000000000110010;
state <= 0;
end else if (B1 == 1) begin
counter <= counter + 16'b00000000010010110;
state <= 0;
end else if (B2 == 1) begin
counter <= counter + 16'b00000000011111010;
state <= 0;
end else if (B3 == 1) begin
counter <= counter + 16'b00000000111110010;
state <= 0;
end else state <= 0;
end
endcase
end
always @ (posedge clk, posedge rst) begin
case(area)
3'b000: begin
if (rst==1)begin
if (counter >= 10)begin
GRNLED <= 1;
REDLED <= 0;
area <= 3'b001;
end
else if (counter < 10 && counter > 0) begin
REDLED <= 1;
GRNLED <= 0;
area <= 3'b010;
end
else REDLED <= ~REDLED;
end
else begin
REDLED <= 0;
GRNLED <= 0;
end
end
3'b001: begin
GRNLED <= 0;
area <= 3'b000;
end
3'b010: begin
REDLED <= 0;
area <= 3'b000;
end
endcase
end
endmodule
Mi módulo convierte BinarytoBCD, así como la salida de pantalla de 7 segmentos:
module EC(in,bcd0,bcd1,bcd2,bcd3,out0,out1,out2,out3);
input [15:0] in;
output reg [3:0] bcd0 = 4'b0000;
output reg [3:0] bcd1 = 4'b0000;
output reg [3:0] bcd2 = 4'b0000;
output reg [3:0] bcd3 = 4'b0000;
output reg [6:0] out0 = 7'b0000000;
output reg [6:0] out1 = 7'b0000000;
output reg [6:0] out2 = 7'b0000000;
output reg [6:0] out3 = 7'b0000000;
reg [15:0] temp;
integer i;
always @ (in) begin
bcd0 = 4'b0000;
bcd1 = 4'b0000;
bcd2 = 4'b0000;
bcd3 = 4'b0000;
temp = in;
for(i=15; i>=0; i=i-1) begin
if (bcd3 >= 4'b0101)
bcd3 = bcd3 + 4'b0011;
if (bcd2 >= 4'b0101)
bcd2 = bcd2 + 4'b0011;
if (bcd1 >= 4'b0101)
bcd1 = bcd1 + 4'b0011;
if (bcd0 >= 4'b0101)
bcd0 = bcd0 + 4'b0011;
bcd3 = bcd3 << 1;
bcd3[0] = bcd2[3];
bcd2 = bcd2 << 1;
bcd2[0] = bcd1[3];
bcd1 = bcd1 << 1;
bcd1[0] = bcd0[3];
bcd0 = bcd0 << 1;
bcd0[0] = temp[i];
end
end
always @ (bcd0) begin
if (bcd0==4'b0000) out0 = 7'b0000001;
else if (bcd0==4'b0001) out0 = 7'b1001111;
else if (bcd0==4'b0010) out0 = 7'b0010010;
else if (bcd0==4'b0011) out0 = 7'b0000110;
else if (bcd0==4'b0100) out0 = 7'b1001100;
else if (bcd0==4'b0101) out0 = 7'b0100100;
else if (bcd0==4'b0110) out0 = 7'b0100000;
else if (bcd0==4'b0111) out0 = 7'b0001111;
else if (bcd0==4'b1000) out0 = 7'b0000000;
else if (bcd0==4'b1001) out0 = 7'b0000100;
else out0=7'b0000001;
end
always @ (bcd1) begin
if (bcd1==4'b0000) out1 = 7'b0000001;
else if (bcd1==4'b0001) out1 = 7'b1001111;
else if (bcd1==4'b0010) out1 = 7'b0010010;
else if (bcd1==4'b0011) out1 = 7'b0000110;
else if (bcd1==4'b0100) out1 = 7'b1001100;
else if (bcd1==4'b0101) out1 = 7'b0100100;
else if (bcd1==4'b0110) out1 = 7'b0100000;
else if (bcd1==4'b0111) out1 = 7'b0001111;
else if (bcd1==4'b1000) out1 = 7'b0000000;
else if (bcd1==4'b1001) out1 = 7'b0000100;
else out1=7'b0000001;
end
always @ (bcd2) begin
if (bcd2==4'b0000) out2 = 7'b0000001;
else if (bcd2==4'b0001) out2 = 7'b1001111;
else if (bcd2==4'b0010) out2 = 7'b0010010;
else if (bcd2==4'b0011) out2 = 7'b0000110;
else if (bcd2==4'b0100) out2 = 7'b1001100;
else if (bcd2==4'b0101) out2 = 7'b0100100;
else if (bcd2==4'b0110) out2 = 7'b0100000;
else if (bcd2==4'b0111) out2 = 7'b0001111;
else if (bcd2==4'b1000) out2 = 7'b0000000;
else if (bcd2==4'b1001) out2 = 7'b0000100;
else out2=7'b0000001;
end
always @ (bcd3) begin
if (bcd3==4'b0000) out3 = 7'b0000001;
else if (bcd3==4'b0001) out3 = 7'b1001111;
else if (bcd3==4'b0010) out3 = 7'b0010010;
else if (bcd3==4'b0011) out3 = 7'b0000110;
else if (bcd3==4'b0100) out3 = 7'b1001100;
else if (bcd3==4'b0101) out3 = 7'b0100100;
else if (bcd3==4'b0110) out3 = 7'b0100000;
else if (bcd3==4'b0111) out3 = 7'b0001111;
else if (bcd3==4'b1000) out3 = 7'b0000000;
else if (bcd3==4'b1001) out3 = 7'b0000100;
else out3=7'b0000001;
end
endmodule
Y, por último, mi divisor de reloj lo alimente a cada módulo que requiere un reloj para funcionar correctamente en FPGA:
module clockdivider(clk,clkout);
input clk;
output clkout;
reg [24:0] q = 0;
always @ (posedge clk) begin
q <= q + 1;
end
assign clkout = q[0];
endmodule
Así que ahí está todo. Cuando habilito mi FPGA, muestra números aleatorios aunque no haya presionado ningún botón. ¿Cómo es esto posible? Soy relativamente nuevo en verilog, así que si hay alguna forma de simplificar mi código, lo agradecería mucho. De nuevo, todo simula a la perfección. Gracias a todos
Podría haber muchos problemas ya que parece no estar familiarizado con los FPGA reales, así que los enumeraré a medida que avanzamos:
¿Están todas las entradas externas sincronizadas con el dominio de reloj de su FPGA? Las señales que ingresan pueden hacer una transición en medio de los bordes del reloj FPGA, lo que conduce a la metaestabilidad. La forma de lidiar con esto es pasar la entrada externa a través de una cadena de flip-flops antes de usarla (es decir, copiar la entrada a través de la cadena de señales/registros de cada reloj). Cada vez que se pasa, las posibilidades de que una señal metaestable llegue a su núcleo funcional se vuelven menos probables hasta que es muy pequeña. El mínimo son dos, los equipos de alta confiabilidad pueden usar tres. Esto debería ser obvio, pero lo diré de todos modos: este tiene que ser el PRIMER paso de cualquier señal que ingrese al FPGA. Si desea eliminar el rebote o filtrar la señal (como en el n. ° 2), debe hacerlo DESPUÉS de este paso, ya que la metaestabilidad no permitirá que nada más funcione correctamente.
¿Tus botones externos tienen rebote? Cuando los contactos electromecánicos chocan entre sí, no se acoplarán limpiamente y se conectarán y desconectarán repetidamente hasta que las cosas se estabilicen. La electrónica es lo suficientemente rápida para captar esto. Puede filtrar las entradas de varias maneras en un FPGA. Algunos enfoques son: (a) Una vez que se detecta una transición, ignorar todas las transiciones posteriores durante un período de tiempo (llamado supresión) (b) Solo pasar el estado de entrada para que lo usen otros valores si se ha estabilizado para una cierta cantidad de muestras .
Su FPGA necesita una forma de saber qué señales están asociadas con qué pines. También necesita decirle al FPGA qué tipo de pines deben ser. La forma en que se hace esto depende de su software de síntesis. Esto debe ser correcto.
Su FPGA también necesita saber cuál será la velocidad del reloj para saber cuánto tiempo puede permitir que una señal se propague, ya que todas las señales (especialmente las señales de reloj) deben llegar a sus destinos a tiempo para que el circuito funcione correctamente.
Las señales de reloj deben ir a todas partes en un FPGA y deben llegar a todas partes aproximadamente al mismo tiempo. No enruta los relojes a través de la estructura FPGA normal, ya que es demasiado variable y demasiado lento para ejecutar los relojes a través de toda la lógica configurable de FPGA. El sesgo del reloj será demasiado alto. Los FPGA tienen redes de reloj dedicadas para distribuir el reloj en todo el chip con un retraso de propagación mínimo. Debe utilizarlos si desea distribuir un reloj.
Las palabras clave como "posege" y "negedge" son muy especiales y le dicen al software que se trata de una señal de reloj, por lo que se enruta a través de la red de distribución de reloj dedicada. Esto ocurrirá automáticamente con cada señal asociada con estas palabras clave, pero solo hay unos pocos números de estas en un FPGA. Por lo tanto, no use esta palabra clave para cosas que no sean señales de reloj reales. Si desea ver un flanco ascendente en una señal que no sea de reloj, escriba un módulo separado que compare el estado lógico anterior con el actual para ver si es diferente.
Una señal de habilitación de reloj es una señal que solo sube durante un solo pulso de reloj antes de volver a bajar. Se activa cuando un módulo hará algo pero el módulo no está desconectado. El módulo todavía está cronometrado fuera del reloj FPGA principal (a través de la red de distribución de reloj). Puede crear un módulo que esté sincronizado con el reloj de la FPGA pero emita una activación de reloj cada N ciclos y use esto para activar la activación de eventos en otros módulos. Todos los módulos todavía tienen el reloj de la FPGA y el hecho de que la habilitación del reloj expire después de un ciclo de reloj garantiza que los módulos no activen continuamente cada ciclo de reloj cuando no se supone que lo hagan.
chris stratton
DKNguyen
se necesita ayuda
DKNguyen
Ale..chenski
se necesita ayuda
micro solar
Ale..chenski
alex.forencich
se necesita ayuda
Neil_ES