Verilog module outputs z's - bit-manipulation

I'm trying to make a parameter and module to AND two numbers together and return a result. However, I seem to be having troubles. My code is as follows:
module main;
reg signed [3:0] x;
reg signed [3:0] y;
wire [3:0] out1;
ander #(.L1(4)) andd(.in1(x), .in2(y), .out(out1));
initial begin
x = 4'b0111;
y = 4'b1110;
$display("%b", out1);
$finish;
end
endmodule
module ander #(parameter L1 = 8)
(input [L1-1:0] in1,
input [L1-1:0] in2,
output wire [L1-1:0] out);
assign out = in2&in1;
endmodule
When I try to run this, the output is "zzzz." Am I doing something wrong?
When I change it to
$display("%b", x&y);
it seems to display just fine.
Do you have any recommendations?

Add a little delay before the $display
initial begin
x = 4'b0111;
y = 4'b1110;
#1; // <-- Add a little delay
$display("%b", out1);
$finish;
end
Verilog does one operation at a time. When inside a procedural block, it will execute every operation within the block until it hits a blocking statement or finishes. In Your case, the assign statement didn't have time to react to the changes in x and y before the initial block called $display and $finish.

If you want a deterministic output, add some delay before your $display:
initial begin
x = 4'b0111;
y = 4'b1110;
#1;
$display("%b", out1);
$finish;
end
This prints 0110.

Related

if-else latch SystemVerilog

i was trying to make a floating point adder in SystemVerilog. When i saw the schematic generated i noticed the presence of a latch. The code is:
module ADDER (
input ieee_effloat In1_ADD, In2_ADD,
input ieee_float A_ADD,
output ieee_float Out_ADD
);
logic [24:0] MantissaSum; //Can generate an overflow, expand at 25 bit
always_comb
begin
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa; //Sum the mantissas
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
assign Out_ADD = '{1'b0, Out_ADD.Exponent, Out_ADD.Mantissa};
endmodule
The types are defined:
`ifndef FPU_MACROFLAG
`define FPU_MACROFLAG
package FPU_DEFINITION;
typedef struct packed {
logic Sign;
logic [7:0] Exponent;
logic [22:0] Mantissa;
} ieee_float; //IEEE-753 floating point number rapresentation
typedef struct packed {
logic Eff_Sign;
logic [7:0] Eff_Exponent;
logic [23:0] Eff_Mantissa;
} ieee_effloat; //IEEE-753 floating point number rapresentation effective mantissa
endpackage
import FPU_DEFINITION::*;
`endif
I don't know why this happen, I even closed the if with the else...
The way the latch is created in verilog is when you do not assign all outputs in all branches of an always block. In your situation:
always_comb
begin
you create a default value for MantissaSum. This way it is always assigned.
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa;
now, when you shift it in one of the branches and do not do anything in the other one the previous statement will take care of it.
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
However, here is you problem. your Out_ADD.Exponent is only assigned in the true branch of the if statement. If ManticcaSum[24] is not 1, then its value is supposed to be the same as before. This is a latch behavior.
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
The rest is ok. Out_ADD.Mantissa is assigned in all branches.
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
If this is what you want, you shold split this always block in two: one with always_comb, the second as always_latch, which takes care of the exponent. Or you should review your algorithm.
I believe the problem lies in the line Out_ADD.Mantissa = MantissaSum [22:0]; because in the true and the false condition this statement is executed, I think the synthesized version of your code will infer a latch with the enable = !MantissaSum[24] ( not 100% sure), I think the following change will keep the same logic and remove the latch.. just remove the line Out_ADD.Mantissa = MantissaSum [22:0]; from both the true and the false conditions and instead outside of the always_comb block type the following assign Out_ADD.Mantissa = MantissaSum [22:0];, tell me if that solved your problem

module inside if in verilog

i'm not that much in verilog
i'm trying to call a module inside if statement
i can't find the answer in google or may i didn't understand what should i do with MY CODE
my code is a full adder addition
i need the IF cause i want to add other things
this is my code:
module top (a,b,cin,Cout,Ctemp,sum,clk,X);
input [3:0] a,b;
input X;
input cin,clk;
output reg[3:0] sum;
output reg[2:0] Ctemp;
output reg Cout;
always#(posedge clk)
begin
generate
if (X==1)
add bit0(a[0], b[0], cin, sum[0], Ctemp[0]); //here i need to call add module
add bit1(a[1], b[1], Ctemp[0], sum[1], Ctemp[1]);
add bit2(a[2], b[2], Ctemp[1], sum[2], Ctemp[2]);
add bit3(a[3], b[3], Ctemp[2], sum[3], Cout);
end
endgenerate
endmodule
module add(a, b, cin, sum, cout);
input a;
input b;
input cin;
output sum;
output cout;
assign sum = (~a*~b*cin)+(~a*b*~cin)+(a*~b*~cin)+(a*b*cin);
assign cout = (a*b)+(a*cin)+(b*cin);
endmodule
I'll give some hints. you need to move the module instantiations outside the always block (above or below). Then add additional wire declarations for for the outputs of the module that you will be flopping. I recommend modifying your module instantiation port connections to explicit (connect-by-name) instead of implicit (connect-by-order). This way even of the port order changes, the connectivity will be maintained. Extremely useful for modules with a lot of ports.
The body of your top module should looks something like this:
// ...
add bit3( .a(a[3]), .b(b[3]), .cin(Ctemp[2]), .sum(pre_sum[3]), .cout(pre_cout));
always#(posedge clk)
begin
if (X==1) begin
sum <= pre_sum;
Cout <= pre_cout;
end
end
Other recommendation: Use ANSI style module header; it is less typing and easier to maintain. Non-ANSI style was required for really old simulations before this century. Example:
module top (
input [3:0] a, b,
input cin,
output reg Cout,
output [2:0] Ctemp,
output reg [3:0] sum,
input clk,
input X );

Bit wise 'AND' an array of registers in Verilog

I have an array of registers/buses and a single result bus defined as follows.
wire [BW-1:0] bus_array[NUM-1:0];
reg [BW-1:0] and_result;
where
parameter BW = 4;
parameter NUM = 8;
I wish to perform a BW-bit AND operation on the elements of the array and assign the result to the register and_result.
I try doing this as follows.
integer l;
generate
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
always # (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1)
and_result[m] = and_result[m] & bus_array[l][m];
end
end
endgenerate
However when I simulate this in Modelsim 10.1e, I get the following error.
Error: (vsim-3601) Iteration limit reached at time 2 ns
If I do not use the generate loop, and instead have BW instances of the always # (*) block, the simulation works okay.
I can infer from the error message, that there is a problem with the generate for loop, but I am not able to resolve the problem.
Most likely a bug with ModelSim. Reproducible on EDAplayground with ModelSim10.1d. Works fine with Riviera2014 (After localizing l inside the generate loop). I'm guessing that and_result[m] is somehow in the #(*) sensitivity list, which it shouldn't be.
l needs to be localized or it will be accessed in parallel with the generated always blocks; creating a potential raise condition.
One workaround is to use SystemVerilog and use always_comb instead of always #(*).
A backwarnd compatable solution is to change and_result[m] = and_result[m] & bus_array[l][m]; to if (bus_array[l][m]==1'b0) and_result[m] = 1'b0; which is equivalent code. This keeps and_result[m] only on as a left hand expression so it cannot be in the sensitivity list.
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
integer l; // <== 'l' is local to this generate loop
always # (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1) begin
if (bus_array[l][m]==1'b0) begin
and_result[m] = 1'b0;
end
end
end
Working code here

Reset If-Else statement produces improper results

I've been trying to debug this code, but I cannot find an error in it. However, it's not producing the results that I expect. Here's the code:
module countAdd( btn, reset, thousands, hundreds, tens, ones, led);
//Port Assignments
input [2:0] btn;
input reset;
output [0:7] thousands, hundreds, tens, ones;
output reg led;
//Internal Port Assignments
reg [15:0] sum;
wire [15:0] sumBCD;
reg [15:0] inc;
//Add some stuff
always #(btn or reset)
begin
//Determine which button is active
case(btn)
3'b110: inc <= 1;
3'b101: inc <= 10;
3'b011: inc <= 100;
default: inc <= 0;
endcase
//Add
sum <= sum + inc;
//Should we reset?
if(reset)
begin
sum <= 0;
led <= 1;
end
else
begin
led <= 0;
end
end
//translate sum to sumBCD
binToBCD translate (sum, sumBCD[15:12], sumBCD[11:8], sumBCD[7:4], sumBCD[3:0]);
//display results on SS display
ssFromBCD seg0 (sumBCD[3:0], ones);
ssFromBCD seg1 (sumBCD[7:4], tens);
ssFromBCD seg2 (sumBCD[11:8], hundreds);
ssFromBCD seg3 (sumBCD[15:12], thousands);
endmodule
module binToBCD(sum, thousands, hundreds, tens, ones);
//Port Assignments
input [15:0] sum;
output reg [3:0] thousands;
output reg [3:0] hundreds;
output reg [3:0] tens;
output reg [3:0] ones;
//Begin conversion
integer i;
always #(sum)
begin
//set 1000's, 100's, 10's, and 1's to 0
thousands = 4'd0;
hundreds = 4'd0;
tens = 4'd0;
ones = 4'd0;
for(i = 15; i >= 0; i=i-1)
begin
//Add 3 to columns >= 5
if(thousands >= 5)
thousands = thousands + 3;
if(hundreds >= 5)
hundreds = hundreds + 3;
if(tens >= 5)
tens = tens + 3;
if(ones >= 5)
ones = ones + 3;
//Shift left ones
thousands = thousands << 1;
thousands[0] = hundreds[3];
hundreds = hundreds << 1;
hundreds[0] = tens[3];
tens = tens << 1;
tens[0] = ones[3];
ones = ones << 1;
ones[0] = sum[i];
end
end
endmodule
module ssFromBCD(in, ssOut);
//Port Assignments
input [3:0] in;
output reg [0:7] ssOut;
always #(in)
begin
case(in)
4'b0000: ssOut = 8'b00000011;
4'b0001: ssOut = 8'b10011111;
4'b0010: ssOut = 8'b00100101;
4'b0011: ssOut = 8'b00001101;
4'b0100: ssOut = 8'b10011001;
4'b0101: ssOut = 8'b01001001;
4'b0110: ssOut = 8'b01000001;
4'b0111: ssOut = 8'b00011111;
4'b1000: ssOut = 8'b00000001;
4'b1001: ssOut = 8'b00011001;
default: ssOut = 8'b11111111;
endcase
end
endmodule
This code does not have a testbench; it's instead loaded onto a DE0 board. The idea is that when I press button 1, the sum is supposed to increment by 1. Button 2 increments it by 10, and button 3 increments it by 100. However, the if-else module that encapsulates reset seems to be causing some serious issues.
For instance, when I activate the switch controlling reset, the sum goes to 0 as expected. However, when I try to increment the sum with any of the three buttons, a random number is added - not a 1, 10, or 100.
I've also tried moving the if-else statement before the case statement. Another issue arises. Even if the switch is not activated, the sum is set to 0 as if it ignores the reset condition. However, if I activate the switch, an led turns on. If I turn it off, the led deactivates. However, sum will always be set to 0 regardless of the state of the switch. In this case, though, if I hold a button I see that a 1, 10, or 100 is added to the sum. As soon as I release it, the sum is reset to 0.
Obviously, I believe something is wrong with my if-else statement. I'm not sure why it's not working as I intended. Basically, the logic is as follows:
Determine which button is depressed, assign an increment accordingly
Add the increment value to sum
Should the sum be reset? If yes, set sum to 0.
Note that the last two modules are straightforward. bintoBCD converts the binary string sum into its BCD equivalency. Then ssFromBCD is simply a seven segment display encoder.
This code does not have a testbench
Firstly: Create a testbench! It's not difficult (you can even do it online) and for logical errors it is way faster to debug in simulation than iterating on real hardware.
Secondly: There's no clock in your code. Is this the top level? FPGAs aren't very good at asynchronous design particularly if you are trying to store state (in this case sum). It's not clear what Quartus will have inferred - it might have hooked one of your inputs up to a clock network. You should check the synthesised design in the RTL viewer and go through the synthesis logs.
However, when I try to increment the sum with any of the three buttons, a random number is added
Are you debouncing your switch input? If you aren't then it's very likely that for each button press you'll get a random number of toggles.
Note that your sensitivity list is incorrect here - it should include sum too:
always #(btn or reset)
Ironically (given my opening comment) this won't affect synthesis but would change the behaviour in simulation. You're better off using always_comb (or always #(*) if you're stuck with Verilog).
It depends what you want from the following line:
always #(btn or reset)
Combinatorial logic or Sequential (flip-flops)?
Combinatorial use always #* or always_comb if SystemVerilog is supported. The automatic sensitivity list behaves as combinatorial hardware does cutting down on simulation mismatches.
Also use = Blocking assignments for combinatorial.
Sequential use something like always #(posedge clk or negedge rst) and do use <= This will allow simulation to match hardware.
You issues look like they could be coming from sum <= sum + inc; which is then followed by optional reset statements. The use of <= is incorrect here as it is a combinatorial block with a manual sensitivity list. The scheduling of <= assignments might be throwing some thing off.
As it stands think about what hardware you might expect from :
always #* begin
sum = sum + 1;
end
Against what you get from:
always #(posedge clk or negedge rst_n) begin
if (~rst) begin
sum <= 'b0;
end
else begin
sum <= sum + 1;
end
end
I think if you add a clock to your design and imply a flip-flop for the counter (sum) you will have a big step in the right direction.
A random number is being displayed because sum is continuously being incremented while btn is changing states. A clear start and stop point must be explicit.
Try sampling btn with a clock. In a combination block assign inc. If past_btn equals btn, then assign inc to zero. sum should be assigned in a clocked block.
alwasy #* begin
if (past_btn == btn) inc = 'b0;
else begin
// case(btn) ...
end
end
always #(posedge clk) begin
past_btn <= btn;
if (!reset) sum <= 'b0;
else sum <= sum + inc;
end
If you are still getting random numbers, then the buttons are likely not denounced. In this case add another stage to the button sampling and use only the sampled values.
alwasy #* begin
if (past_btn == sync_btn) inc = 'b0;
else begin
// case(sync_btn) ...
end
end
always #(posedge clk) begin
sync_btn <= btn;
past_btn <= sync_btn;
if (!reset) sum <= 'b0;
else sum <= sum + inc;
end
Always make a test bench and run in simulation. Debugging from FPGA is difficult with logic bugs and implementation issues.

Issues in Ada Concurrency

I need some help and also some insight. This is a program in Ada-2005 which has 3 tasks. The output is 'z'. If the 3 tasks do not happen in the order of their placement in the program then output can vary from z = 2, z = 1 to z = 0 ( That is easy to see in the program, mutual exclusion is attempted to make sure output is z = 2).
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyz is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task task1 is
pragma Priority(System.Default_Priority + 3);
end task1;
task task2 is
pragma Priority(System.Default_Priority + 2);
end task2;
task task3 is
pragma Priority(System.Default_Priority + 1);
end task3;
task body task1 is
begin
x := x + 1;
end task1;
task body task2 is
begin
y := x + y;
end task2;
task body task3 is
begin
z := x + y + z;
end task3;
begin
Put(" z = ");
Put(z);
end xyz;
I first tried this program
(a) without pragmas, the result : In 100 tries, occurence of 2: 86, occurence of 1: 10, occurence of 0: 4.
Then
(b) with pragmas, the result : In 100 tries, occurence of 2: 84, occurence of 1 : 14, occurence of 0: 2.
Which is unexpected as the 2 results are nearly identical. Which means pragmas or no pragmas the output has same behavior.
Those who are Ada concurrency Gurus please shed some light on this topic. Alternative solutions with semaphores (if possible) is also invited.
Further in my opinion for a critical process (that is what we do with Ada), with pragmas the result should be z = 2, 100% at all times, hence or otherwise this program should be termed as 85% critical !!!! (That should not be so with Ada)
A protected object to do the three operations might look something like this. But note, all this does is make sure that the three variables x, y and z are consistent with the order that the updates occurred in; it says nothing about the order.
protected P is
procedure Update_X;
procedure Update_Y;
procedure Update_Z;
function Get_Z return Integer;
private
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
procedure Update_X is
begin
X := X + 1;
end Update_X;
procedure Update_Y is
begin
Y := Y + X;
end Update_Y;
procedure Update_Z is
begin
Z := X + Y + Z;
end Update_Z;
function Get_Z return Integer is
begin
return Z;
end Get_Z;
end P;
On the other hand, to make sure that the three tasks "submit their results" in the proper order, you could rewrite P so that a call to say Update_Y will block until Update_X has been called: Get_Z now has to be an entry with an out parameter rather than a function.
protected P is
entry Update_X;
entry Update_Y;
entry Update_Z;
entry Get_Z (Result : out Integer);
private
X_Updated : Boolean := False;
Y_Updated : Boolean := False;
Z_Updated : Boolean := False;
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
entry Update_X when True is
begin
X := X + 1;
X_Updated := True;
end Update_X;
entry Update_Y when X_Updated is
begin
Y := Y + X;
Y_Updated := True;
end Update_Y;
entry Update_Z when Y_Updated is
begin
Z := X + Y + Z;
Z_Updated := True;
end Update_Z;
entry Get_Z (Result : out Integer) when Z_Updated is
begin
Result := Z;
end Get_Z;
end P;
The three tasks can now have any priority you like. But the task that calls Update_Z will block until the other two have reported.
Well, those pragmas just prioritize the tasks on your system, they don't guarantee any kind of mutual-exclusion on those variables.
There may be some systems where that is enough. However, most Ada implementations these days map Ada tasks to OS threads, and most consumer PC's these days have multiple processors and can spilt their threads among them. There's nothing stopping the OS from scheduling the next lower-priority thread on your second processor while the highest priority thread is running.
This kind of behavior in a program is called a "race condition".
If you want mutual-exlusion on those variables, you need to implement that. Either give control of the variables to one task and use rendezvous to modify them from other tasks, or look into putting them into protected objects. I'd suggest the latter, as rendezvous can be much more difficult to get right. However, if you want to order the calls in a specific way, a master controller task calling rendezvous on the other tasks might be the way to go.
here is a program that is a sequential variant of the above ! .... with just one task (even that can be avoided if I use a single procedure, as suggested by Marc C and T.E.D )
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE
Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyzsimple is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task type xyz;
T: xyz;
task body xyz is
begin
x:= x + 1;
y:= x + y;
z:= x + y + z;
end xyz;
begin Put(" z = ");
Put(z);
end xyzsimple;
This program always gvies output z = 2, but then it doesn't serve to illustrate what I was trying to do. This program is deterministic, not into the paradigm of concurrency ! Further, this program will never exhibit 'RACE CONDITION' that T.E.D had mentioned.