我有以下代码:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 04/07/2019 01:20:06 PM
// Design Name:
// Module Name: data_generator_v1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module data_generator_v1 #(
// Define parameters
parameter integer MAPPING_NUMBER = 196 // MAPPING NUMBER IS USED TO SET A SPECIFIC PROBABILITY (16 BIT SCALING --> MAX VALUE = 65535 --> MAPPING NUMBER = 65535 * 0.03 == 196)
)
(
input S_AXI_ACLK , // Input clock
input S_AXI_ARESETN, // RESET signal (active low )
input start_twister,
output reg [1022:0] rec_vector = 1023'd0,
output reg start_decoding = 1'b0 ,
output integer random_vector_bit_errors = 0
);
// Mersenne Twister signals ----------------------------------------------------------------------
wire [63:0] output_axis_tdata ;
wire output_axis_tvalid ;
wire output_axis_tready ;
wire busy ;
wire [63:0] seed_val ;
wire seed_start ;
//--------------------------------------------------------------------------------------------------
// Signals ----------------------------------------------------------------------------------------
wire [3:0] random_nibble ;
integer nibble_count = 256 ; // initialize to 256
reg [1023:0] random_vector = 1024'd0;
reg sample_random_vector = 1'b0;
reg [9:0] bit_errors = 10'd0 ;
// -------------------------------------------------------------------------------------------------
// Generate numbers with a specific probability
assign random_nibble[0] = (output_axis_tdata[15:0] < MAPPING_NUMBER) ? 1 : 0 ;
assign random_nibble[1] = (output_axis_tdata[31:16] < MAPPING_NUMBER) ? 1 : 0 ;
assign random_nibble[2] = (output_axis_tdata[47:32] < MAPPING_NUMBER) ? 1 : 0 ;
assign random_nibble[3] = (output_axis_tdata[63:48] < MAPPING_NUMBER) ? 1 : 0 ;
// Generate a random vector ------------------------------------------------------------------------
always@(posedge S_AXI_ACLK) begin
if(S_AXI_ARESETN == 1'b0 ) begin
random_vector <= 1024'd0 ;
sample_random_vector <= 1'b0 ;
nibble_count <= 256 ;
random_vector_bit_errors <= 0 ;
bit_errors <= 0 ;
end
else begin
if(output_axis_tvalid == 1'b1) begin
if(nibble_count == 0 ) begin
random_vector <= random_vector ;
sample_random_vector <= 1'b1 ;
nibble_count <= 256 ;
random_vector_bit_errors <= bit_errors ;
bit_errors <= 0 ;
end
else begin
nibble_count <= nibble_count - 1 ; // 256*4 == 1024 bit vector
sample_random_vector <= 1'b0 ;
random_vector <= (random_vector << 4) ^ random_nibble ;
random_vector_bit_errors <= random_vector_bit_errors ;
if(nibble_count == 256) begin
case(random_nibble[2:0])
3'b000 : bit_errors <= bit_errors ;
3'b001 : bit_errors <= bit_errors + 1 ;
3'b010 : bit_errors <= bit_errors + 1 ;
3'b011 : bit_errors <= bit_errors + 2 ;
3'b100 : bit_errors <= bit_errors + 1 ;
3'b101 : bit_errors <= bit_errors + 2 ;
3'b110 : bit_errors <= bit_errors + 2 ;
3'b111 : bit_errors <= bit_errors + 3 ;
endcase
end
else begin
case (random_nibble)
4'b0000 : bit_errors <= bit_errors ;
4'b0001 : bit_errors <= bit_errors + 1 ;
4'b0010 : bit_errors <= bit_errors + 1 ;
4'b0011 : bit_errors <= bit_errors + 2 ;
4'b0100 : bit_errors <= bit_errors + 1 ;
4'b0101 : bit_errors <= bit_errors + 2 ;
4'b0110 : bit_errors <= bit_errors + 2 ;
4'b0111 : bit_errors <= bit_errors + 1 ;
4'b1000 : bit_errors <= bit_errors + 1 ;
4'b1001 : bit_errors <= bit_errors + 2 ;
4'b1010 : bit_errors <= bit_errors + 2 ;
4'b1011 : bit_errors <= bit_errors + 3 ;
4'b1100 : bit_errors <= bit_errors + 2 ;
4'b1101 : bit_errors <= bit_errors + 3 ;
4'b1110 : bit_errors <= bit_errors + 3 ;
4'b1111 : bit_errors <= bit_errors + 4 ;
endcase
end
end
end
end
end
// Sample output for the next block
always@(posedge S_AXI_ACLK) begin
if(S_AXI_ARESETN == 1'b0) begin
rec_vector <= 1023'd0 ;
start_decoding <= 1'b0 ;
end
else begin
if(sample_random_vector) begin
rec_vector <= random_vector[1022:0] ;
start_decoding <= 1'b1 ;
end
else begin
rec_vector <= rec_vector ;
start_decoding <= 1'b0 ;
end
end
end
//---------------------------------------------------------------------------------------------------
// //-------------------------------------------------------------------------------------------------------------------------------------
// // STANDARD CLOCK AND RESET
// //output_axis_tdata contains valid data when output_axis_tvalid is asserted
// // output_axis_tready is input into the mersenne twister and we can use this to accept or stop the generation of new data streams
// // busy is asserted when the mersenne twister is performing some computations
// // seed val is not used . It will start will default seed
// // seed start --> not used
// Mersenne twister signal assignment
assign seed_val = 64'd0 ; // used for seeding purposes
assign seed_start = 1'b0 ; // We do not want to assign a new seed so we proceed with the default one
assign output_axis_tready = (S_AXI_ARESETN == 1'b0 || start_twister == 0 ) ? 1'b0 : 1'b1 ; // knob to turn the twister on and off
// MODULE INSTANTIATION
axis_mt19937_64 AMT19937(S_AXI_ACLK,S_AXI_ARESETN,output_axis_tdata,output_axis_tvalid,output_axis_tready,busy,seed_val,seed_start) ;
// //-------------------------------------------------------------------------------------------------------------------------------------
endmodule
这个问题的重点是变量:输出寄存器[1022:0] rec_vector = 1023'd0
我正在使用Mersenne Twister随机数生成器加载此向量。梅森捻线器提供一个64位数字,然后将其映射为4位数字。生成256个这样的4位数字,以填充rec_vector变量中的一行。
现在,我需要选择此二维数组中的每一行,并将其发送以进行解码。这很简单。我可以编写类似rec_vector [row_index]的内容来获取特定行。 在对每一行进行操作之后,我还需要对列执行相同的操作。如何从二维数组中取出列?
请注意,一种简单的方法,例如创建导线和分配它们,如: codeword_column [0] = {rec_vector [0] [0],rec_vector [1] [0] .....,rec_vector [1022] [0]}不起作用。如果执行此操作,则利用率将大打折扣,因为现在我正在对2-d数组进行异步读取,并且由于块ram仅支持同步读取,因此无法将2-d数组推断为block ram。
我真的很感激与此有关的任何投入。感谢您抽出宝贵时间阅读本
答案 0 :(得分:0)
我将给出完整的答案,而不是作为不久前出现的类似问题的评论:Accessing a million bits
实际上,您要问的是“如何在列模式下访问和行中的二维数组”。
仅当您使阵列完全不在寄存器中时,这才有可能。
一旦您拥有很多位,太多了以至于无法存储在寄存器中,您就必须依靠内存。那么,如何访问内存中列中的和行?
答案是非常不令人满意的:“您不能。”
不幸的是,存储器是在长行中实现的,而硬件仅允许您一次只选择一行。要访问列,您必须遍历地址,读一行并选择所需的列。这意味着读取一个列元素需要一个时钟周期。
加快速度的首要方法是使用双端口内存。我知道的FPGA上的存储器都是双端口的。这样您就可以一次从不同的地址进行两次读取。
您还可以通过一次存储两行来加快访问速度。例如一个8x8字节的数组可以存储为16x4,读取使您一次可以访问两行,因此可以访问两个列元素。 (但是收益递减,您将再次得到一大堆寄存器。)
将其与双端口访问相结合,每个时钟周期为您提供四列。
在以上链接中也提到了最后一个警告:FPGA有两种类型的存储器:
后者的存储量最大。因此,如果您编写代码以使用前者,则可以快速发现自己的资源不足。