What kind of assignment is this? - verilog

I have this verilog code from my university course which implements a basic multiplier.
//this is a portion of the code.
reg [16:0] multiplicand_copy;
input [7:0] multiplicand;
multiplicand_copy = {9'd0, multiplicand}; // this line is my question
somewhere in the code there is this assignment using brackets that i can't understand.What kind of assignment is this and what's happening in this line ?I appreciate any help.

reg [16:0] multiplicand_copy;
input [7:0] multiplicand;
multiplicand_copy = {9'd0, multiplicand};
In this code snippet, multiplicand is 8 bits variable and multiplicand_copy is 17 bits variable.
multiplicand_copy = {9'd0, multiplicand}; will do concatenation of 9 zeros and 8 bits of multiplicand and make assignment of 17 bits of multiplicand_copy.

Related

Signed Number Multiplication using Karatsuba Algorithm in Verilog

Tried implementing Karatsuba multiplier for multiplying two binary numbers, the logic below works well for unsigned numbers, but getting incorrect answer when I change one of the inputs to a negative. In the example below a=1010011111000000(equals -88.25) and b= 0001010001000000(equals 20.25). The answer should be 11111001000001001111000000000000(equals:-1787.0625)but I end up getting the incorect answer. Have used fixed point logic, with inputs 16 bits and fraction point 8 bits, output being 32 bits with fraction bits 16.
module karatsuba( input signed [15:0] a,
input signed [15:0] b,
output signed [31:0] out
);
reg [15:0] ac,bd;
reg [31:0] t1;
reg [31:0]t2;
reg [24:0] psum;
initial begin
assign ac = a[15:8]*b[15:8];
assign bd = a[7:0]*b[7:0];
assign t2= bd;
assign t1={ac,16'b0000000000000000};
assign psum = {(a[15:8]+a[7:0])*(b[15:8]+b[7:0])-ac-bd,8'b00000000};
end
assign out= t1+psum+t2;
endmodule
module karatsuba_tb();
reg signed [15:0]a,b;
wire signed [31:0]out;
karatsuba uut(.a(a),.b(b),.out(out));
initial begin
a=16'b0101100001000000;
b=16'b0001010001000000;
end
endmodule
enter image description here
enter image description here
There are two issues pertaining to the signed multiply in the post:
Slices of vector variables (even slices of signed vectors) are treated as unsigned in Verilog. This is because when a slice is taken there is no way to identify the original sign bit, therefore it must be treated as unsigned
The solution is to cast the slices to signed so that Verilog treats them as signed. Like this:
assign ac = signed'(a[3:2]) * signed'(b[3:2]);
Make the line that defines the variable ac,bd to be treated as signed using the signed keyword (default is unsigned).
You will need to propagate these changes to other places in the posted code which have the same issues.
Here is a simplified version of the post using small numbers to illustrate the cast and keyword use:
module karatsuba(
input signed [3:0] a,
input signed [3:0] b
);
reg signed [3:0] ac;
assign ac = signed'(a[3:2]) * signed'(b[3:2]);
endmodule
module karatsuba_tb();
reg signed [3:0]a,b;
karatsuba uut(.a(a),.b(b));
initial begin
a = 4'b1110;
b = 4'b1111;
#1;
//
$display("---------------");
$display("uut.a[3:2] = %b",uut.a[3:2]);
$display("uut.b[3:2] = %b",uut.b[3:2]);
$display("uut.ac = %b",uut.ac);
$display("---------------");
//
$display("uut.a[3:2] = %d",signed'(uut.a[3:2]));
$display("uut.b[3:2] = %d",signed'(uut.b[3:2]));
$display("uut.ac = %d",uut.ac);
$display("---------------");
end
endmodule
The example displays this message at runtime:
---------------
uut.a[3:2] = 11
uut.b[3:2] = 11
uut.ac = 0001
---------------
uut.a[3:2] = -1
uut.b[3:2] = -1
uut.ac = 1
---------------

Fixed-point Signed Multiplication in Verilog

I am designing a signed verilog multiplier which I intend to use multiple times in another module.
My two inputs will be always s4.27 format. 1 bit signed, 4 bits of integer and 27 bits of fraction. My output has to be also in s4.27 format and I have to get the most accurate result out of it.
In C, the following not so perfect code snippet did the job.
int32_t mul(int32_t x, int32_t y)
{
int64_t mul = x;
mul *= y;
mul >>= 27;
return (int32_t) mul;
}
In verilog my simple version of code is given below,
`timescale 1ns/1ps
module fixed_multiplier (
i_a,
i_b,
o_p,
clk
);
input clk;
input signed [31:0] i_a;
input signed [31:0] i_b;
output signed [31:0] o_p;
wire signed [63:0] out;
assign out = i_a*i_b;
assign o_p = out;
endmodule
The above mentioned code has bugs that I know because I am not getting the desired results at all.
So my questions are,
(1) As this line "assign o_result = out;" seems crucial to me, how shall I do my assignments to my final output so that I get the correct and most accurate s4.27 format output? Please note, this output will be fed to an adder and the adder output will be again an input for the multiplier.
Above question being asked, I also tried with xor-ing of sign bits of both inputs and assigning [57:27] bits to final output. Did not suit me and resulted in overflow, while in C same inputs did not give any overflow error.
(2) With C I did not have any problem with fixed-point multiplication while in verilog I guess I am struggling as I am quite a newbie. Any suggestions what things to keep in mind while dealing with signed multiplication/addition?
Below is the testbench code,
`timescale 1ns / 1ps
module tb_mul;
// Inputs
reg clk;
reg [31:0] a;
reg [31:0] b;
// Outputs
wire [31:0] c;
fixed_multiplier mul_i (
.clk(clk),
.i_a(a),
.i_b(b),
.o_p(c)
);
initial begin
$dumpfile("test_mul.vcd");
$dumpvars(1);
$monitor ("a=%h,\tb=%h,\tc=%h",a,b,c);
a = 32'h10000000;
b = 32'h10000000;
$finish();
end
endmodule
Thank you in advance.
Your multiplier does not work like you think it does. Verilog will assume your multiplication will be unsigned, and will compute it as such. You might want to do something like the following:
wire [61:0] temp_out;
assign temp_out = i_multiplicand[30:0] * i_multiplier[30:0];
assign sign = i_multiplicand[31] ^ i_multiplier[31];
assign out = {sign, temp_out[57:37]};

In Verilog, counting and outputting the number of 1's in an 8bit input?

What I am trying to do in my mind is take 8 1-bit inputs and count the 1's. Then represent those 1's.
01010111 should output 0101 (There are five 1's from input)
module 8to4 (in,out,hold,clk,reset);
input [7:0] in; //1 bit inputs
reg [7:0] hold; //possible use for case statement
output [3:0] out; //Shows the count of bits
always #(clk)
begin
out = in[0] + in[1] + in[2] + in[3] + in[4] + in[5] + in[6] + in[7]; //Adds the inputs from testbench and outputs it
end
endmodule
Questions:
Is that the proper way to have 8 1-bit inputs? Or do I need to declare each variable as one bit ex: input A,B,C,D,E,F,G,H;
If my above code is close to being correct, is that the proper way to get out to display the count of 1's? Would I need a case statement?
I'm really new to verilog, so I don't even want to think about a test bench yet.
The way you wrote it is probably the better way of writing it because it makes it easier to parameterize the number of bits. But technically, you have one 8-bit input.
module 8to4 #(parameter WIDTH=8) (input [WIDTH-1:0] in,
output reg [3:0] out,hold,
input clk,reset);
reg [WIDTH-1:0] temp;
integer ii;
always #(clk)
begin
temp = 0;
for(ii=0; ii<WIDTH; i = i + 1)
temp = temp + in[ii];
out <= temp;
end
endmodule
Logically the code is proper.
However you can improve it like the following.
Make out as a reg, because you are using it in a procedural assignment.
Usage of reset. Ideally any code should have reset state, which is missing in your code.
Declare the direction (input/output) for hold, clk & reset port, which is currently not specified.
As dave mentioned, you can use parameters for your code.

verilog multiplication results is zero?

i'm trying to multiply two 32 bit signed fractional number (1 sign bit, 8 integer bit, 23 fraction bit)
the first one is
32'b0_00000001_00000000000000000000000 // 1.00
the 2nd one is
32'b0_00000100_00000000000000000000000 // 4.00
when i do like this for example
output signed[31:0] a;
assign a = 32'b0_00000001_00000000000000000000000 * 32'b0_00000100_00000000000000000000000;
the results is zero? why it isn't 4?
kindly please help me in which part i am mistaken and what should i do. thank you very much
regards
Isaac
Because you are trying to assign a 64 bit value to a 32 bit wire, and Verilog will truncate the value, keeping only the lower 32 bits of the result, which is zero.
To have a proper result, you can do as this:
module mult;
reg [31:0] a = 32'b0_00000001_00000000000000000000000; // 1.0
reg [31:0] b = 32'b0_00000100_00000000000000000000000; // 4.0
reg [63:0] t;
reg [31:0] c;
initial begin
t = a * b;
c = t[54:23];
$display ("%b",c);
$finish;
end
endmodule

adder in verilog

I am designing an adder in Verilog. It will have two inputs of size N and two outputs. The first output has a size of 2N and the second has a size of K.
This is what I have so far:
module adder(
out,
CCR,
inA,
inB
);
parameter N=8,CCR_size=8;
parameter M=2*N;
input [N-1:0] inA,inB;
output [M-1:0] out;
output [CCR_size-1:0] CCR;
reg [N:0] temp;
always #(inA or inB)
begin
temp = inA+inB;
CCR[0] = temp[N];
out[N-1:0]= temp[N-1:0];
out[M-1:N]= 'b0;
end
endmodule
Moved from comment:
However this didn't compile. I have errors in line
CCR[0],out[N-1:0] and out[M-1:N]
# Error: VCP2858 adder.v : (16, 20): CCR[0] is not a valid left-hand side of a procedural assignment.
# Error: VCP2858 adder.v : (17, 28): out[N-1:0] is not a valid left-hand side of a procedural assignment.
# Error: VCP2858 adder.v : (18, 20): out[M-1:N] is not a valid left-hand side of a procedural assignment.
What is wrong with the above code?
Register data types are used as variables in procedural blocks.
A register data type must be used when the signal is on the left-hand side of a procedural assignment.
Since the default type of ports is wire you get an error.
Changing your output ports to type reg should solve the problem.
output reg[M-1:0] out;
output reg[CCR_size-1:0] CCR;
Including the answer from #damage declaring the outputs as reg types, you also have CCR defined as 8 bits wide and then only assign the LSB.
The Bit growth from an Adder is 1 bit over the largest input.
I would implement as:
module adder(
parameter N =8,
parameter CCR_size=8
)(
input [N-1:0] inA,
input [N-1:0] inB,
output [2*N-1:0] out,
output reg [CCR_size-1:0] CCR,
);
reg [n:0] sum;
always #* begin
{CCR, sum} = inA + inB;
end
assign out = sum; //Will Zero pad
endmodule

Resources