while loop inside a for loop - verilog

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.

Related

Is event trigger synthesizable in verilog?

I am trying to use event triggering in my code (->). Will this get synthesized?
always #(posedge clk) begin
count <= count + 1;
-> x;
end
always #(x) flag = 1;
This is just a sample code. What i want to do is when ever there is an event in the count I want to make the flag high, else it should remain low. In my case the count value increases after every 7 clock cycles. Can i use event triggering for this? If not what can I do to meet my requirement?
Anything you can execute in simulation could be synthesized if tools choose to support it. But most RTL synthesis tools do not support this.
In your simple case, you could replace your event trigger with a task call (or void function call in SystemVerilog).
always #(posedge clk) begin
count <= count + 1;
x;
end
task x;
flag <= 1;
endtask
You should not do this in synthesizable code. While some tools may be able to create equivalent logic, there is almost always an alternative that should be used instead. For example, your code can be rewritten as:
always #(posedge clk) begin
count <= count + 1;
-> x;
end
always #(count) flag = 1;
Some software can maybe synthesize it, but it's not a good code. If you do that, your code is not synchronous.
To be synchronous, all «always» statement must toggle on the same edge of clk.

Wait for A Bit Change in Same Timestep in SV

Here is the code
module m;
bit x;
initial
begin
fork
begin
wait(x == 1);
wait(x == 0);
end
begin
#(x == 1);
#(x == 0);
end
#10 $display("Timeout");
join_any
disable fork;
end
initial
begin
#5;
x = 1;
// Some other Logical Stuff
x = 0;;
end
endmodule
Now in this code, Timeout will happen, because x = 1 & x = 0 is done in the single time step.
One solution is to provide delay between x = 1 & x = 0, then both waits will work fine.
Is there any other method, which can work without providing hard-coded delays?
Note :- With events or semaphores like stuff, this problem can be solved. But I am looking for the answer in terms of coding style or methods, which can work without usage of events.
There are several ways, which you can use here like event, semaphore, flag, etc.
I have added an event in your code. Please find a modified code in below link.
http://www.edaplayground.com/x/Ws3
There are other ways also like,
1. Assign value "1" to x, during its declaration
E.g., bit x=1;
2. Use blocking and nonblocking assignment together in your 2nd initial block.
E.g.,
initial
begin
#5;
x = 1;
// Some other Logical Stuff
x <= 0; // Add non-blocking assignment
end
end
=> The second option is not a good coding practice, but it'll solve your issue as both the assignment statments will work on different regions.

How do I add 1 to a 4 bit wire in Verilog

This seems like it would be simple, but I can't find out how to do this anywhere... All I want to do is add 1 to a 4 bit wire.
Overall, I want to count the number of 1's in a 8 bit variable. Let's call this input inA. The output will be outA. Both are defined as wires; inA is 8 bits where outA is 4 bits.
wire[0:7] inA;
wire[0:3] outA;
I can do a for loop to go through the array:
for (i = 0; i <= 7; i = i + 1) begin
if (inA[i] == 1) begin
outA <= outA + 1;
end
end
But this isn't working.
Can someone please help? I am extremely new to Verilog (and VHDL), so I really have no clue what I am doing wrong.
There are a few ways to do this, here is one option:
reg [0:3] ones;
integer i;
always # (inA) begin
ones = 0;
for (i = 0; i < 8; i = i + 1) begin
ones = ones + inA[i];
end
end
assign outA = ones;
Since you haven't provided your full source code (e.g. the context of the for loop), we can only guess what the problem with that is.
Remember though that non-blocking assignments like outA <= outA + 1 will be scheduled to be executed at the end of the always block, such that the last assignment will override all previous ones.
Since outA (which by the way will have to be a reg if your for loop is embedded in an always block), is only updated after the always block has finished "executing", only inA[7] can cause an increment to outA.
Have a look at my answer here for further information on how always blocks are executed.

Combining Blocking and NonBlocking in Verilog

If I want statements to happen in parallel and another statement to happen when all other statements are done with, for example:
task read;
begin
if (de_if==NOP) begin
dp_op <= 3'b000;
dp_phase = EXEC;
end
else begin
if (de_if==EXEC_THEN) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else if (get_value(de_ctrl1,de_src1)==dp_mem[de_src2]) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else begin
dp_const <= de_src4[0];
dp_src <= de_src4;
dp_op <= {NOP,de_ctrl4};
dp_dest <= de_dest2;
end
#1 dp_phase=READ;
end
end
endtask
In this code I want the statement dp_phase = READ to only be executed after all other assignments are done, how do I do it?
As you can see what I did is wait 1 clock before the assignment but i do not know if this is how its done ...
You need a state machine. That's the canonical way to make things happen in a certain sequence. Try to remember that using a hardware description language is not like a regular programming language...you are just describing the kind of behavior that you would like the hardware to have.
To make a state machine you will need a state register, one or more flip-flops that keep track of where you are in the desired sequence of events. The flip-flops should be updated on the rising clock edge but the rest of your logic can be purely combinational.

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