verilog syntax error with always block - verilog

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.

Related

How to dynamically change value assigned to a vector register

I am a newbie to verilog coding. In my problem statement, I will get number of entries in a sorted table from another module and based on number of entries I need to decide where should I start my binary search
(e.g. Let num_entries be 15, then start index should be 8). Code snippet is given below:
srch_addr <= {{(TBL_AW-msb_loc(num_entries)-1){1'b0}},2'b10, {(msb_loc(num_entries)-1){1'b0}}};
//function to find out MSB 1
integer LOC;
function [3:0] msb_loc;
input [TBL_AW:0] num_entries;
reg found;
//input start;
begin
//if(start = 1)
//begin
found = 1'b0;
msb_loc = 3'b000;
for (LOC=TBL_AW; LOC> 0; LOC=LOC-1)
begin
if((num_entries[LOC] == 1) && !found)
begin
msb_loc = LOC;
found = 1'b1; //TO exit the loop
end
end
//end
end
endfunction
Compiler gives me this error "Illegal operand for constant expression". What can be done to resolve this error?
The replicator 'count' value must be a non-zero, non-X and non-Z constant expression.
{(TBL_AW-msb_loc(num_entries)-1){1'b0}}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This is not a constant.
To get the 'halfway' address you can just the standard mathematical way: divided and round upwards. In this case add one and divide by two:
srch_addr <= (msb_loc(num_entries)+1)>>1;
Coming back to your formula. This part just makes zeros: {(TBL_AW-msb_loc(num_entries)-1){1'b0}} You don't need that.
This part 2'b10, {(msb_loc(num_entries)-1){1'b0}} actually shifts 2'b10 left by "(msb_loc(num_entries)-1)" positions.
This does the same but then without syntax errors:
srch_addr <= 1'b1 << msb_loc(num_entries);
What I can see it does NOT give you the half-way address.
Further:
Your integer LOC; should be inside your function as a local variable.

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 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.

Can't identify unsafe latch behaviour or completeness of case statement in Verilog code

Hey I'm trying to create a small module that reads which button is pressed on a DE2 4x4 matrix board and then display which column and which row is being pressed on the LED's but I'm having a few problems.
Right now the Columns work but not the rows. I think it has something to do with the fact that the LEDS I use to display the row status have "unsafe latch behaviour" but I'm not too sure.
I have also noticed that for my case statement only ever resolves to the default statement and I don't know why and it says it can't check for completeness.
Would anybody be able to help me? If so thank you very much.
module MatrixInput(MInput, MOutput, LEDR);
input [16:10] MInput; //cols
output reg [24:18] MOutput; //rows
output reg [7:0] LEDR;
reg [31:0] counter; //just setting to max size for now
reg [31:0] i;
reg LEDFlag;
initial begin
counter = 0;
i = 7;
LEDFlag = 0;
end
always#(*) begin
case(counter)
0: MOutput = 7'b0x1x1x1;
1: MOutput = 7'b1x0x1x1;
2: MOutput = 7'b1x1x0x1;
3: MOutput = 7'b1x1x1x0;
default: MOutput = 7'b1x0x0x0;
endcase
LEDR[7] = MInput[10];
LEDR[6] = MInput[12];
LEDR[5] = MInput[14];
LEDR[4] = MInput[16];
repeat(4) begin //step through each col
if (LEDR[i] == 1) //set the LED flag on if any of the col LEDS on
LEDFlag = 1;
if (i != 3) //count down from 7 to 3
i = i - 1;
else
i = 7;
end
LEDR[counter] = LEDFlag;
LEDFlag = 0;
if (counter != 4)
counter = counter + 1;
else
counter = 0;
end
endmodule
There are a number of issues here, I'll give you some hints to get started. Number one is you need some kind of clock to make the counter actually count in a way that you can observe. Otherwise it just zips around like an infinite loop in software (actually, the synthesis tool is probably smart enough to see this and not synthesize any logic at all). Second, initial works only in simulation, but it is not a synthesizable construct. When you power up the logic, counter is going to be at some random value which will likely not match any of the 0-3 cases you have defined, which is why it always goes to the default case. You need a reset and to specify a reset value.

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 #*

Resources