在Verilog中查找二维数组中的列

问题描述 投票:0回答:1

我有以下代码:

`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

这个问题的焦点是变量:输出reg [1022:0] rec_vector = 1023'd0

我正在使用Mersenne Twister随机数生成器加载此向量。 mersenne twister提供64位数字,然后映射到4位数字。生成256个这样的4位数以填充rec_vector变量中的一行。

现在,我需要选择这个2-d数组中的每一行并发送它进行解码。这很简单。我可以编写类似rec_vector [row_index]的内容来获取特定的行。在每行上对一行进行操作后,我也需要对列执行相同的操作。如何从这个二维数组中获取列?

请注意一个简单的方法,如创建连线并分配它们:codeword_column [0] = {rec_vector [0] [0],rec_vector [1] [0] ....., rec_vector [1022] [0]}不行。如果我这样做,利用率就会爆炸,因为我现在正在对2-d数组进行异步读取,并且2-d数组不能再被推断为块ram,因为块rams只能支持同步读取。

我真的很感激有关这方面的任何意见。感谢您抽时间阅读

verilog fpga
1个回答
0
投票

我会把这个作为完整的答案,而不是作为一个类似问题的评论,不久前弹出:Accessing a million bits

实际上你要问的是“如何在行和列模式下访问二维数组”。

只有在完全不使用寄存器的情况下才能实现这一点。

一旦你有很多位,太多无法存储在寄存器中,你就必须依赖记忆。那么如何访问内存中的行和列? 答案非常令人不满:“你做不到。”

不幸的是,存储器以长行位实现,硬件允许您一次只选择一行。要访问列,您必须按地址工作,读取一行并选择所需的列。这意味着读取一个列元素需要一个时钟周期。

加快速度的第一种方法是使用双端口存储器。我所知道的FPGA上的存储器都是双端口的。因此,您可以一次从不同的地址进行两次读取。

您还可以通过一次存储两行来加快访问速度。例如一个8x8字节的数组可以存储为16x4,并且读取允许您一次访问两行,因此第一个是两列元素。 (但收益递减,你最终会再收到一大排寄存器。)

将其与双端口访问相结合,每个时钟周期为您提供四列。

正如上面链接中提到的最后一个警告:FPGA有两种类型的存储器:

  • 同步写和同步读,他们必须使用LUT。
  • 它们具有的同步写入和读取可以使用内部存储体。

后者具有最大的存储量。因此,如果您编写代码以使用前者,您可以快速找到自己的资源。

© www.soinside.com 2019 - 2024. All rights reserved.