【问题标题】:Verilog - Getting immediate response from external memoryVerilog - 从外部存储器获得即时响应
【发布时间】:2016-02-05 12:52:40
【问题描述】:

我正在尝试编写一个 Verilog 模块,该模块在每个周期中迭代外部存储器的元素。我现在面临的问题是,在循环期间更改内存地址不会导致输入数据在同一个循环中发生更改。即:更改地址不会导致输入数据一次更改循环。我会用一些代码来说明问题:

module r(input rst, ..., output reg [MEMORY_ADDR_WIDTH-1:0] addr, input memory_value);

//...
always @(posedge clk) begin
    //...
    for(addr = 0; addr < MEMORY_SIZE; addr = addr+1) begin        
        if (memory_value) //...
        // PROBLEM: changing addr in this loop doesn't cause memory_value to change
    end
end
endmodule

这是我实例化模块的方式

module top;

 reg mem[MEMORY_SIZE-1:0];
    wire [MEMORY_ADD_WIDTH-1:0] addr;
    //...
    r r( rst, ..., addr, mem[addr]);
endmodule

我正在使用 Modelsim 来模拟设计。首先,这是预期的行为吗?如果这是常见的解决方法?

【问题讨论】:

  • “memory_value”是“r”模块的输入,因此“r”模块本身不会改变“memory_value”的值。那么,“在此循环中更改 addr 不会导致 memory_value 更改”是什么意思?
  • @KaranShah 作为 OP 指定他们正在与内存交谈,他们可能期望 memory_value 在他们在 addr 上提供新值时发生变化(这没有发生;看我的回答)

标签: verilog hdl


【解决方案1】:

for Verilog 中的循环用于创建分配的多个副本。循环会自动展开(这就是它需要恒定边界的原因)。

例如

always@(posedge clk)
for (i=1; i<4; i=i+1)
    foo[i] <= foo[i-1]*foo[i-1];

等价于

always@(posedge clk) begin
    foo[1] <= foo[0]*foo[0];
    foo[2] <= foo[1]*foo[1];
    foo[3] <= foo[2]*foo[2];
end

因此,您提供的代码从未将值分配给 addr,这可能是您看不到任何更改的原因。 (就像i 没有出现在我的示例的第二部分中一样)


考虑将它们分开。

always@(posedge clk)
    addr<=(addr+1)%ADDR_MAX;

always@(*)begin
    if (memory_value) // mem[addr]
    //...
end

【讨论】:

  • 这完全合乎逻辑。不过遇到这种情况你会怎么处理?
  • 拆分你的代码。有一个时钟块作为您的地址的计数器,以及一个组合块来评估memory_value。我假设您只想每个时钟周期执行一次检查。 (我将编辑一些代码作为示例)
  • 如果您尝试在一个周期内进行多次内存读取,则需要一个支持该功能的内存(此时,您最好为每个内存创建一个单独的模块您要处理的记忆词)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
相关资源
最近更新 更多