SystemVerilog Concatenation - concatenation

I want to use a concatenation to store only the bottom half of a multiplication, however it tells me that my syntax is incorrect
module ALU
(
input signed [15:0] InSrc,
input signed [15:0] InDest,
output logic signed [15:0] OutDest
);
always_comb
begin
OutDest = {InDest*InSrc}[15:0];
end
endmodule
the exact error is Error (10170): Verilog HDL syntax error at ALU.sv(181) near text: "["; expecting ";". Check for and fix any syntax errors that appear immediately before or at the specified keyword.

There is nothing to concatenate, the behavior is a multiply, then take a slice.
Here are two ways to take a slice.
Both produce the same result.
module ALU
(
input signed [15:0] InSrc,
input signed [15:0] InDest,
output logic signed [15:0] OutDest
);
integer product;
always_comb
begin
product = InDest * InSrc;
//
// OutDest = product[15:0];
OutDest = product[0 +: 16];
end
endmodule
A testbench:
module tb ();
integer OutDest;
initial
begin
#1;
$display("Outdest = %0d",OutDest);
end
ALU
ALU(
.InSrc(-1),
.InDest(2),
.OutDest(OutDest)
);
endmodule
Produces:
Outdest = -2
In 4 different simulators on EDA Playground.

Related

Sort issues with TArray<Myrectype> for large numbers

What is the reason why TArray.Sort<Mytype> does not work when I have large numbers in the comparison?
My code is as follows (Delphiy Tokyo):
Interface
Type
RCInd = record
Num : Integer;
Ger : Integer;
Confirmed : Boolean;
Total : Real;
End;
TArrInd = TArray<RCInd>;
Procedure SortInd (Var PArrayInd : TArrInd);
Implementation
Procedure SortInd (Var PArrayInd : TArrInd);
begin
TArray.Sort<RCInd>( PArrayInd,TComparer<RCInd>.Construct
( function (Const Rec1, Rec2 : RCInd) : Integer
begin
Result := - ( Trunc(Rec1.Total) - Trunc(Rec2.Total) );
end )
);
end;
......
When the values of Rec1.Total and Rec2.Total are within a Integer limits, this Sort works fine, BUT when values exceed Integer limits Sort procedure does not work! It generates a non sorted set of data in PArrayInd .
What is going on here?
The problem is one of overflow. The real values overflow the integer type.
The compare function is meant to return negative to indicate less than, positive to. Indicate greater than and zero to indicate equal. Your using arithmetic is the cause of your problem, leading as it does to overflow. Instead use comparison operators.
function(const Rec1, Rec2: RCInd): Integer
begin
if Rec1.Total < Rec2.Total then
Result := 1
else if Rec1.Total > Rec2.Total then
Result := -1
else
Result := 0;
end;
The problem in this question is trying to fit a real value into an integer, but even if you have integer data then arithmetic should not be used for compare functions. Consider the expression
Low(Integer) - 1
This results in overflow. As a general principle, always use comparison operators to implement compare functions.

Multiplication of two double-digit integer with arrays in Fortran

I have tried to write a code for multiplying two double-digit integers like ab * cd using arrays and the preliminary multiplying method. However, when I compile my code and insert any input, the output is a wrong result. I traced my code and I got an appropriate result but in compiling is something different. for example i insert 9 9 9 9 which mean 99 * 99 in this code but the result is 1210 instead of 9801.
program main
! multiplication of two double-digit integer ! array method
implicit none
integer , parameter :: size=2
integer , dimension (size)::A
integer , dimension (size)::B
integer , dimension (size+1)::C
integer , dimension (size+2)::D
integer , dimension (size+2)::E
integer :: i=0,carry1=0,carry2=0,carry3=0
do i=1,size,1
read *,A(i)
end do
do i=1,size,1
read *,B(i)
end do
do i= 3,2,-1
C(i)=B(size)*A(i-1)+carry1
if (C(i)>9)then
C(i)=mod (C(i),10)
carry1 = C(i)/10
else
carry1=0
end if
end do
C(1)=carry1
D(4)=0
do i=3,2,-1
D(i)=B(size-1)*A(i-1)+carry2
if (D(i)>9)then
D(i)=mod (D(i),10)
carry2= D(i)/10
else
carry2=0
end if
end do
D(1)=carry2
do i=4,2,-1
E(i)=D(i)+C(i-1)+carry3
if (E(i)>9) then
E(i)=mod (E(i),10)
carry3=1
else
carry3=0
end if
end do
E(1)=D(1)+carry3
do i=4,1,-1
print*,E(i)
end do
end program main

synthesizable way to load initial values in verilog

I would like to write a module that uses some coefficients that are loaded from a file.
For example:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= 3;
coeffs[1] <= 2;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
I would like to replace the values 3 and 2 by values that I can modify in a file, and provide the file during synthesis.
Obviously, this file will only assign initial values to the registers.
I don't want it to be a block ram, I want it to be like independent registers.
Just to clarify, I need the solution to be very generic, because I intent to use it in many modules that are doing the same thing, but with a different number of coefficients.
Meaning, in the end I wish to have a generic module that receives as a parameter a file name that stores the coefficients, and the number of coefficients and their width, and generates a code using those parameters.
I have tried readmemh but I understood it is only synthesizable to initiate a memory.
Any suggestions?
Thanks.
Here's a suggestion: put the statements initialising the array coeffs in an include file, eg
coeffs.v:
coeffs[0] <= 3;
coeffs[1] <= 2;
code:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
`include "coeffs.v"
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
An include file is included at compile time. So, your synthesiser will insert the contents of the file in the right place in the design. You could then manage the files using your operating system.
I am happy to stand corrected, but apart from 'Trickery' (Include files, define files, running a script generating such before synthesis) I am not aware of any method where you can load plain numbers from a file for synthesis.
I admit it a is problem waiting for a solution.
If only to prevent major embarrassment when your chip comes back from the manufacturer and you find the boot-rom is completely empty.... As if that ever happened where I worked (rolls eyes) Fixing requires only a single (contact) layer change but the lower layer masks are the most expensive).
Using parameter to pass the initial value is better option.
module A
#( parameter INITIAL_VALUE_COEFFS_0 = 3,
parameter INITIAL_VALUE_COEFFS_1 = 2)
( /* ignore it */ );
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= INITIAL_VALUE_COEFFS_0;
coeffs[1] <= INITIAL_VALUE_COEFFS_1;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
endmodule

Why is this variable not considered a constant?

The following is code I wrote is a test bench to simulate a decoder (Verilog HDL). It converts [15:0]IR to [25:0]ControlWord. Literal is a byproduct that is watched as well.
All values from 0-65535 need to be tested for the 16-bit IR variable. In the beginning of the loop, I distinctly assign IR to be 0, but Quartus is telling me that:
Warning (10855): Verilog HDL warning at controluni_tb.v(20): initial value for variable IR should be constant
and as a result I get the following:
Error (10119): Verilog HDL Loop Statement error at controluni_tb.v(23): loop with non-constant loop condition must terminate within 250 iterations
The code for my test bench module is as follows:
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial
begin
clock <= 1'b0;
end
initial
begin
IR <= 16'b0;
end
initial
begin
forever
begin
#1 IR <= IR + 16'b1;
end
end
initial
#65535 $finish;
endmodule
Your code has no errors. initial blocks and system functions ($finish) is used for simulation (not synthesis). That error is related to synthesis. I edited your code for more readability (your clock is always zero!) :
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial begin
clock = 1'b0;
end
initial begin
IR = 16'b0;
forever #1 IR = IR + 16'b1;
end
initial begin
#65535 $finish;
end
endmodule
Instead of using a forever loop, why not just use a for loop for IR? Then the problem is completely bounded.
initial begin
for (IR = 0; IR <= 65535; IR++);
$finish;
end

Concatenation operator in System verilog in a loop

I am trying to do the following : concat = {concat[7:0],clk} inside a forever loop as below :
bit [7:0] concat;
concat = 0;
forever begin
#(posedge clk);
concat = {concat[7:0],clk};
end
I wanted to know what value will it contain after 8 clock iterations at any point of time, if the initial value of concat = 0.
Can it be different from 'hAA or 'h55 at any point of time?
You can not just write concat = 0; you should either assign concat = 0; or
initial begin
concat = 0;
end
Forever can not be used like that, the only two top levels you're allowed are initial and always. You want some thing like the following for a simulation:
initial begin
forever begin
#(posedge clk);
concat = {concat[6:0],clk};
end
end
If you are writing for synthesis then you might want to imply a flip-flop:
always #(posedge clk) begin
concat = {concat[6:0],clk};
end
Once you have fixed your RTL it should be easy to try out on EDA Playground.
Since you have #(posdege clk), clk will always be 1 (or x) when evaluating the RHS of the assignment. So concat will be 'h00, 'h01, 'h03, 'h07, 'h17, ...
Also note that if any other thread tries to read concat on the same positive edge of clk, you have a race condition, so please use a NBA to make the assignment.

Resources