First, thanks for the help yesterday. This time I will document my code correctly.
So, we were tasked with creating a parking meter that would take 4 inputs, one adding 50 seconds, one adding 150 seconds, one adding 250 seconds, and one adding 500 seconds. When there are over 10 seconds remaining, a green led should flash with a period of 2 seconds. When there are less than 10 seconds a red led should flash with period 2 seconds, and when there are no seconds left a red led should flash with period 1 second. Every clock cycle with no input is supposed to subtract one from the meter.
We were tasked with using a debouncer as well a single pulse state machine for the inputs, and a 7 segment display for the outputs. So, I used a state machine for my addition and led flashing, then sent the counter to a binarytoBCD converter and then that one to a BCD to 7 segment display. I'm wondering if I messed up the clock and somehow the simulation ignores my errors, somehow making the FPGA unable to correcly use my code?
without further ado, here are my code snippets:
Top Module
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
my debounce module
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
My single pulse state machine
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
And my module for adding the inputs as well as flashing on and off 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
My module converting BinarytoBCD as well as the 7 segment display output:
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
And finally, my clock divider I feed to every module requiring a clock to run correctly on 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
So there it all is. When I enable my FPGA to it displays random numbers even though I haven't pushed any buttons. How is this possible? I'm relatively new to verilog so if theres any way I can simplify my code it would be greatly appreciated. Again, everything simulates perfectly. Thanks all
Best Answer
There could be many issues since you seem unfamiliar with real FPGAs so I will list them as we go:
Are all external inputs synchronized to your FPGA's clock domain? Signals coming in can transition in the middle of the FPGA clock edges which leads to metastability. The way to deal with this is to pass the external input through a chain of flip-flops before you use it (i.e. copying the input through chain of signals/registers every clock). Each time it is passed, the chances of a metastable signal making it through to your functional core gets less probable until it is vanishingly small. The minimum is two, high reliability equipment might use three. This should be obvious, but I will say it anyways: This has to be the FIRST step of any signal that enters the FPGA. If you want to debounce or filter the signal (like in #2) then you must do it AFTER this step since metastability will not allow anything else to work properly.
Are your external buttons debounced? When electromechanical contacts hit each other they will not mate cleanly and will repeatedly connect and disconnect until things settle down. Electronics are fast enough to pick this up. You can filter inputs in various ways in an FPGA. Some approaches are: (a) Once a transition is detected, ignore all subsequent transitions for a period of time (called blanking) (b) Only pass on the input state to be used by other values if it has stabilized for some amount of samples.
Your FPGA needs a way to know what signals are associated with which pins. It also needs to tell the FPGA what type of pins those need to be. The way this is done is dependent on your synthesis software. This must be correct.
Your FPGA also needs to know what the clock speed will be so that it knows how long it can allow a signal to propagate since all signals (especially clock signals) must arrive at their destinations in time for the circuit to work properly.
Clock signals must go everywhere in an FPGA and must arrive everywhere at approximately the same time. You do not route clocks through the normal FPGA fabric since it is too variable and too slow to run clocks through all the FPGA configurable logic. The clock skew will be too high. FPGAs have dedicated clock networks to distribute the clock across the entire chip with minimum propagation delay. You must use these if you want to distribute a clock.
Keywords like "posedge" and "negedge" are very special and tell the software that this is a clock signal so it gets routed through the dedicated clock distribution network. This will occur automatically with every signal associated with these keywords, but there are only a very few numbers of these on an FPGA. So do not use this keyword for things that are not actual clock signals. If you want to look at a rising edge on a non-clock signal, write a separate module that compares the previous logic state to the current one to see if it is different.
A clock enable signal is a signal that only goes high for a single clock pulse before falling low again. It triggers when a module will do something but the module is not clocked off of it. The module is still clocked off the main FPGA clock (through the clock distribution network). You can make a module that is clocked off the FPGA clock but outputs a clock enable every N cycles and use this to clock enable to trigger events to happen in other modules. All modules are still clocked off the FPGA clock and the fact that the clock enable expires after one clock cycle ensure that the modules don't continually trigger every clock cycle when they're not supposed to.
Sensitivity list rule in HDL