How do I use combinational logic while using posedge? - verilog

I am a beginner at Verilog and I am trying to get logic to occur every positive clock edge. However, within this same block, I need combinational logic as I am using a for-loop and changing the value of a register within the for-loop. Currently, the value of this register always shows up as X. Is there a way to get this logic processed within a sequential block? Thanks!
Code:
output reg count;
// ...
always #(posedge clock) begin
integer row;
integer col;
count <= 0;
for (col = 0; col < 4; col = col + 1) begin
if (col == 1)
count <= count + 1;
if (count == 1) begin
//other logic that does not occur because count value = x
end
end
end

Non-blocking assignment works does not assign values immediately to the 'count'. Instead they postpone the assignment till the end of the simulation tick. So, in your case:
initially the value of the count is x.
in your always block count <= 0 will set it to zero some time in the future, but for now it is still x;
in your loop you say count <= count + 1. But the count is still 'x' and count + 1 is also x. You asked it to assign x to the count some time in the future, but after you asked it to assign '0'. So, it will become 'x' at the end of the simulation tick. As a result it will always be 'x'.
your if (count == 1) which will never be true, because count is still 'x'.
The usual way to initialize your count is to have a reset signal, for example
always #(posedge clk) begin
if (reset)
count <= 0;
else
for(...)
if (col == 1)
count <= count + 1;
end
you can add your if (count == 1) inside the always block, but remember the rule of the non-blocking assignments, count will become '1' one clock cycle later in this case. Depending on your requirements you might be able to move it into a separate always block.
always #*
if (count == 1) do something
else do something else

Related

Blocking assignments in always block verilog?

now I know in Verilog, to make a sequential logic you would almost always have use the non-blocking assignment (<=) in an always block. But does this rule also apply to internal variables? If blocking assignments were to be used for internal variables in an always block would it make it comb or seq logic?
So, for example, I'm trying to code a sequential prescaler module. It's output will only be a positive pulse of one clk period duration. It'll have a parameter value that will be the prescaler (how many clock cycles to divide the clk) and a counter variable to keep track of it.
I have count's assignments to be blocking assignments but the output, q to be non-blocking. For simulation purposes, the code works; the output of q is just the way I want it to be. If I change the assignments to be non-blocking, the output of q only works correctly for the 1st cycle of the parameter length, and then stays 0 forever for some reason (this might be because of the way its coded but, I can't seem to think of another way to code it). So is the way the code is right now behaving as a combinational or sequential logic? And, is this an acceptable thing to do in the industry? And is this synthesizable?
```
module scan_rate2(q, clk, reset_bar);
//I/O's
input clk;
input reset_bar;
output reg q;
//internal constants/variables
parameter prescaler = 8;
integer count = prescaler;
always #(posedge clk) begin
if(reset_bar == 0)
q <= 1'b0;
else begin
if (count == 0) begin
q <= 1'b1;
count = prescaler;
end
else
q <= 1'b0;
end
count = count - 1;
end
endmodule
```
You should follow the industry practice which tells you to use non-blocking assignments for all outputs of the sequential logic. The only exclusion are temporary vars which are used to help in evaluation of complex expressions in sequential logic, provided that they are used only in a single block.
In you case using 'blocking' for the 'counter' will cause mismatch in synthesis behavior. Synthesis will create flops for both q and count. However, in your case with blocking assignment the count will be decremented immediately after it is being assigned the prescaled value, whether after synthesis, it will happen next cycle only.
So, you need a non-blocking. BTW initializing 'count' within declaration might work in fpga synthesis, but does not work in schematic synthesis, so it is better to initialize it differently. Unless I misinterpreted your intent, it should look like the following.
integer count;
always #(posedge clk) begin
if(reset_bar == 0) begin
q <= 1'b0;
counter <= prescaler - 1;
end
else begin
if (count == 0) begin
q <= 1'b1;
count <= prescaler -1;
end
else begin
q <= 1'b0;
count <= count - 1;
end
end
end
You do not need temp vars there, but you for the illustration it can be done as the following:
...
integer tmp;
always ...
else begin
q <= 1'b0;
tmp = count - 1; // you should use blocking here
count <= tmp; // but here you should still use NBA
end

while loop inside a for loop

hi guys i wrote a while loop inside a for loop but it is not working is there something wrong with my coding?
always# (posedge clk) begin
if (delay)
D = 1;
else
D = 0;
if (a) begin
for (g=0;g<10;g=g+1) begin
high <= high_in;
low <= low_in;
delay = 0;
while (count == 0) begin // when i simulate the waveform cant come
out and it stuck at here
ws = 1;
count <= D;
delay = 1;
end
delay = 0;
end
end
else begin
//other coding
end
end
If you enter the while loop when count is zero, you have an infinite loop. You've got a non-blocking assignment on count, so it won't update. Look up blocking vs. non-blocking assignments.
I find some basic issues with this code :-
1. Mix and match of blocking and non-blocking in same always block.
2. use of blocking statement in a always block is a problem creator
3. No reset/default value of count, delay outside of loop. although decision making is based on that.
Few advice :-
Try to use for and while loop outside always statement.
try to assign default values for the loop usage.
As suggested by EML, try writing it again. Try to not combine different assignment as far as possible.

How to use two events in an "always" block in verilog

I have two push buttons (using Basys2 rev C board) and I want to increment a register (counter) when I push one of them. I used this:
always #( posedge pb1 or posedge pb2 )
begin
if(count2==9) count2=0;
else count2= count2+1;
end
but when I implemented it (using ISE 9.2), an error appeared:
The logic for does not match a known FF or Latch template.
However when I tried it using just one event (posedge pb1), it worked.
So why did that happen?
The error message means that the target technology (I am guessing in your case is an FPGA or CPLD) doesn't have the physical circuit required to implement the functionality you described with this behavioural code.
One of the important things to consider when writing synthesizable RTL (verilog or VHDL) is you are describing an electronic circuit. You should understand what real world logic you are trying implement (combinatorial logic, registers) before you start coding. In this case, you are describing a register with two separate clocks--something that doesn't exist in any FPGA or ASIC library I've seen. If you can't figure out what you're trying to implement, the chances are the synthesizer can't either.
In other words, not everything you can describe in Verilog can be translated into an actual circuit.
The solution depends on what you want to do - if you require that the counter increments on both pb1 and pb2 rising edges, irrespective of the other pbs state, I would look into solutions which use another (independent) clock (clk in the code below) - something like this:
reg old_pb1, old_pb2;
always # (posedge clk) begin
if (old_pb1 == 0 && pb1 == 1)
if(count2==9) count2 = 0;
else count2 <= count2 + 1;
if (old_pb2 == 0 && pb2 == 1)
if(count2==9) count2 = 0;
else count2 <= count2 + 1;
old_pb1 <= pb1;
old_pb2 <= pb2;
end
If you have no other clock, you could also combine both input signals like in this example:
wire pbs = pb1 | pb2;
always # (pbs) begin
if(count2==9) count2 <= 0;
else count2 <= count2 + 1;
end
Another option would be to use independent counters for the inputs:
always # (posedge pb1)
begin
if(count_pb1==9) count_pb1 <= 0;
else count_pb1 <= count_pb1 + 1;
end
always # (posedge pb2)
begin
if(count_pb2==9) count_pb2 <= 0;
else count_pb2 <= count_pb2 + 1;
end
wire [4:0] count2 = count_pb1 + count_pb2;
All options have their own restrictions, limitations and drawbacks, therefore it depends heavily on what you want to do. Corner cases matter.
Note that I put these example codes together without testing them - please let me know in a comment if you are having trouble with any of them and I look into it.

Verilog generate statement with always#(*) block

I have this generate block below which I think should work, but I am seeing issues with the always #(*) part under the else block. When using VCS, temp_in[i+1][j] is assigned 'x' always. I expect it to be set to '0'. If I instantiate a module/gate instead of always block, like I did for the if part, then it works correctly. Googling for the right syntax for using foreach, generate, always and if within a single block does not yield any useful results. I know the fix is a minor change but I am not that familiar with all the language constructs, so I will appreciate any help.
ceil() is a function which returns an integer. It uses only parameters which are fixed at compile time, so I expect the loop unrolling to happen correctly.
genvar i, j, k;
generate
for (i = 0; i < NUM_STAGES; i = i + 1) begin:gen_stage
for (j = 0; j < (TOTAL_LENGTH/(2**(i+1))); j = j + 1) begin:gen_or
if(j < ceil(i)) begin
for (k = 0; k < CPU_DATA_WIDTH; k = k + 1) begin:gen_bit
msw_mem_out_mux_bit_or U_msw_mem_out_mux_bit_or (
.in_1 (temp_in[i][2*j][k]),
.in_2 (temp_in[i][(2*j)+1][k]),
.out (temp_in[i+1][j][k])
);
end
end else begin
always #(*) begin
temp_in[i+1][j] = {CPU_DATA_WIDTH{1'b0}};
end
end
end
end
endgenerate
An always #* waits until a change occurs on a signal in the inferred sensitivity list. i and j are constants (from the perspective of simulation time when always #* is evaluating), so the your always block has no signals in the sensitivity list.
If using SystemVerilog, change always #* to always_comb which will run at time 0. For Verilog, add an initial block.
Reference: IEEE Std 1800-2012 ยง 9.2.2.2.2 always_comb compared to always #*

verilog syntax error with always block

I am new to verilog.I dont know what the hell is wrong with my code.The program displays the counter value at the given moment from 0H to 16H.
key[2] is the button that will increment the counter, and sw[0] resets the counter.
else if(sw[9:5]==5'b00100)
begin
counter = 0;
hex2 = 7'b1000000;
always#(negedge sw[0],posedge key[2])
begin
if(~sw[0]) counter = 0;
else if(key[2])begin
if(counter == 16'hFFFF) counter = 0;
else counter = counter +1;
end
end
end
The error I get says Verilog HDL syntax near text "always"; expecting ";", or "#", or "end" or an identifier("always" is a reserved keyword), or a system task, or "{", or a sequential statement.
my counter = 0; is defined at the top outside my upper most module as integer counter;
Your help is greatly appreciated.
always block is not allowed in sequentially executed if..else block.
One way you can try is :
#(negedge sw[0],posedge key[2])
This will trigger on any change in above two signals, but it will detect only one change.
Looks like you want to enable the counter when sw[9:5]==5'b00100
Why not try setting a flag here, and then use an always #flag block to implement the running counter.

Resources