Verilog Assignment nth iteration - verilog

I have the following code:
always # (clk) begin
for (1=0,i<150, i++) begin
abc[i] = xyz[i];
end
end
Question: If I want to get value of abc[8] (set of 8th iteration with the assign statement), how can I do that?
I did like below:
reg [31:0] abc;
wire [31:0] jkl;
always # (clk) begin
for (1=0,i<150, i++) begin
abc[i] = xyz[i];
end
end
assign jkl = abc[8];
$display ("value is 0x%x\n", jkl);
I have an error, can you please suggest me something?

Seems like you have misunderstanding of how for loops work in Verilog. In Verilog, you are defining hardware which operates in parallel at all times. The for loop is just a handy way to express something. You should not think of it as iterating.
What your expression means is something like this:
Assign abc[i] from xyz[i] for all values of i from 0 to 149, on every clock cycle
If you really want to iterate, you need to create a counter which increments on each cycles and use that instead of a for loop.
Now, you are probably getting error messages due to some of your other errors:
You cannot put a $display outside of a sequential code block. That is, it needs to be inside an always or forever block or similar.
You are assigning jkl (a 32-bit value) from abc[8] which is a single bit
You are assigning abc[0] to abc[149] in the for loop, but abc is only 32-bits wide

Related

Im trying to make a right/left shifter using verilog but my output is xxxxx

module MyProject(A,B,k,right,F);
input [31:0]A;
input [31:0]B;
input [4:0]k;
input right;
output reg [31:0]F;
reg [31:0]F1;
integer i,j;
initial
begin
assign F1=(A&~B)+(~A&B);
for(j=0;j<k;j=j+1)
begin
if(right==1)
begin
for(i=0;i<32;i=i+1)
begin
F1[i]=F1[i+1];
if(i==31)
F1[i]=0;
end
end
else if(right==0)
begin
for(i=31;i>-1;i=i-1)
begin
F1[i]=F1[i-1];
if(i==0)
F1[i]=0;
end
end
end
for(i=0;i<32;i=i+1)
F[i]=F1[i];
//F=F1;
end
endmodule
Your code got a little jumbled in the question - here's the original question with the Enter Code Here lines replaced with new lines:
module MyProject(A,B,k,right,F);
input [31:0]A;
input [31:0]B;
input [4:0]k;
input right;
output reg [31:0]F;
reg [31:0]F1;
integer i,j;
initial
begin
assign F1=(A&~B)+(~A&B);
for(j=0;j
begin
if(right==1)
begin
for(i=0;i<32;i=i+1)
begin
F1[i]=F1[i+1];
if(i==31)
F1[i]=0;
end
end
else if(right==0)
begin
for(i=31;i>-1;i=i-1)
begin
F1[i]=F1[i-1];
if(i==0)
F1[i]=0;
end
end
end
for(i=0;i<32;i=i+1)
F[i]=F1[i];
//F=F1;
end
endmodule
I am guessing the objective is to perform a logical operation on the inputs A and B, and then generate a shifted output. I think you are close, but there a few things that should be corrected:
The function just has an initial block, so it gets run once when the simulator starts up, and it never runs again. You didn't mention if the assignment was to create a function that continuously generates output F (i.e. a bunch of gates with no registers) or a function that evaluates "A/B/k/right" on a clock edge, and then generates the output. If you are creating a combinatorial function, when you would need to replace the "initial" with something like "always #*" which will re-run the function every time an input value changes, and you will also need to change the reg's to wires. If you are creating a registered block, you will need to add a clock. You might look at this code for a good example of a clocked shift register.
There is an assign statement inside the initial block. Assign statements represent expressions that are always true in Verilog, so they go outside of procedural blocks. The assign statement assigns a value to a register - assign statements should be paired with wires.
The procedural code uses the F1 register as the input and output, but F1 has already been assigned a value. I would suggest breaking this up into two steps, mainly compute (A&~B)+(~A&B) and assign that to F1. Then write a procedural block to perform the shifting of F1 into the output, which could be a wire or register depending on the answer to #1
Hope that helps.

Verilog for error while synthesizing

When I try to synthesize my verilog project i get the following errors:
ERROR:Xst:2634 - "shiftman.v" line 15: For loop stop condition should depend on loop variable or be static.
ERROR:Xst:2634 - "shiftman.v" line 22: For loop stop condition should depend on loop variable or be static.
I think I understand what causes the error, but I can't find a way to fix it.
module shiftman(in,sh,out);
input[47:0] in;
input[8:0] sh;
output[47:0] out;
reg[47:0] out;
reg[7:0] r;
reg i;
always#(in or sh)
begin
r=sh[7:0];
out=in;
if(sh[8]==0)
for(i=0; i<r; i=i+1)
begin
out[23:0]={1'b0,out[23:1]};
end
else
for(i=0; i<r; i=i+1)
begin
out[47:24]={1'b0,out[47:25]};
end
end
endmodule
The reason your synthesis is failing is because you cannot uses variable-iteration loops in synthesizable code. When synthesizing, the tool will attempt to unroll the loop, but it cannot do this if the termination condition for the loop is not static or determinable at synthesis. Your condition i <= r is such a condition as we cannot unroll the loop without knowing r, which is an input to the module and thus, not static.
In order to fix this, youll need to rewrite your code in a way that the synthesis tool can process. By the looks of it, you are simply logically shifting either the top or bottom of in by sh[7:0] depending on sh[8]. In order to do this, you don't need looping at all, but can use the >> (logical right shift operator). So, your always block would look more like this:
always #(*) begin
out = in;
if (sh[8])
out[47:24] = in[47:24] >> sh[7:0];
else
out[23:0] = in[23:0] >> sh[7:0];
end

Getting strange error in verilog (vcs) when trying to use if/else blocks

I am trying to write an "inverter" function for a 2's compliment adder. My instructor wants me to use if/else statements in order to implement it. The module is supposed to take an 8 bit number and flip the bits (so zero to ones/ones to zeros). I wrote this module:
module inverter(b, bnot);
input [7:0] b;
output [7:0]bnot;
if (b[0] == 0) begin
assign bnot[0] = 1;
end else begin
assign bnot[0] = 0;
end
//repeat for bits 1-7
When I try and compile and compile it using this command I got the following errors:
vcs +v2k inverter.v
Error-[V2005S] Verilog 2005 IEEE 1364-2005 syntax used.
inverter.v, 16
Please compile with -sverilog or -v2005 to support this construct: generate
blocks without generate/endgenerate keywords.
So I added the -v2005 argument and then I get this error:
vcs +v2k -v2005 inverter.v
Elaboration time unknown or bad value encountered for generate if-statement
condition expression.
Please make sure it is elaboration time constant.
Someone mind explaining to me what I am doing wrong? Very new to all of this, and very confused :). Thanks!
assign statements like this declare combinatorial hardware which drive the assigned wire. Since you have put if/else around it it looks like you are generating hardware on the fly as required, which you can not do. Generate statements are away of paramertising code with variable instance based on constant parameters which is why in this situation you get that quite confusing error.
Two solutions:
Use a ternary operator to select the value.
assign bnot[0] = b[0] ? 1'b0 : 1'b1;
Which is the same as assign bnot[0] = ~b[0].
Or use a combinatorial always block, output must be declared as reg.
module inverter(
input [7:0] b,
output reg [7:0] bnot
);
always #* begin
if (b[0] == 0) begin
bnot[0] = 1;
end else begin
bnot[0] = 0;
end
end
Note in the above example the output is declared as reg not wire, we wrap code with an always #* and we do not use assign keyword.
Verliog reg vs wire is a simulator optimisation and you just need to use the correct one, further answers which elaborate on this are Verilog Input Output types, SystemVerilog datatypes.

Generate statement inside verilog task

I want to use generate statement inside a task. The following code is giving compile errors (iverilog).
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] MEM;
integer i;
begin
generate
genvar j;
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
end
endtask // write_mem
I also tried putting generate just after the line integer i, but still its producing errors. Any thoughts?
EDIT: I also tried putting genvar declaration between begin and generate statement in the above code. Its still producing compiler errors
Thanks in advance,
Jay Aurabind
What you are trying is not possible - a generate region (generate..endgenerate block) is only allowed in the module description (aka "top level"), i.e. the same level where you have parameters, wires, always- and inital-regions, etc. (see Syntax 12-5 in the IEEE Std. 1364-2005). Within a task a generate region is e.g. as invalid as an assign statement.
However, you can use a non-generate for-loop in a task (this is also synthesizeable).
Either way, you can not count from 0 to i-1 in synthesizeable code as 'i' is not constant. Also note that j++ is not valid verilog, you must write j=j+1 instead. Finally you probably want to use a nonblocking assignment (<=) instead of a blocking assignment (=), but this depends on how you intent to use this task.
genvars should be defined before the generate statement:
genvar j;
generate
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
Although your usage here does not look like it needs a generate statement a for loop would have done.
As pointed out by #CliffordVienna generate statements are for building hierarchy and wiring based on compile time constants. ie parameters can be changed for reusable code but are constant in a given simulation. Tasks do not contain hierarchy and therefore the use of a generate is invalid.
Any for loop that can be unrolled is synthesizable, some thing like:
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] mem;
integer i = WIDTH / 8; // CONSTANT
begin
for(j=0; j<i;j++) begin
mem[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
end
end
endtask // write_mem
Tasks are synthesizable as long as they do not contain any timing control, which yours does not. From the information given this should be synthesizable.
NB: I would separate data width and addr width, they might be the same now but you might want to move to 8 bit addressing and 16 bit data.

Verilog while error

I have a school project in Verilog and I am very newbie at it. A part of the program is this
integer x;
assign x=1;
**LINE 49** while(x<=9)
begin
assign lastBitsofP=P[1:0];
if(lastBitsofP == 2'b00 || lastBitsofP ==2'b11)
begin
rightShift r1(shiftedValue,P);
end
x=x+1;
end
but I always get this error : "mainModule.v" line 49 expecting 'endmodule', found 'while' ,
You need to stop coding and think about what is going on. You are modelling hardware and connections. When you write assign x = that means "I have a wire and I want you to drive that wire with this value". If you have a module like r1 that you want connected it must be connected always you can't go "oh wait, if this happens just create a multiply unit for me".
You need to instantiate your connections at the start. If you only want the right shifted value sometimes then you can have a statement like assign out = select ? shiftedValue : unshiftedValue; And then you just need to write the logic for select.
And you'll probably want a flip-flop for your output. Something like
reg [31:0] result;
always #(posedge clk)
begin
result <= out;
end

Resources