如何向bram写入数据以及从bram读取数据?

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

我试图了解在某些控制情况下BRAM存储器中的写入和读取是如何发生的。请告诉我我的代码中是否存在任何概念错误:

module bram_dual(wrt_data,addr_w,rst,clk,wr_en,read_data,rd_en);

input [17:0]wrt_data;
input clk,rst,wr_en;
input [4:0]addr_w;
output [17:0]read_data;
output  rd_en;

reg [17:0]ram[0:23];
integer i;

always@(posedge clk) begin
    if(rst)begin 
       for (i=0;i<23;i=i+1)begin  
          ram[i]<={24{1'b0}};
            
       end 
     end 
     else 
       if(wr_en) begin
          ram[addr_w]<=wrt_data;
       end 
end 

assign read_data=rd_en ? ram[addr_w]:0;
    
endmodule

测试台:

module tb_bram;

reg [17:0]wrt_data;
reg clk,rst,wr_en;
reg [4:0]addr_w;
wire  [17:0]read_data;
wire  rd_en;


integer j;

bram_dual dut1 (.wrt_data(wrt_data),
                .clk(clk),
                .rst(rst),
                .wr_en(wr_en),
                .addr_w(addr_w),
                .read_data(read_data),
                .rd_en(rd_en)
                
                ); 
 
 

 initial begin
  
  rst<=1;
  clk<=0;
  
  #20; 
  rst <=0;
  
  end
always@(posedge clk) begin
       if (rst) begin 
          wr_en<=0;
          wrt_data<=0;
          addr_w<=0;
       end 
       else begin 
         if (wr_en) begin
            for (j=0;j<23;j=j+1) begin
               wrt_data<=j;
               addr_w<=j;
            end 
          end   
         else begin 
             wrt_data<=0;
         end 
       end 
end    
 
always #10 clk=~clk;

endmodule

我有关于将数据写入 bram 内存和从 bram 内存读取数据的问题。

我可以使用两个信号将数据写入bram并从bram读取数据吗?

如写入操作时: 通过该信号将数据写入bram -> write_enable , address_write

读取操作: 读取启用,地址读取

我可以使用单独的使能信号进行写入和读取操作吗? 同样,我们也可以做地址吗?

理论上我知道我可以,但从逻辑上讲,当我尝试用 Verilog 编码来做到这一点时,我失败了。

verilog system-verilog fpga ram xilinx
1个回答
0
投票

您的

bram_dual
模块中有一些错误。

rd_en
应该是
input
端口,而不是
output
端口。

您仅重置

ram
中的 23 个位置,但您应该重置所有 24 个位置。

这是更正后的代码:

module bram_dual(wrt_data,addr_w,rst,clk,wr_en,read_data,rd_en);

input [17:0]wrt_data;
input clk,rst,wr_en;
input [4:0]addr_w;
output [17:0]read_data;
input  rd_en;

reg [17:0]ram[0:23];
integer i;

always@(posedge clk) begin
    if(rst)begin
       for (i=0;i<24;i=i+1)begin
          ram[i]<={24{1'b0}};    
       end
     end
     else
       if(wr_en) begin
          ram[addr_w]<=wrt_data;
       end
end

assign read_data=rd_en ? ram[addr_w]:0;

endmodule

在测试台中,您需要将

rd_en
更改为
reg
并驱动信号。

目前,我认为您应该只使用

initial
块来进行写入和读取。我从测试台中删除了
always
块,因为我认为它使事情变得复杂。我在初始块中添加了代码,将 5 写入地址 0,然后读取地址 0:

module tb_bram;

reg [17:0]wrt_data;
reg clk,rst,wr_en;
reg [4:0]addr_w;
wire  [17:0]read_data;
reg  rd_en;
integer j;

bram_dual dut1 (.wrt_data(wrt_data),
                .clk(clk),
                .rst(rst),
                .wr_en(wr_en),
                .addr_w(addr_w),
                .read_data(read_data),
                .rd_en(rd_en)
                );

initial begin
    rst <= 1;
    clk <= 0;
    wr_en <= 0;
    rd_en <= 0;
    wrt_data <= 0;
    addr_w <= 0;

    repeat (1) @(posedge clk);
    rst <= 0;

    repeat (2) @(posedge clk);
    wr_en <= 1;
    wrt_data <= 5;
    repeat (1) @(posedge clk);
    wr_en <= 0;
    wrt_data <= 0;

    repeat (2) @(posedge clk);
    rd_en <= 1;
    repeat (1) @(posedge clk);
    rd_en <= 0;
    repeat (2) @(posedge clk);
    $finish;
end

always #10 clk=~clk;

endmodule

模拟输出:

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