main.v
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
always @ (trigger) begin
temp <= (temp == 7'b1000000) ? 7'b0000001 :
(temp == 7'b0000001) ? 7'b0000010 :
(temp == 7'b0000010) ? 7'b0000100 :
(temp == 7'b0000100) ? 7'b0001000 :
(temp == 7'b0001000) ? 7'b0010000 :
(temp == 7'b0010000) ? 7'b0100000 :
(temp == 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
assign led = temp;
endmodule
The LED doesn't move. It stays on the first LED forever. Is it the trigger that didn't work or did I misunderstand the counter?
This is the working code. I don't know why I have to use if statement, but it works.
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'd0;
end
else begin
if (temp == 7'b1000000) begin
temp = 7'b0000001;
end
else if (temp == 7'b0000001) begin
temp = 7'b0000010;
end
else if (temp == 7'b0000010) begin
temp = 7'b0000100;
end
else if (temp == 7'b0000100) begin
temp = 7'b0001000;
end
else if (temp == 7'b0001000) begin
temp = 7'b0010000;
end
else if (temp == 7'b0010000) begin
temp = 7'b0100000;
end
else if (temp == 7'b0100000) begin
temp = 7'b1000000;
end
else begin
temp = 7'b0000001;
end
trigger <= 'b0;
end
end
assign led = temp;
endmodule
The general structure for a a flip flop for an FPGA is to use an initial to set default values, or for ASIC use an async reset.
Looking at the code exert:
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
We have temp assigned a value in an async reset and an initial, while counter never get initialised. The more standard approach for creating a flip_flop with an async reset:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
end
else begin
counter <= counter + 1;
end
end
The next section of code is:
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
This has a manual sensitivity list which triggers on counter, It is best practise to use an automatic sensitivity list with always @*
. This is also a combinatorial block so it should use blocking assignments (=
).
In verilog a variable should not be assigned a value from multiple blocks, as counter is here. The exception is using initial blocks for default values.
Combinatorial blocks do not hold state, and this block only changes value on a particular count. implying trigger would hold its value, this will imply a latch. Accidentally implied latches can cause a lot of problems as is a bigger topic, than can be discussed here.
Consider doing this instead:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
Your last section of code is again a manual sensitivity list:
always @ (trigger) begin
This is not edge triggered so is a combinatorial section. A combinatorial loop is where the output is a function of itself. temp = some function of temp
.
It looks like you really wanted to make this a flip-flop which updates on the positive edge of trigger:
update I have also just noticed that you used a less than or equals, which will not work in this situation as you have the largest number first.
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 'b0;
end
else begin
temp <= (temp == 7'b1000000) ? 7'b0000001 : // <= changed to ==
(temp <= 7'b0000001) ? 7'b0000010 :
(temp <= 7'b0000010) ? 7'b0000100 :
(temp <= 7'b0000100) ? 7'b0001000 :
(temp <= 7'b0001000) ? 7'b0010000 :
(temp <= 7'b0010000) ? 7'b0100000 :
(temp <= 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
end