使用BRAM实现数据延迟

目录

为何使用BRAM实现延时

实现与仿真


为何使用BRAM实现延时

在一些设计中需要对数据进行多个周期的延时。延时方法有多种,比如使用SLICEM生成移位寄存器,或者使用FF。但是对于大位宽、深延时的数据,使用上述方法会消耗过多资源,功耗也较大。此时使用BRAM进行延时将是更优的选择。

实现与仿真

下面是简单的实现和仿真代码。其中DELAY_LEV是需要的延时周期数,READ_LATENCY是RAM的读延时,WRITE_LATENCY是RAM写入延时(在本例中是指top文件中对输入din进行的同步处理)。需要注意的是需要将RAM的工作模式设置为Read First,这样可以保证从当前地址读出的数据是之前存储的数据,而不是写入数据。当延时模块开始工作时,在addr第一次累加并归零之前,从RAM读出的都是RAM中的初始数据。只有从第二轮地址累加开始后,从RAM读出的才是需要延时的数据。所以通过控制addr在何处归零,即可实现不同的延时级数。

由于本例中的RAM通过调用XPM库实现,所以可以进一步增加parameter参数,使延时功能参数化程度进一步提高。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
//   Yinye
// Create Date: 2020/02/26 22:04:12
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top
#(  parameter DELAY_LEV         = 10,
    parameter READ_LATENCY      = 1,
    parameter WRITE_LATENCY     = 1)
(
    input               clk,
    input   [31: 0]     din,

    output  [31: 0]     dout
    );

reg     [31: 0]     din_r=32'h0;
reg     [ 5: 0]     addr=6'h0;
wire    [31: 0]     dout_w;

assign dout = dout_w;

always @ (posedge clk) begin
    din_r <= din;

    if( addr == DELAY_LEV-1 - READ_LATENCY-WRITE_LATENCY ) addr <= 6'h0;
    else addr <= addr + 1'b1;
end

xpm_memory_spram #(
      .ADDR_WIDTH_A(6),              // DECIMAL
      .AUTO_SLEEP_TIME(0),           // DECIMAL
      .BYTE_WRITE_WIDTH_A(32),       // DECIMAL
      .ECC_MODE("no_ecc"),           // String
      .MEMORY_INIT_FILE("none"),     // String
      .MEMORY_INIT_PARAM("0"),       // String
      .MEMORY_OPTIMIZATION("true"),  // String
      .MEMORY_PRIMITIVE("auto"),     // String
      .MEMORY_SIZE(2048),            // DECIMAL
      .MESSAGE_CONTROL(0),           // DECIMAL
      .READ_DATA_WIDTH_A(32),        // DECIMAL
      .READ_LATENCY_A(1),            // DECIMAL
      .READ_RESET_VALUE_A("0"),      // String
      .RST_MODE_A("SYNC"),           // String
      .USE_MEM_INIT(1),              // DECIMAL
      .WAKEUP_TIME("disable_sleep"), // String
      .WRITE_DATA_WIDTH_A(32),       // DECIMAL
      .WRITE_MODE_A("read_first")    // String
   )
   xpm_memory_spram_inst (
      .dbiterra(),                     // 1-bit output: Status signal to indicate double bit error occurrence
                                       // on the data output of port A.

      .douta(dout_w),                   // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
      .sbiterra(),                     // 1-bit output: Status signal to indicate single bit error occurrence
                                       // on the data output of port A.

      .addra(addr),                   // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
      .clka(clk),                     // 1-bit input: Clock signal for port A.
      .dina(din_r),                    // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
      .ena(1'b1),                      // 1-bit input: Memory enable signal for port A. Must be high on clock
                                       // cycles when read or write operations are initiated. Pipelined
                                       // internally.

      .injectdbiterra(1'b0),           // 1-bit input: Controls double bit error injection on input data when
                                       // ECC enabled (Error injection capability is not available in
                                       // "decode_only" mode).

      .injectsbiterra(1'b0),           // 1-bit input: Controls single bit error injection on input data when
                                       // ECC enabled (Error injection capability is not available in
                                       // "decode_only" mode).

      .regcea(1'b1),                   // 1-bit input: Clock Enable for the last register stage on the output
                                       // data path.

      .rsta(1'b0),                     // 1-bit input: Reset signal for the final port A output register stage.
                                       // Synchronously resets output port douta to the value specified by
                                       // parameter READ_RESET_VALUE_A.

      .sleep(1'b0),                    // 1-bit input: sleep signal to enable the dynamic power saving feature.
      .wea(1'b1)                        // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A input
                                       // data port dina. 1 bit wide when word-wide writes are used. In
                                       // byte-wide write configurations, each bit controls the writing one
                                       // byte of dina to address addra. For example, to synchronously write
                                       // only bits [15-8] of dina when WRITE_DATA_WIDTH_A is 32, wea would be
                                       // 4'b0010.

   );

endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
//   Yinye
// Create Date: 2020/02/26 22:58:54
// Design Name: 
// Module Name: top_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top_tb(

    );

parameter PERIOD        = 10.0;

reg             clk;
reg     [31: 0] din=32'h1;
wire    [31: 0] dout;
reg             sim_running=1'b0;

initial begin
    clk = 1'b0;
    forever begin 
        #(PERIOD/2) clk = ~clk;
    end 
end 

initial begin
    sim_running = 1'b0;
    #200 sim_running = 1'b1;
    $display("Simulation running");
    #500 sim_running = 1'b0;
    $display("Simulation end");
end 

always @ (posedge clk) begin
    if( sim_running ) din <= din + 1'b1;
    else din <= 32'h1;
end

top top_i(
    .clk        (clk),
    .din        (din),
    .dout       (dout) );

endmodule

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值