How do I loop states with clock signal? - verilog

I need en to loop between 4 specific given states: 4'b0111 , 4'b1011, 4'b1101, and 4'b1110
This is my code so far
// enable pin cycle
always_ff #(posedge clk) en <=
4'b0111 ? 4'b1011 :
4'b1011 ? 4'b1101 :
4'b1101 ? 4'b1110 :
4'b1110 ? 4'b0111 : en;
From what I can tell, through the hardware, it passes the first stage onto 4'b1011 then stops entirely.
This is most likely caused by the fact that it is a conditional operator; however, from what I understand, it should still loop.
How can I get this working?
And if it's not possible, what's a better way of doing this loop?

The problem with your code is that you need to compare en against all those values.
For example, you need to do something like:
(en == 4'b0111) ? 4'b1011 :
In your code, the first condition is (4'b0111), which is always true. So, en gets the value 4'b1011. en then remains at 4'b1011 on all subsequent clock edges because the first condition ((4'b0111)) always evaluates to true. No other condition is ever evaluated.
You could continue to use the conditional operator, but I think the code would be a lot easier to understand using a case:
always_ff #(posedge clk) begin
case (en)
4'b0111: en <= 4'b1011;
4'b1011: en <= 4'b1101;
4'b1101: en <= 4'b1110;
4'b1110: en <= 4'b0111;
default: en <= 4'b0111;
endcase
end

Related

Verilog code, same structure, same style. How come one works but the other doesnt? Where did I go wrong?

I will get straight to the point. I have a simple counter that is trying to
mimic how a clock works pretty much. I have a module called counter60sec and another one called counter12hr
counter12hr
module counter12hr(reset, hourInc, overflowOut, hrCounter);
input reset;
input hourInc;
output overflowOut;
output [3:0] hrCounter;
reg overflowOut;
reg [3:0] hrCounter; //0'b1101 == 13 hours
//Initialize counter
initial begin
overflowOut = 1'b0;
hrCounter = 4'b0; //once hour reaches 12:59:59, it is supposed to go back to zero
end
//Everytime hrInc is one, increment hrCounter
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
if(reset == 1'b0) begin
overflowOut = 1'b0;
hrCounter = 4'b0;
end
else begin
if (hourInc == 1'b1) begin
hrCounter = hrCounter + 1'b1;
end
end
end
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
hrCounter = 4'b0;
end
end
endmodule
counter60sec
module counter60sec(reset, secInc, minOut, secCounter);
input reset;
input secInc;
output minOut;
output [5:0] secCounter;
reg [5:0] secCounter; //0'b111100 == 60 seconds.
reg minOut;
//Initialize counter
initial begin
minOut = 1'b0;
secCounter = 6'b0;
end
//Everytime secInc is one, increment secCounter
always#(posedge secInc or negedge reset) begin
minOut = 1'b0;
if(reset == 1'b0) begin
minOut = 1'b0;
secCounter = 6'b0;
end
else begin
if (secInc == 1'b1) begin
secCounter = secCounter + 1'b1;
end
end
end
//output minOut to 1 to signal minute increase when secCounter hits 111100 in binary
always#(negedge secCounter) begin
if(secCounter == 6'b111100) begin
minOut = 1'b1;
secCounter = 6'b0;
end
end
endmodule
I have test bench set up for both. The counter60sec one works fine (Where when secCounter is at value of 60, the minOut becomes 1). The counter12hr follows the same concept, but the value of overflowOut never becomes 1.
For my hrCounter conditional statement in counter12hr.v, I have tried both 4'b1101 and 4'b1100 and neither of them worked. (Trying to get the overflowOut to become one when the hrCounter hits 13)
I've spent hours on this, taking break to relax my eyes etc. I still can't see where I am going wrong. Any help would be appreciated
you have a few issues. The main one is that you have a multiple-driven register in both cases:
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
...
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
the overflowOut is driven from 2 different alsways blocks. Same as minOut in the second counter. The order in which those statements are executed is undefined and the resulting value would depend on the order.
You need to restructure your program in such a way that the registers are assigned in a single always block only.
Secondly, i think, that you have a logic bug, assigning your overflow to '0' in the first statement of the first block (same as in the second one).
Thirdly, you should have uset non-blocking assighments '<=' in finlal assignments to the registers.
something like the following should work.
always#(negedge reset or posedge hourInc) begin
if(reset == 1'b0) begin
hrCounter <= 4'b0;
overflowOut <= 1'b0;
end
else begin
if (hrCounter == 4'b1100) begin
overflowOut <= 1'b1;
hrCounter <= 4'b0;
end
else
hrCounter <= hrCounter + 1'b1;
overflowOut <= 1'b0;
end
end
end
Your code is wrong in so many ways...
Most likely it does not work because of:
#(negedge hrCounter)
You are using a vector but #... works with bits. So it will look at the LS bit only.
As to your code:first and most start using a clock. Do not use posedge and negedge of your signals to drive the other signals.
You use:
always#(posedge secInc ...
...
if (secInc == 1'b1)
Remove the 'if'. you have that condition already in your always statement. (But the signal should not be the 'always' anyway, it should be your clock)
Remove the 'initial' sections You have a reset which defines the start condition.
If you have an active low reset reflect that in the name. Call it reset_n or n_reset anything but 'reset' which is per convention a positive reset signal.
If your drive ANYTHING from an edge, be it from a clock or from other signals, use non-blocking assignments "<="
Do not use your generated signal edges to generate other signals. As mentioned use a clock for everything an in the clocking section use an if. Also do not drive signals from different 'always'. You can never know in which order they are executed and then you have a race condition. Thus the clear and the increment are all in one always block:
if (secCounter == 6'b111100) begin
minOut <= 1'b1;
secCounter <= 6'b0;
end
else
secCounter <= secCounter + 6'b000001;
Because of the timing aspect you now have to go to 59 not 60. Which is as you should expect as digital clocks and watches run from 00 to 59, not 00 to 60. You are allowed to use decimal numbers which will, again, make the code more readable: 6'd59, 4'd11

Automatic Verilog code generation issue

I am trying to make the generation of FSM state parametric or automatic.
I tried many ways and seems there is no way to generate the code I need.
Can someone help please?
The Code which I need to generate is part of FSM state machine, for the ST_DATA_CHECK state:
always #(posedge ui_clk_sync_rst or posedge ui_clk)
begin
if (rst) begin
s_app_cmd <= 3'b111;
s_app_en <= 1'b0;
end
end else begin
case (ddr3_state)
ST_INIT :
….
ST_DATA_CHECK : // This part of the code, needs to make parameteric
if (~dwfifo_ef[0]) begin
s_data_write_active[0] <= 1'b1 ;
end else if (~dwfifo_ef[1]) begin
s_data_write_active[1] <= 1'b1 ;
end else if (~dwfifo_ef[2]) begin
s_data_write_active[2] <= 1'b1 ;
end else if (~d_rfifo_ef[0]) begin
s_data_read_active[0] <= 1'b1 ;
end else if (~d_rfifo_ef[1]) begin
s_data_read_active[1] <= 1'b1 ;
end
ST_WRITE :
…
endcase
Please notice that for example dwfifo_ef[0] and dwfifo_ef[1] bits can be 0 at the same time, so that’s why I need to use priority encoder here.
Any help/idea/suggestion is welcomed about how I can make the code parametric.
Thanks
Hayk
You want a for loop with a break statement:
ST_DATA_CHECK :
for (int i=0;i<$bits(dwfifi_ef);i++)
if (~dwfifo_ef[i]) begin
s_data_write_active[i] <= 1'b1 ;
break;
end
#dave_59 has just about solved your problem, but as you say "in my if statement there are 2 signals s_data_write_active and s_data_read_active", how about trying something like this?
ST_DATA_CHECK :
if (|dwfifo_ef == 1'b1)
for (int i=0;i<$bits(dwfifi_ef);i++)
if (~dwfifo_ef[i]) begin
s_data_write_active[i] <= 1'b1 ;
break;
end
else
for (int i=0;i<$bits(d_rfifo);i++)
if (~d_rfifo[i]) begin
s_data_read_active[i] <= 1'b1 ;
break;
end
(I have not tried to compile, simulate or synthsise this, hence my phrase something like.)

How to control a flag in two different procedural blocks in verilog?

I want to rise a flag once I enter procedural block#1, and I want to reset it to zero in another procedural block. Of course I get an error saying the flag is driven by too many drivers. How can I overcome this problem?
Block 1, sensitive to sw (FPGA board switches):
always # (sw)
flag =1;
begin
case (sw)
8'bxxxxxx01: x2= 13'd1249;
8'bxxxxxx10: x2= 13'd2499;
8'bxxxxxx11: x2= 13'd3749;
endcase
end
Block 2, sensitive to CLK:
always # (posedge CLK)
begin
if (counter2 == x2)
begin
counter2 <=0;
flag=0;
end
else
counter2 <= counter2 +1;
end
Assuming all initialization are taken care of.
One method is to have set and reset flags and a FSM which listens to these flags.
localparam S_RESET = 2'b0;
localparam S_SET = 1'b1;
reg state;
always #(posedge clk) begin
case ({flag_set, flag_reset})
2'b00 : state <= state;
2'b01 : state <= S_RESET;
2'b10 : state <= S_SET;
2'b11 : state <= S_SET; //Choose priority
endcase
end
But to note that always # (sw) should be written as always #(*) ie with an automatic sensitivity list. This represents a combinatorial block of hardware, all outputs should be based on inputs (or flipflops).
I hope this makes it clear that:
always # (sw)
flag =1;
does not represent hardware and will not be synthesisable. flag is based on triggering the simulator not a value based on an input.

How to assign the state of a blinking LED in an always block in verilog?

I have this code:
module(
// Set inputs and outputs
output [7:0]ledg
);
reg state;
assign ledg[0] = state;
always # (posedge clock)
begin
// Increment a counter and set state <= to the counter
end
always # (posedge clock)
if (sw[9:5] == 5'b00010)
begin
hex3 <= 7'b1000000;
hex2 <= 7'b1000000;
hex1 <= 7'b1000000;
hex0 <= 7'b1000000;
end
endmodule
I got the LED to blink, but what I want is to be able to have the LED blink when one of the sw[9:5] is ON. However, the way it's coded, the LED is always blinking whether the switch is on or off.
However I am having trouble with the line of code:
assign ledg[0] = state;
The problem, I believe, is that you cannot use the assign keyword in an always block. It has to be assigned outside an always block.
And this is where my problem lies. How do I assign the state of the blinking LED in such a way that it will "start" blinking when it enters the IF condition block, but stops blinking when the switch is down?
Thanks
You can set a flag to create a conditional statement:
assign ledg[0] = (flag == 1'b1) ? state : '0;
You need to change your always block to:
always # (posedge clock)
if (sw[9:5] == 5'b00010)
begin
flag <= 1'b1;
hex3 <= 7'b1000000;
hex2 <= 7'b1000000;
hex1 <= 7'b1000000;
hex0 <= 7'b1000000;
end
else begin
flag <= 1'b0;
end
FYI, you could have used the values of hex0 to hex3, but you don't assign any values to them when the switch is not on. As a result they will synthesize to latches.
Alternatively, you can define ledg[0] as a reg, and just assign to it in the always block without the assign keyword:
module(
// Set inputs and outputs
output reg [7:0]ledg // <----- 'output' to 'output reg'
);
reg state;
//assign ledg[0] = state; <-------Remove this line
always # (posedge clock)
begin
// Increment a counter and set state <= to the counter
end
always # (posedge clock)
if (sw[9:5] == 5'b00010)
begin
hex3 <= 7'b1000000;
hex2 <= 7'b1000000;
hex1 <= 7'b1000000;
hex0 <= 7'b1000000;
ledg[0] <= state;
end
else
ledg[0] <= '0;
endmodule

compiling Verilog code in Quartus

I'm new to verilog HDL and my first project is to implement a simple stopwatch counter using a set of registers. I'm using Altera Quartus.
When I tried compiling the code below, I keep getting an error for each and everyone of the registers. one of the error messages looks like this:
Error (10028): Can't resolve multiple constant drivers for net "sec0[3]" at test_interface.v(127)
Anyone can help? The code simulates fine in Modelsim.
Here's the fragment of code that's causing problems:
always # (posedge clk)
if (qsoutput == 1)
sec0 = sec0 + 1;
else if (sec0 == 4'b1010) begin
sec1 = sec1 + 1;
sec0 = 4'b0000;
end else if (sec1 == 4'b0110) begin
min0 = min0 + 1;
sec1 = 4'b0000;
end else if (min0 == 4'b1010) begin
min1 = min1 + 1;
min0 = 4'b0000;
end else if (min1 == 4'b0110) begin
sec0 = 4'b0000;
sec1 = 4'b0000;
min0 = 4'b0000;
min1 = 4'b0000;
end
Based on your code in Dropbox, you are assigning registers in multiple always blocks. This is illegal for synthesis and cosponsors to the Altera Quartus error message is referring to. A reg type should only be assigned with in one always block.
As an example, sec0 is defined in always #(posedge reset_reg) and the code provided in your question. The code in Dropbox is even worse because you split the counter logic into 4 separate always blocks that assign sec0.
I suggest you put all sec* and min* resisters one clock synchronous always block with an asynchronous:
always(#posedge clk or posedge reset_reg)
begin
if(reset_reg)
begin
// ... asynchronous reset code ...
end
else
begin
// ... synchronous counter code ...
end
end
This paper goes into detail about good verilog coding practices for synthesis:
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
Other issues you will have:
Use non-blocking (<=) when assigning registers. This is discussed in Cliff's paper mentioned earlier.
Get rid of the initial block. I understand some FPGA synthesizers allow it and some ignore it. It is a better practice to have an asynchronous to put everything into a known and predictable value.
The block starting with always # (clk or start_reg or lap_reg or reset_reg) has a bizarre sensitivity list and will likely give you problems. you wither want #(*) if you want combination logic or #(posedge clk or posedge reset_reg) for synchronous flops.
Very rarely dual edge flops are used. The line always # (posedge clk or negedge clk) should be always # (posedge clk) for synchronous or always #(*) for combination logic.

Resources