Giving a matrix as an input to a verilog module - verilog

I am working with the implementation of a Product Code on FPGA . The product code is basically a matrix with the rows and columns being codewords coming from a BCH codebase (BCH(1023,993,3)) . I already have a BCH decoder in Verilog . I want to have a 1023 by 1023 matrix as an input to my Product code decoder and then call upon that module to decode the rows and columns of the product code matrix . The way the decoding process works at a higher level is that , if there are more than 3 errors in a codeword , the BCH decoder module fixes those errors and moves to the next row/ column .
The questions I have are as follows :
1) Is it possible to make the input port as a matrix ?
2) If I need to pipeline the decoding process, do I need to instantiate the BCH decoder 1023 times or is there a better way to do it ?
3) If it is not possible to make the input port as a matrix , do I need to give all the 1023 rows as 1-D vectors like input row1[1022:0] or is there a better way to do that ?
4) If the technique mentioned in step 3 is the only one available, how do I make the column vectors out of those row vectors available as the inputs ?
Thanks in advance. I really appreciate your time and effort .

One can not pass a two dimensional array as a port in Verilog. SystemVerilog supports 2D array as ports of modules.
Here, you need to take a vector and do some pack/unpack operations. One can define macros for the same.
Here is a sample code where PACK_ARRAY macro packs two dimensional array into a single vector. Packing is done based on the width and length provided as input. Similarly, UNPACK_ARRAY unpacks a vector into a two dimensional array.
`define PACK_ARRAY(PK_WIDTH,PK_LEN,PK_SRC,PK_DEST) \
genvar pk_idx; \
generate \
for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) \
begin \
assign PK_DEST[((PK_WIDTH)*pk_idx+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx)] = PK_SRC[pk_idx][((PK_WIDTH)-1):0]; \
end \
endgenerate
`define UNPACK_ARRAY(PK_WIDTH,PK_LEN,PK_DEST,PK_SRC) \
genvar unpk_idx; \
generate \
for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin \
assign PK_DEST[unpk_idx][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx)]; \
end \
endgenerate
module example (
input [(63):0] pack_4_16_in,
output [(31):0] pack_16_2_out
);
wire [3:0] in [0:15];
`UNPACK_ARRAY(4,16,in,pack_4_16_in)
wire [15:0] out [0:1];
`PACK_ARRAY(16,2,in,pack_16_2_out)
// useful code goes here
endmodule // example
As suggested in comments, I believe that you should think of some other approach rather than directly providing 1023*1023 wires as input and output to a single module. As an alternative, you can provide the 1023*1023 matrix elements row wise and store them into internal memory of module.
module example(
input [1023:0] inp, // One can take 'load', 'addr' etc as inputs also
input clk, rst,
output [1023:0] out
);
reg [1023:0] mem [0:1023];
reg [9:0] cnt;
always #(posedge clk) begin
mem[cnt] <= inp;
cnt <= cnt + 1;
end
// Some other logic
endmodule
Here, it will take 1K clocks to load the memory and some glue logic might be required. But this approach will implement a memory inside the module and you will not have hard coded million wires coming as ports.
Refer to this forum discussion for the above code.

Related

FPGA LUTs for combinational logic

I'm having trouble finding direct answers to how FPGA-level LUTs are accessed/implemented in simple modules (I'll provide an example below). Referring to the top answer on this post, https://electronics.stackexchange.com/questions/163961/creating-a-verilog-code-for-4-bit-multiplier-using-lookup-table, the type of LUT I'm trying to understand is the first one listed (FPGA-level).
For example, let's say I had the following module:
module RightRotation
{
input logic clk
input logic [2:0] din
output logic [2:0] dout
};
always#(clk) begin
dout[0] <= din[2];
dout[1] <= din[0];
dout[2] <= din[1];
end
endmodule
If I were to implement this module with a FPGA-level LUT with 3 inputs and 1 output, how many lookups would it take (for instance, is a value looked up every time a value is assigned with a nonblocking statement in the always#)? How would this answer change if I had 4, or 5, or 6 inputs?
After fixing syntax errors, Vivado produces these results for utilization and implementation.
N inputs would use N flops in your design.
Vendor datasheets can help understand look up tables, CLBs, slices etc.
Example here:
https://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf

How to write a module with variable number of ports in Verilog

I would like to write a module with a variable number of inputs, i.e. depending on some parameter, the result would be:
module my_module #(LENGTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data_1
);
//...
endmodule
or
module my_module #(LENGTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data_1,
input [LENGTH-1:0] data_2,
input [LENGTH-1:0] data_3
);
//...
endmodule
Would it be possible to do this in Verilog or Systemverilog or would I have to write a script, let's say in Python, in order to generate the code for a specific module with fixed number of inputs? (it might be more than 1000 inputs)
There are no variable number of ports in SystemVerilog, but you could use a port that is a parameterized array.
module my_module #(int LENGTH, DEPTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data[DEPTH]
);
//...
endmodule
Otherwise, you would need to use a script to generate the code.
Use a two dimensional input with a parameterized size. Added a generate for loop that can be used to set signals individually. Although many operations can be done with smart array operations.
module my_module #(SIZE, LENGTH)(
input clk,
input rst_n,
input [SIZE-1:0][LENGTH-1:0] data_in_array,
output [SIZE-1:0][LENGTH-1:0] data_out_array
);
genvar N;
generate for (N=0; N<SIZE; N++) begin :la_coolOps
//Do cool operations here. For example instantiate a module for every data_in
end
//...
endmodule
Edit:
As Mehran Torki points out: The syntax above will work for SystemVerilog only. Verilog does not allow for multiple packed arrays. Use input [LENGTH*SIZE-1:0] data_in_array.
I would add to these other answers that ports are just groupings of wires. While having 3, 1-bit wires named a, b, and c might be easier to read and understand, there is no physical/logical difference between a single, 3-bit wire abc, where abc[0] corresponds to a, abc[1] corresponds to b, and abc[2] corresponds to c.
So, you can always just expand or shrink a single (or multiple) signal(s) to get however many bits you need. It may not be as neat, but it will work. In the receiving module, you can then part-select the bus in whatever manner you like. So, you could have one really long wire the shrinks or expands (wire [(SOME_PARAM*8)-1:0] my_input_wire), or with SystemVerilog an array (wire [7:0] my_input_wire[0:SOME_PARAM-1])
If this is just testbench/verification code, the other thing you could do in SystemVerilog is use a dynamic array
As others said, there is no direct way to do this, but another workaround is to use SystemVerilog interfaces, where you define all the inputs that you want in the interface definition and inside the module only use the ones that correspond to the parameter. Below is a sample:
module my_module #(LENGTH)(
input clk;
input rst_n;
output o;
interface i_data;
);
logic outValue;
generate
case (LENGTH) //Based on the value of LENGTH, use corresponding data
1: outValue = i_data.data_1;
2: outValue = i_data.data_1 + i_data.data_2;
3: outValue = i_data.data_1 + i_data.data_2 + i_data.data_3;
endcase
endgenerate
always #(posedge clk) begin
if (~rst_n)
o <= '0;
else
begin
o <= outValue;
end
endmodule
You can still use a parameterized array for data and a for-generate loop if your outputs are similar.
With System verilog we can import a package instead of having parameterization and define types in the package to be used in the portlist.
module mymodule
import mymodule_pkg::*;
(
input portlist_t portlist
);
endmodule
And define multiple copies of the package with different variants of the port list and compile whichever version is required. eg
package mymodule_pkg;
localparam LENGTH=5;
typedef struct packed {
logic [LENGTH-1:0] data_1,
logic [LENGTH-1:0] data_2,
logic [LENGTH-1:0] data_3
} portlist_t;
endpackage
As with the interface solution there will be situations where you run into issues, like having different iterations of the module instantiated together.

Use of << in given Verilog code?

In the following Verilog code snippet for implementing an input buffer for a router, in second line, what is the role of 1<<`BUF_WIDTH? I understand that << is the left shift operator, but what happens by left shifting 1 by `BUF_WIDTH? Or is there some other function of << operator?
`define BUF_WIDTH 3 // BUF_SIZE = 16 -> BUF_WIDTH = 4, no. of bits to be used in pointer
`define BUF_SIZE ( 1<<`BUF_WIDTH )
module fifo13( clk, rst, buf_in, buf_out, wr_en, rd_en, buf_empty, buf_full, fifo_counter );
input rst, clk, wr_en, rd_en;
input [7:0] buf_in; // data input to be pushed to buffer
output[7:0] buf_out;// port to output the data using pop.
output buf_empty, buf_full; // buffer empty and full indication
output[`BUF_WIDTH :0] fifo_counter; // number of data pushed in to buffer
reg[7:0] buf_out;
reg buf_empty, buf_full;
reg[`BUF_WIDTH :0] fifo_counter;
reg[`BUF_WIDTH -1:0] rd_ptr, wr_ptr; // pointer to read and write addresses
reg[7:0] buf_mem[`BUF_SIZE -1 : 0];
.
.
.
The entire code is available on http://electrosofts.com/verilog/fifo.html
You assume correctly that << is the left-shift operator, it has no other special meaning.
Shifting the binary representation of a number to the left is equivalent to multiplying the number by 2. So, by shifting 1 to the left N times, you get 2 to the power of N as a result.
The way this is used in the code sample ensures that the buffer has exactly as many entries (BUF_SIZE) as can be uniquely addressed by a pointer of size BUF_WIDTH.
It is the bit shift operator. Think what it does: it shifts bits left. You have a definition of BUF_WIDTH being 3. Then you take 1, shift it by that many places and you get 8 for BUF_SIZE. With three bits you can have 8 different values.
So this is a way to define these two constants so that you only have to change one value. If they would be two constants, someone might accidentally only change one and not the other and this would cause problems.

How to prevent ISE compiler from optmizing away my array?

I'm new to Verilog, ISE, FPGAs. I'm trying to implement a simple design into an FPGA, but the entire design is being optimized away. It is basically an 2D array with some arbitrary values. Here is the code:
module top(
output reg out
);
integer i;
integer j;
reg [5:0] array [0:99][0:31];
initial begin
for(i=0;i<100;i=i+1) begin
for(j=0;j<32;j=j+1) begin
array[i][j] = j;
out = array[i][j];
end
end
end
endmodule
It passes XST Synthesis fine, but it fails MAP in the Implementation process. Two Errors are given:
ERROR:Map:116 - The design is empty. No processing will be done.
ERROR:Map:52 - Problem encountered processing RPMs.
The entire code is being optimized away in XST. Why? What am I doing wrong?
The reason your design is being synthesized away is because you have not described any logic in your module.
The only block in your design is an initial block which is typically not used in synthesis except in limited cases; the construct mainly used for testbenches in simulation (running the Verilog through ModelSim or another simluator).
What you want is to use always blocks or assign statements to describe logic for XST to synthesize into a netlist for the FPGA to emulate. As the module you provided has neither of these constructs, no netlist can be generated, thus nothing synthesized!
In your case, it is not entirely clear what logic you want to describe as the result of your module will always have out equal to 31. If you want out to cycle through the values 0 to 31, you'll need to add some sequential logic to implement that. Search around the net for some tutorials on digital design so you have the fundamentals down (combinational logic, gates, registers, etc). Then, think about what you want the design to do and map it to those components. Then, write the Verilog that describes that design.
EDIT IN LIGHT OF COMMENTS:
The reason you are get no LUT/FF usage on the report is because the FPGA doesn't need to use any resources (or none of those resources) to implement your module. As out is tied to constant 31, it will always have the value of 1, so the FPGA only needs to tie out to Vdd (NOTE that out is not 31 because it is only a 1-bit reg). The other array values are never used nor accesses, so the FPGA synthesized them away (ie, not output needs to know the value of array[0][1] as out is a constant and no other ports exist in the design). In order to preserve the array, you need only use it to drive some output somehow. Heres a basic example to show you:
module top( input [6:0] i_in, // Used to index the array like i
input [4:0] j_in, // Used to index the array like j
output reg [5:0] out // Note, out is now big enough to store all the bits in array
);
integer i;
integer j;
reg [5:0] array[0:99][0:31];
always #(*) begin
// Set up the array, not necessarily optimal, but it works
for (i = 0; i < 100; i = i + 1) begin
for (j = 0; j < 32; j = j + 1) begin
array[i][j] = j;
end
end
// Assign the output to value in the array at position i_in, j_in
out = array[i_in][j_in];
end
endmodule
If you connect the inputs i_in and j_in to switches or something and out to 6 LEDs, you should be able to index the array with the switches and get the output on the LEDs to confirm your design.

Verilog: Passing parameters

I have written two verilog modules. The first one is named topmodule.v and the second one is tx.v. The module topmodule.v pass a parameter data[31:0] to tx.v. I want to take the variables Rmax and Cmax from data[31:0]. After that I want to make Rmax and Cmax to be the width of a bus. Moreover, I want to define a reg matrix called Mat with dimensions Cmax-x-Rmax. I receive the error at the 6th line of the code, "Range must be bounded by constant expression". Kindly help me to resolve this problem. The code is given below.
tx (data, output)
input [31:0] data;
reg [15:0] Rmax, Cmax;
assign Rmax [15:0] = data [31:16];
assign Cmax [15:0] = data [15:0];
reg [Rmax-1:0] Matrix [0:Cmax-1];
The error means pretty much what it says, you cannot have a variable size bus or array.
Declare your matrix to be the maximum size that you ever need, and if you want to use a smaller one, then just use a subsection of it while leaving the rest vacant.
Remember that the width of buses are physical objects, they can't change when the circuit is running, only during synthesis.
If you really want these to be parameters then use that:
module tx #(parameter DATA=32'h00000000) (
// inputs and outputs here
);
reg [DATA[31:16]-1:0] Matrix [0:DATA[15:0]-1];
However, I'm not really sure of what you are trying to accomplish. Show some more pseudo code and get a more useful answer.

Resources