Verilog Instantiating module inside a always block. Using Adder for multiplication - module

I have a code written for multiplying two 53 bit numbers (written below). I am using shift-add strategy using two other 106 bit registers. This code is working fine. Now I have another 53 bit highly optimized hans carlson adder module written in form:
module hans_carlson_adder(input [52:0] a, b, input c_in, output [52:0] sum, output c_out);
I want to use this adder to do the summation line in for loop (mentioned in code). I am having problem instantiating the adder inside an always block. Plus I dont want to have 106 instances (due to for loop) of this adder. Can you please help with this code
module mul1(
output reg [105:0] c,
input [52:0] x,
input [52:0] y,
input clk,
input state
);
reg [105:0] p;
reg [105:0]a;
integer i;
always #(posedge clk) begin
if (state==1) begin
a={53'b0,x[52:0]};
p=106'b0; // needs to zeroed
for(i=0;i<106;i=i+1) begin
if(y[i]) begin
p=p+a; //THIS LINE NEEDS TO BE REPLACED WITH HANS CARLSONADDER
end
a=a<<1;
end
c<=p;
end else begin
c=0;
end
end
endmodule

First you need to instantiate your adder outside of the always block and connect it to signals:
wire [52:0] b;
reg [5:0] count;
assign b = c[count+7'd52:count];
wire [52:0] sum;
wire c_out;
// Add in x depending on the bits in y
// b has the running result bits that still apply at this point
hans_carlson_adder u0(x, b, 1'b0, sum, c_out);
Now because this is a pipelined adder you are going to need something to kick off the multiplication (I'll call that input start) and something that indicates that the result is available (I'll call that output reg done). You'll want to add them to your mul1 module definition. You can choose a slightly different protocol depending on your needs. It appears that you have something that you've been implementing with the input state. I'm also going to use start to initialize during each calculation so that I don't need a separate reset signal.
reg [52:0] shift;
always #(posedge clk) begin
if (start) begin
done <= 0;
count <= 0;
c <= 106'b0;
shift <= y;
end else if (count < 53) begin
if (shift[0]) begin
c[count+7'd52:count] <= sum;
c[count+7'd53] <= c_out;
end
count <= count + 1;
shift = shift >> 1;
end else begin
done <= 1;
end
end
If you want to make an optimization you could end once the shift signal is equal to 0. In this case the done signal would become high as soon as there were no more bits to add into the result, so multiplying by small values of y would take less cycles.

Related

Reassign result value of a module to one of it's ports in Verilog

I've spend so time implementing an algorithm in Verilog. I have to use float point numbers, so FPU module is used to compute all operations result(+, -, *, /). FPU module instantiation, out is the result of operand (fpu_op) applied on opa, and opb, both 32-bit reg s that represents IEEE754 float numbers:
fpu inst0 (.clk(clk), .rmode(rmode), .fpu_op(fpu_op), .opa(opa), .opb(opb), .out(fout));
I wonder if it's okay to reassign value in always block as in following code:
(rcmp_1 is the result of float comparison made also in a module)
always # (posedge clk) begin
if(rcmp_1[0] & !rcmp_1[1]) begin
opa <= x;
opb <= ftwo;
fpu_op <= mul;
x <= fout;
end
end
So my question is: Will x contain value of fout at the end of if block, and can i futher use computed value of x in other always blocks?
Any help is appreciated. Thanks!
Your always block models a set of 4 registers (without reset) that are enabled by the condition rcmp_1 equal to '01'.
When the condition is true, at the rising edge of the clock the output of the four registers, that are named opa , opb, fpu_op, and x become equal to:
opa equal to the actual value of x
opb equal to ftwo,
fpu_op equal to mul,
the next value of x becomes equal to fout.
So in my opinion the answer to your first question is YES.
Aslo, you can use x (connect the output of the register with output 'x') in other always blocks (circuits). YES also to the second question.
I would write your code as:
assign enable = (rcmp_1==2'b01); // enable signal on 1bit
always # (posedge clk) // register for fpu_op
begin
if(enable) fpu_op <= mul;
end
always # (posedge clk) // register for x
begin
if(enable) x <= fout;
end
always # (posedge clk) // register for opa
begin
if(enable) opa <= x;
end
always # (posedge clk) // register for opb
begin
if(enable) opb <= ftwo;
end

Index out of range error in Verilog, although the register is declared correctly

I am trying to learn Verilog and I have this simple code
module division (
output reg [14:0] A,
input [14:0] D);
reg[4:0] i;
always #(*) begin
for (i = 14; i >= 0; i = i-1) begin
A[0] = D[i];
end
end
endmodule
This returns the error : Index out of range for D.. I have no idea why, since D is declared on that interval. Can you please help me?
I know the code might not make any sense, but I only included the relevant part to the issue.
You have declared i as unsigned, so the expression i >= 0 will always be true.
When i reaches 0, the next iteration is 5'b11111, which is out of range. You should declare i as an integer or add the signed keyword.

4-Bit verilog adder not passing carry bit

I had my 2-bit adder working, except for some reason it is not passing the carry bit. For instance if I use A=1 and B=1 the result S=00, but if either A or B is 1 i get S=1
?i tried printing out the values and it seems my c1 wire in the 2nd module isn't being set, and for some reason Cout is.
So with a input of A=1, B=1, S=00 and Cout=1
when it should be. S=10 and Cout=0
I have only been using Verilog for one day so the syntax is very new to me.
module fulladder(Cin,A,B,S,Cout); // dont forget semi colon
input A,B, Cin; // defaults to 1 bit or [0,0] size
output S, Cout;
wire XOR1,AND1,AND2;
xor(XOR1,A,B);
and(AND1,A,B);
xor(S,Cin,XOR1);
and(AND2,Cin,XOR1);
or(Cout,AND2,AND1);
endmodule
module adder4(Cin,A,B,S,Cout);
input Cin;
input [0:1]A;
input [0:1]B;
output [0:1]S;
output Cout;
wire c1;
fulladder FA1(Cin,A[0:0],B[0:0],S[0:0],c1);
fulladder FA2(c1,A[1:1],B[1:1],S[1:1],Cout);
endmodule
module t_adder;
reg Cin;
reg [1:0]A;
reg [1:0]B;// to declare size, must be on own line, wires can be more than 1 bit
wire [1:0]S;
wire Cout;
adder4 add4bit(Cin,A,B,S,Cout);
initial
begin
A = 1; B = 1; Cin = 0;
#1$display("S=%b Cout = %b",S,Cout);
end
endmodule
You're reversing the bit order in the adder4 module, by declaring the inputs as [0:1], where elsewhere it is [1:0].
Since you reverse the bits, to adder4 it looks like you are adding A=2'b10, B=2'b10, which gives the output you see (3'b100).

Is it possible to declare variables in VHDL with an asterisk?

Quite new to VHDL here, so I'm not entirely sure if this is feasible at all, but here goes:
In my test code for some RAM, I have 2 8-bit std_logic_vector variables wdata_a_v and wdata_b_v. This is all I need for the current setup, but if the ratio of read to write data length changes, I will need more variables of the name wdata_*_v. I'm trying to write the code generically so that it will function for any amount of these variables, but I don't want to declare 26 of them in the code when I will likely only need a few.
It would be nice if there was a way to declare a variable like so:
variable wdata_*_v : std_logic_vector (7 downto 0);
that would, behind the scenes, declare all of the variables that fit this framework so that I could write a loop without worrying about running out of variables.
If there's a way to write a function or procedure etc. to make this work, that would be excellent.
Yes, you can go with a 2d array, recipe:
entity TestHelper is
generic (n: natural range 2 to 255 := 8);
end TestHelper;
architecture behavioral of TestHelper is
type array2d is array (n-1 downto 0) of std_logic_vector(7 downto 0);
begin
process
variable a : array2d;
begin
a(0)(0) := '0';
end process;
end architecture behavioral;
EDIT: Now to use it and create similar code for each of wdata_*_v:
process
variable wdata_v : array2d;
begin
someLabel: for i in 0 to n-1 generate
wdata_v(i)(0) := '0';
x <= y and z;
...
end generate;
x <= '1';
...
anotherLabel: for i in 1 to n generate
...
end generate;
...
end process;

VHDL shift operators?

I'm still trying to get used to some of the quirks of VHDL and I'm having a bit of an issue. First off, I understand that shift operators like rol, ror, ssl, srl, etc. are not synthesizeable. The purpose of this lab is to use a golden model to check against a synthesizeable version of the same thing in a testbench.
Now, the purpose of this program is to convert thermometer code into a 3-bit binary number. So, in other words, thermometer code "00000001" = "001", "00000011" = "010", "00000111" = "011", etc. I'm basically trying to count the number of 1's in the string from right to left. There will be no case where a '0' is placed between the string of 1's, so the vector "00011101" is invalid and will never occur.
I've devised a non-synthesizeable (and so far, non-compile-able) algorithm that I can't figure out how to get working. Basically, the idea is to read the thermometer code, shift it right and increment a counter until the thermometer code equals zero, and then assign the counter value to the 3-bit std_logic_vector. Below is the code I've done so-far.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
begin
while(therm /= "00000000") loop
therm <= therm srl 1;
i = i + 1;
end loop;
bin <= std_logic'(to_unsigned(i,3));
end process golden;
behavioral_g;
here's a version that is synthesisable. the while loop is replaced by a for loop. srl is implemented explicitly:
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : out integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
variable i_internal: integer range 0 to 7;
begin
i_internal:=0;
for idx in 0 to therm'length loop
if therm/="0000000" then
therm<='0' & therm(therm'left downto 1);
i_internal := i_internal + 1;
end if;
end loop;
bin<=std_logic_vector(to_unsigned(i_internal,bin'length));
i<=i_internal;
end process golden;
end behavioral_g;
"... operators like rol, ror, ssl, srl, etc. are not synthesizeable..."
Who says that on who's authority? Have you checked? On which synthesis tool? Was it a recent version, or a version from the early 1990s?
Note that the argument that some tools might not support it is just silly. The fact that some kitchens might not have an oven does not stop people from writing recipes for cake.