2013-10-06 93 views
-1

我開始一個項目,我乘矩陣和合成它在FPGA /變更DE2。 當我開始時,我想指導如何操作將此值存儲在內存中。 我想要做的是[C] = [A] * [B]。 注:[A],[B]和[C]的值會自動存儲在SRAM或SDRAM中? 當我看到這個問題:Verilog For Loop For Array Multiplication變得更清晰如何操作,但我看不出如何管理它進入內存。 任何人都有一些我可以適應讀寫內存的代碼? 我正在遵循這條道路是正確的?矩陣乘法和存儲SRAM或SDRAM

編輯:

我有這個矩陣4x4乘法的代碼。你能告訴我這段代碼是否正確?我嘗試運行,但C值不保存到內存中。

module rams(
input clk, 
    // SRAM Interface 
    inout [15:0] SRAM_DQ, // SRAM Data bus 16 Bits 
    output [17:0] SRAM_ADDR, // SRAM Address bus 18 Bits 
    output SRAM_UB_N,  // SRAM High-byte Data Mask 
    output SRAM_LB_N,  // SRAM Low-byte Data Mask 
    output SRAM_WE_N, // SRAM Write Enable 
    output SRAM_CE_N,  // SRAM Chip Enable 
    output SRAM_OE_N  // SRAM Output Enable 
); 

parameter mat_size = 4; // change the size of the matrices here. 
reg [7:0] A_mat [0:mat_size*mat_size-1]; 
reg [7:0] B_mat [0:mat_size*mat_size-1]; 


wire [15:0] mem_in; 
reg [17:0] mem_address; 

wire [7:0] A,B; 
wire [7:0] C; 
wire [19:0] A_addr,B_addr,C_addr; 
reg reset; 
wire start; 
reg [9:0] Cr,Cc; 

assign SRAM_ADDR = mem_address; 
assign SRAM_UB_N = 1'b0;  // SRAM High-byte Data Mask 
assign SRAM_LB_N = 1'b0;  // SRAM Low-byte Data Mask 
assign SRAM_CE_N = 1'b0;  // SRAM Chip Enable 
assign SRAM_OE_N = 1'b0;  // SRAM Output Enable 

reg [2:0] state; 
parameter idle=0, read_A=1, read_B=2, start_process=3,do_nothing = 4;; 

assign SRAM_WE_N = (valid_output ? 1'b0 : 1'b1); 
assign start = !(valid_output | reset);//(valid_output ? 1'b0 : 1'b1); 
assign SRAM_DQ = (valid_output ? mem_in : 16'hzzzz); 

    // Instantiate the Unit Under Test (UUT) 
    mat_mult uut (
     .clk(clk), 
     .reset(reset), 
     .start(start), 
     .A_addr(A_addr), 
     .B_addr(B_addr), 
     .C_addr(C_addr), 
     .A(A), 
     .B(B), 
     .mat_size(mat_size), 
     .C(C), 
     .valid_output(valid_output) 
    ); 

assign mem_in = {4'h00,C}; 

initial begin 
    state = idle; 
end  

always @(posedge clk) 
begin 
    case (state) 
     idle : 
      begin 
       mem_address <= 16'h0000; 
       state = read_A; 
       reset <= 1'b1; 
      end 
     read_A :  
      begin 
       A_mat[mem_address] <= SRAM_DQ; 
       if(mem_address < mat_size*mat_size) begin 
        state = read_A; 
        mem_address <= mem_address + 1; 
       end else begin 
        state = read_B; 
       end 
      end 
     read_B :  
      begin 
       B_mat[mem_address-(mat_size*mat_size)] <= SRAM_DQ; 
       if(mem_address < 2*mat_size*mat_size) begin 
        state = read_B; 
        mem_address <= mem_address + 1; 
       end else begin 
        state = start_process; 
        reset <= 1'b0; 
       end 
      end 
     start_process : 
      begin 
       state = start_process; 
       mem_address <= 2*mat_size*mat_size + C_addr; 
       if(C_addr == mat_size*mat_size-1) begin 
        state = do_nothing; 
       end else begin 
        reset <= 1'b0; 
       end 
      end  
     do_nothing : 
      if(valid_output) begin 
       reset <= 1'b1; 
      end 
    endcase 

end 

assign A = A_mat[A_addr]; 
assign B = B_mat[B_addr]; 

endmodule 

我載荷值A和B一起,格式十六進制16.我與DE_Control Altera的值,becouse我不知道如何爲負載做到這一點使用你的代碼。 而模塊乘法是:

module mat_mult(
    input clk, 
    input reset, 
    input start, 
    output [19:0] A_addr, 
    output [19:0] B_addr, 
    output [19:0] C_addr, 
    input [7:0] A, 
    input [7:0] B, 
    input [9:0] mat_size, 
    output [7:0] C, 
    output valid_output 
    ); 

reg [9:0] Ar,Br,Bc,Cr,Cc; 
reg [7:0] C_res; 
reg v; 

always @ (posedge clk or posedge reset) 
    if (reset) begin 
     Ar <= 10'b0000000000; 
     Br <= 10'b0000000000; 
     Bc <= 10'b0000000000; 
     Cr <= 10'b0000000000; 
     Cc <= 10'b0000000000; 
     C_res <= 8'h00; 
     v <= 1'b0; 
    end else begin 
     if (start) begin 
      if (Br == mat_size-1) begin 
       Br <= 10'b0000000000; 
       if (Bc == mat_size-1) begin 
        Bc <= 10'b0000000000; 
        if (Ar == mat_size-1) begin 
         Ar <= 10'b0000000000; 
        end else begin 
         Ar <= Ar + 1; 
        end 
       end else begin 
        Bc <= Bc + 1; 
       end 
       v <= 1'b1; 
      end else begin 
       Br <= Br + 1; 
      end 
      C_res <= C_res + A*B; 
     end else begin 
      C_res <= 8'h00; 
      v <= 1'b0; 
     end 
    end 

assign A_addr = (Ar * mat_size) + Br; 
assign B_addr = (Br * mat_size) + Bc; 
assign C_addr = (Ar * mat_size) + Bc; 
assign C = C_res; 
assign valid_output = v; 

endmodule 

回答

0

當內存的工作,只記得它只是地址和字節之間的映射。所以如果你想到一個矩陣(爲了簡單起見,我將假設32位浮點數是4x4),那麼你真正擁有的只是16個浮點32位數。

你存儲如果打算將它們存儲在片上存儲器(集成到FPGA裸片SRAM單元)這些在存儲器將是不同的方式,或芯片外,成一些DDR類型的存儲器。

將它們存儲在芯片上是比較容易的Verilog你只是聲明數組,然後讀取並從它一個元素在同一時間寫的工作,在這種情況下。您的合成器會將此推斷爲RAM,前提是您的FPGA具有可用的可用RAM容量。

module matrixmem; 

input clk; 
input [3:0] addr; 
input [31:0] data_in; 
output [31:0] data_out; 
input write; 
input read; 

reg [31:0] mem [0:15]; //16 32-bit elements, enough to store one 4x4 array. 

always @(posedge clk) begin 
    if(write) 
     mem[addr] <= data_in; 
    else if (read) 
     data_out <= mem[addr]; 
end 

然後從這個模塊可以拉出陣列的一個的在一個時間中的元素,通過改變地址,其中地址表示要拉矩陣的哪些元素。

如果要存儲這些斷片它更復雜一些,因爲你需要實現DDR控制器或利用附帶的FPGA,以便與外部RAM傳達某些IP。但基本上它的工作原理是一樣的,因爲矩陣的每個元素都將存儲在某個地址中。

+0

非常感謝你! –

0

多了一個預防措施,你必須始終牢記的是,當宣告始終阻止它是明智的聲明輸出端口REG類型,如果它是一個連續的塊。

爲這裏如果我們要使用的data_out用於存儲價值的解決方案,我們需要把它聲明爲REG類型。否則它很好。