Verilog Parallel Check and Assignment Across Dissimilar Sized Shift Registers - loops

I'm looking to perform the cross-correlation* operation using an FPGA.
The secific part that I am currently struggling with is the multiplication piece. I want to multiply each 8-bit element of a nx8 shift register that uses excess or offset representation** against a nx1 shift register where I treat 0s as a -1 for the purposes of multiplication.
Now if I was doing that for a single element, I might do something like this for the operation:
input [7:0] dataIn;
input refIn;
output [7:0] dataOut;
wire [7:0] dataOut;
wire [7:0] invertedData;
assign invertedData = 8'd0 - dataIn;
assign dataOut <= refIn ? dataIn : invertedData;
What I'm wondering is how do I scale this to 4, 8, n elements?
My first though was to use a for loop like this:
for(loop=0; loop < n; loop = loop+1)
begin
assign invertedData[loop*8+7:loop*8] = 8'd0 - dataIn[loop*8+7:n*8];
assign dataOut[loop*8+7:loop*8] <= refIn[loop] ? dataIn[loop*8+7:loop*8] : invertedData[loop*8+7:loop*8];
end
This doesn't compile, but that's more or less the idea, and I can't seem to find the right syntax to do what I want.
https://en.wikipedia.org/wiki/Cross-correlation
** http://www.cs.auckland.ac.nz/~patrice/210-2006/210%20LN04_2.pdf

for(loop=0; loop < n; loop = loop+1)
begin
assign invertedData[n*8+7:n*8] = 8'd0 - dataIn[n*8+7:n*8];
assign dataOut[n*8+7:n*8] <= refIn[n] ? dataIn[n*8+7:n*8] : invertedData[n*8+7:n*8];
end
There's a few issues with this, but I think you can make this work.
You can't have 'assign' statements in a for loop. A for loop is meant to be used inside a begin/end block, so you need to change invertedData/dataOut from wire type to reg type, and remove the assign statements.
You generally can't have variable part-selects, unless you use the special constant-width selection operator (verilog-2001 support required). That would look like this: dataIn[n*8 +:8], which means: select 8 bits starting from n*8.
I don't know about your algorithm, but it looks like loop/n are backwards in your statement. You should be incrementing n, not loop variable (or else all statements will be operating on the same part-select).
So considering those points I believe this should compile for you:
always #* begin
for(n=0; n< max_loops ; n=n+1)
begin
invertedData[n*8 +:8] = 8'd0 - dataIn[n*8 +:8];
dataOut[n*8 +:8] <= refIn[n] ? dataIn[n*8 +:8] : invertedData[n*8 +:8];
end
end

Related

System Verilog : wire input for bits part indexing

I have the following code:
module rotate
(
input wire [5:0] index,// tells how many bits to rotate
input [31:0] a,
output [31:0] b
);
I want to implement this assign statement for left rotate:
assign b = {a[32-index-1 : 0], a[31: 32-index] ;
..
..
..
endmodule
The above assignment will not work since wire/logic signals are evaluated during simulation time. I am not able to use parameters.
I tried converting wire to integer and then do assignment, still its not working.
int i1 = index ;
assign assign b[i1] = a[i1] ; // this worked
assign b[i1-1 : 0] = a[i1-1 : 0] ; //not worked
I implemented using for loop inside always_comb but I want a simpler method like concatenation operation etc.
Please help with a suitable way.
I want to do a rotate operation using the concatenation operator and the rotate count will be specified by an input.
You were very close, especially with using two concatenated a's. All you have to do is use the +: operator:
wire [63:0] a_twice = {a,a};
assign b = a_twice[ index +: 32];
The +: operator gives you the bits from index to index+31:
3322222222221111111111 3322222222221111111111
1098765432109876543210987654321010987654321098765432109876543210
<------------- +32 ----------> index=21

Systemverilog localparam array with configurable size

I want to create and define a localparam array in SystemVerilog. The size of the array should be configurable, and the value of each localparam array cell calculated based on its location. Essentially this code:
localparam [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = '{
7*PAGE_SIZE,
6*PAGE_SIZE,
5*PAGE_SIZE,
4*PAGE_SIZE,
3*PAGE_SIZE,
2*PAGE_SIZE,
1*PAGE_SIZE,
0
};
but where the first '7' is replaced with a parameter, and where the parameter initialization is extended to the generic case. So I need a way to loop from 0 to (N-1) and set ADDR_OFFSET(loop) = loop*PAGE_SIZE.
The "obvious" option in SystemVerilog would be generate, but I read that placing a parameter definition inside a generate block generates a new local parameter relative to the hierarchical scope within the generate block (source).
Any suggestions?
For background reference: I need to calculate an actual address based on a base address and a number. The calculation is simple:
real_address = base_address + number*PAGE_SIZE
However, I don't want to have the "*" in my code since I am afraid the synt tool will generate a multiplier, that it will then try to simplify since PAGE_SIZE is a constant value. I am guessing that this can lead to more logic than if I try to do all calculations when generating the localparam array, since this for sure will not give any multiplier in logic.
So with the above localparam definition, I perform the desired address calculation like this:
function [ADDR_BITS-1:0] addr_calc;
input [ADDR_BITS-1:0] base_addr;
input [NBITS-1:0] num;
addr_calc = base_addr + ADDR_OFFSET[num];
endfunction
I think perhaps I found a solution. Wouldn't I essentially accomplish the same by not defining a localparam array, but rather performing the address calculation inside a loop? Since systemverilog sees the loop variable as "constant" (when it comes to generating logic) that seems to accomplish the same? Like this (inside the function I wrote above):
for (int loop1 = 0; loop1 < MAXNUM ; loop1++) begin
if (num == loop1) begin
addr_offset = CSP_PAGE_SIZE*loop1;
end
addr_calc = base_addr + addr_offset;
end
You can set your localparam with the return value of a function.
localparam bit [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = ADDR_CALC();
function bit [7:0] [ADDR_BITS-1:0] ADDR_CALC();
for(int ii=0;ii<$size(ADDR_CALC,1); ii++)
ADDR_CALC[ii] = ii * PAGE_SIZE;
endfunction

Making 2D arrays in Verilog

How do I create an 2D array in Verilog? To be precise, I wanted a 32x100 matrix. Then, how do I define the values of each position of this array?
I tried some stuff I found on the web, but my code needs to be synthesised , simulating is not enought.
Thanks
My attempt so far (I'm new to verilog)
module top(
input a
);
integer i;
reg [31:0] arr[0:99];
initial begin
for(i=0;i<100;i=i+1) begin
assign arr[i] = 22;
end
end
endmodule
Don't use assign within an initial block or always bock. It is procedural assign a simulation feature scheduled for depletion (IEEE Std 1800-2012 C.4 Constructs identified for deprecation).
I'm guessing you are targeting FPGA, you can initialize the array with:
initial begin
for(i=0;i<100;i=i+1) begin
arr[i] = 22;
end
end
IC design ignore initial the code would have to go into the reset condition of an always block. Alternatively if it is a ROM you can use a generate block:
genvar i;
generate
for(i=0;i<100;i=i+1) begin
assign arr[i] = 22;
end
endgenerate

Comparing input signal with array values

As I wrote in my previous post Synthesizable array of XY values
I wanted to create an array in Verilog to store x, y values of a given function.
Now I want to compare an input with x values of this array. If the value is within a specific region I want to save the index of this region and perform an addition with y with the same index. The result goes to the output. The code compiles just fine but its not synthesizes any circuit. The idea later is to use this array to perform linear interpolation and determinate the value of y for a given value of x that its not inside the array. The code is the following. I save the save value for x and y for each index.
module memc (inp,outp,clk,reset);
input[2:0] inp;
input clk, reset;
output[2:0] outp;
reg[2:0] outp;
wire [2:0] test;
reg [5:0] mem[2:0];
always #(posedge clk)
if (reset == 1'b1) begin
mem[0] <= {3'b000, 3'b000};//y0,x0
mem[1] <= {3'b001, 3'b001};//y1,x1
mem[2] <= {3'b010, 3'b010};//y2,x2
end
assign test ={inp<mem[0][2:0],inp<mem[1][2:0],inp<mem[2][2:0]}; //create a test vector by comparing inp with xo,x1,x2
always #(test)
case (test)
3'b1xx: outp=mem[0][2:0]+mem[0][5:3];//if 0<inp<x1
3'b0xx: outp=mem[1][2:0]+mem[1][5:3];//if x1<inp<x2
3'b00x: outp=mem[2][2:0]+mem[2][5:3];//if x2<inp<x3
default: outp=3'b00;
endcase
endmodule
Firstly, all three of your if conditions are the same (inp > mem[0][2:0]). I'm assuming you want
always #(*)
begin
if (inp > mem[0][2:0] ) //index 0
begin
index = 0;
end
else if (inp > mem[1][2:0] ) // index 1
begin
index = 1;
end
else if(inp > mem[2][2:0] ) // index 2
begin
index = 2;
end
end
Secondly, if you are using a large array (hard to be exact on the size), the latency from inp -> outp will get quite long, and you may get timing violations, depending on your clock speed. In that case, you'd be better off building a very simple FSM, and checking one or two entries per clock cycle instead. Just something to keep in mind moving forward.

Verilog, logic OR-ing an entire array

Suppose I have an array like this:
parameter n=100;
reg array[0:n-1];
How would one get the logic-OR value of each and every bit in the array?
The resulted circuit must be combinatorial.
This is a follow up question from this one.
(see discussion below the answer)
I don't know if this meets your design requirements, but you might have a much easier time with a hundred bit bus reg [n-1:0] array; than by using an array of 1 bit wires. Verilog does not have the greatest syntax to support arrays. If you had a bus instead you could just do assign result = |array;
If you must use an array, than I might consider first turning it into a bus with a generate loop, and then doing the same:
parameter n=100;
reg array[0:n-1];
wire [n-1:0] dummywire;
genvar i;
generate
for (i = 0; i < n; i = i+1) begin
assign dummywire[i] = array[i];
end
endgenerate
assign result = |dummywire;
I'm not aware of a more elegant way to do this on arrays.

Resources