How does Verilog interpret multiplication by a single bit? - verilog

I have a conditional 2-bit variable coming in. Based off its value, the current value is either incremented or decremented. By that, I mean:
module verilog_block(clk, cond, incr, curr_val)
input clk;
input [1:0] cond;
input [5:0] incr;
output reg [5:0] curr_val;
always # posedge(clk)
begin
curr_val <= curr_val + (!cond[1] - cond[1]) * incr * cond[0];
end
endmodule
Sorry if I made any mistakes, I haven't checked this specific code, as I am just trying to illustrate my question. If cond[0]==0, I don't want curr_val to change (irrespective of cond[1]). If cond[1]==1, I want curr_val to reduce by incr, and if cond[1]==0, I want curr_val to increment by incr.
I think this works, theoretically, but my goal is to expand this into a much larger code. Therefore, it needs to be optimized. I know that the * operator can be slow and require a lot of resources, but I am not sure if that applies to the case of multiplication with only one bit.
If you can spot a way to make this code optimized for area, please let me know. Thanks a lot.

Any good synthesis tool will optimize multiplication where it can, especially when it involves multiplication by zero or any power of 2. But you've created a very hard to read operation. Why not write it the way you said it:
always # posedge(clk)
begin
if (cond[0]==1)
curr_val <= curr_val + (cond[1]==1) ? -incr : incr;
end

Related

How to assign "all the last bits" automatically in Verilog

Consider this
reg [5:0]assign_me;
reg [11:0]source_of_data;
assign_me <= source_of_data[5:0];
where assign_me always gets the least significant bits of source_of_data. Here the 5 is hardcoded in the last line in the sense that if for some reason the definition of assign_me changes to reg [6:0]assign_me I will have to change the last line. Is there any way to avoid this? Like for example in a pythonic notation something like assign_me <= source_of_data[:0]?
You could use:
assign_me <= source_of_data;
Verilog will assign the LSB's. But, you might get warnings about width mismatch.
A cleaner way is to use a parameter:
parameter WIDTH = 6;
reg [WIDTH-1:0]assign_me;
reg [11:0]source_of_data;
assign_me <= source_of_data[WIDTH-1:0];
When it comes to integral (packed) arrays, Verilog is loosely typed. Verilog will right justify to align LSBs, then make the assignment padding or truncating the MSB. You do not need to select a specific set of bits unless you need to mask bits on either end. Some tools will generate size mismatch warnings, especially around port connections, but the language does not require it.
One thing to be careful of is that selecting bits of a single is always unsigned regardless of the sightedness of the signal as a whole.

Accessing register values in verilog

I initialize a register
reg[1:0] yreg;
and manipulate it a bit, i.e., value from prev. iteration of program is shifted to 1 spot when I add in the new value in the 0 spot
yreg = SIGNAL; //here SIGNAL is an input to the program
And then I want to access the values at the 0 and 1 spots in the register later for a calculation. How can I do this? My initial reaction was yreg[0] and yreg[1] (I normally program in python =) but this is producing an error (line 35 is the line of code that has yreg[0] and yreg[1] in it):
ERROR:HDLCompiler:806 - "/home/ise/FPGA/trapezoid/trapverilog.v" Line 35: Syntax error near "[".
My assumption when I saw this was that it's not the right syntax to use the brackets to access a certain index of the register. How do you properly access the information in an index of a register? I'm having trouble finding information on this.
Sorry for the probably ridiculous question, this is my first time ever using verilog or FPGAs in general.
Full Code
module trapverilog(
input CLK,
input SIGNAL,
input x,
output OUT
);
reg[1:0] yreg;
float sum = 0;
always #(posedge CLK)
begin
yreg = SIGNAL; //should shift automatically...?
sum = ((reg[0] + reg[1])*x/2) + sum; //this is effectively trapezoidal integration
OUT = sum;
end
endmodule
You have a fundamental misunderstanding of how Verilog signals work.
By default, all Verilog signals are single bits. For example, in your code, SIGNAL, x, and out are all one bit wide. They cannot store a number (other than 0 or 1).
Specifying a width when you define a signal (like reg [1:0] yreg) controls how many bits are used to represent that signal. For instance, yreg is a two-bit signal. This does not mean that it "shifts automatically"; it just means that the signal is two bits wide, allowing it to be used to represent numbers from 0 to 3 (among other things).
I would strongly advise that you work through a course in digital electronics design. Verilog programming is very different from procedural programming languages (such as Python), and you will have a hard time making sense of it without a solid understanding of what you are actually building here.
Apparently as per this answer using brackets to get a certain index of a register is correct. I just forgot to call the variable properly - I was calling reg[0] instead of yreg[0]. Changing this fixed the error.

assign real value to wire in Verilog

Hi I have a simple verilog statements where I want to transfer value at real net to a wire using assign statement. However I see a wire at "x" all the time regardless of the value of a real variable. Here is a snapshot of a sample code with values annotated at time zero:
QN is a wire and real_QN is of type real.
Any ideas why QN is at "x" even though real_QN is at "0" ?
So for reference, the "real" type in not synthesizeable. Only mentioning it because it might be relevant. As such, this solution isn't synthesizeable either. But it should work in simulation. You can not just assign one to the other in this case. But there is a function that will do it for you.
real someReal;
reg [63:1]someReg;
initial begin
someReal = 21.0 ;
$display("someReal---->%f",someReal);
$display("someReg---->%b",someReg);
#1
someReg = $realtobits(someReal);
$display("someReg---->%b",someReg);
Let me know if that does not work for you.

Always block instead of assign, simulated in FPGA

I am trying to code and synthesize in Verilog. Sometimes I am still getting confused with using Verilog as a typical C like programming language, I am trying to understand if there will be a difference between 2 different codes:
always # (a1,a0,b1,b0)
begin
case ({a1,a0,b1,b0})
4'b0000 : s= 7'b1110111 ;
4'b0001 : s= 7'b1110111 ;
....
....
4'b1110 : s= 7'b0101111 ;
4'b1111 : s= 7'b1111010 ;
endcase
end
and
using the above code logic with assign, instead of always block.
Will the above code generate a latch? In which case would it generate a latch? Will there be any delay difference between using the 2 codes?
PS we are trying to create a 2bit binary multiplier, which outputs to a 7 segm display.
Thank you.
Latches are generated when one or more paths through a conditional statement are unassigned. For example:
reg [1:0] a;
reg b;
always#(*)
case (a)
0: b=0;
1: b=0;
2: b=1;
endcase
would generate a latch, because I did not cover the a=3 case. You can avoid this by either explicitly covering each case (like it appears you have done) or by using the default case.
For assign statements, it depends on how you format them, but you're significantly less likely to accidentally infer a latch. For example, if you you the ternary operation (i.e. assign b = a? 1:0;) both halves of the if are inferred.
As for delay, case vs. assign should create the same netlist, so they should produce similar or identical results, provided they're logically identical.
(As a side note, it's good practice to use always#(*), rather than always # (a1,a0,b1,b0); The synthesis tool can figure out the correct sensitivity list.)

What's included in a verilog always #* sensitivity list?

I'm a bit confused about what is considered an input when you use the wildcard #* in an always block sensitivity list. For instance, in the following example which signals are interpreted as inputs that cause the always block to be reevaluated? From what I understand clk and reset aren't included because they dont appear on the right hand side of any procedural statement in the always block. a and b are included because they both appear on the right hand side of procedural statements in the always block. But where I'm really confused about is en and mux. Because they are used as test conditions in the if and case statements are they considered inputs? Is the always block reevaluated each time en and mux change value? I'm pretty much a noob, and in the 3 Verilog books I have I haven't found a satisfactory explanation. I've always found the explanations here to be really helpful. Thanks
module example
(
input wire clk, reset, en, a, b,
input wire [1:0] mux,
output reg x,y, z
);
always #*
begin
x = a & b;
if (en)
y= a | b;
case(mux)
2'b00: z = 0;
2'b01: z = 1;
2'b10: z = 1;
2'b11: z = 0;
endcase
end
endmodule
Any signal that is read inside a block, and so may cause the result of a block to change if it's value changes, will be included by #*. Any change on a read signal used must cause the block to be re-evaluated, as it could cause the outputs of the block to change. As I'm sure you know, if you hadn't used #* you'd be listing those signals out by hand.
In the case of the code you've provided it's any signal that is:
Evaluated on the right hand side of an assignment (a and b)
Evaluated as part of a conditional (en and mux)
...but it's any signal that would be evaluated for any reason. (I can't think of any other reasons right now, but maybe someone else can)
clk and reset aren't on the sensitivity list because they aren't used. Simple as that. There's nothing special about them; they're signals like any other.
In your example, the following signals are included in the implicit sensitivity list:
a
b
en
mux
clk and reset are not part of the sensitivity list.
This is described completely in the IEEE Std for Verilog (1800-2009, for example). The IEEE spec is the best source of detailed information on Verilog. The documentation for your simulator may also describe how #* works.
The simplest answer depends on if you are writing RTL, or a testbench. If you are writing RTL then you should try to forget about the concept of Sensitivity lists, as they don't really exist. There is no logic that only updates when an item on the list is triggered. All sensitivity lists can do in RTL is cause your simulation and actual circuit to differ, they don't do anything good.
So, always use "always #*" or better yet "always_comb" and forget about the concept of sensitivity lists. If the item in the code is evaluated it will trigger the process. Simple as that. It an item is in an if/else, a case, assigned to a variable, or anything else, it will be "evaluated" and thus cause the process to be triggered.
But, just remember, in digital circuits, there is no sensitivity list.

Resources