当我尝试按照 quartus prime 模板建议为我的项目编写定制 ROM 时,我最终得到了这个模块:
// Quartus Prime Verilog Template
// Single Port ROM
module memory
#(parameter DATA_WIDTH=256, parameter ADDR_WIDTH=12, parameter OUT_WIDTH=4)
(
input wire [(ADDR_WIDTH-1):0] addr,
input wire clk,
input wire [7:0] index,
output reg [(OUT_WIDTH-1):0] q
);
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
initial
begin
$readmemb("test.txt", rom);
end
always @ (posedge clk)
begin
q <= {rom[addr+3][index], rom[addr+2][index], rom[addr+1][index], rom[addr][index]};
end
endmodule
但出乎意料的是,quartus 无法合成和推断
ROM
,而且还编译了很长时间然后崩溃并给出以下消息:
我确信问题不是来自我的设备,我在不同的设备上尝试过
然后我尝试简化
always block
进行调试和测试,所以我将索引输入替换为常量0,然后它正常工作,没有问题,几分钟内编译完成,并且内存正确推断,请参阅修改:
// Quartus Prime Verilog Template
// Single Port ROM
module memory
#(parameter DATA_WIDTH=256, parameter ADDR_WIDTH=12, parameter OUT_WIDTH=4)
(
input wire [(ADDR_WIDTH-1):0] addr,
input wire clk,
output reg [(OUT_WIDTH-1):0] q
);
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
// Initialize the ROM with $readmemb. Put the memory contents
// in the file single_port_rom_init.txt. Without this file,
// this design will not compile.
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
// format of this file, or see the "Using $readmemb and $readmemh"
// template later in this section.
initial
begin
$readmemb("test.txt", rom);
end
always @ (posedge clk)
begin
q <= {rom[addr+3][0], rom[addr+2][0], rom[addr+1][0], rom[addr][0]};
end
endmodule
但我想在我的模块中使用索引,因为我每次都读不同的位,怎么办?
您对数据结构感到困惑。
您建模的不是ROM。
ROM 和 RAM 一次访问一个地址。
您正在尝试一次访问四个地址:
q <= {rom[addr+3][0], rom[addr+2][0], rom[addr+1][0], rom[addr][0]};
这是一个同步 Verilog ROM 模型
module my_rom
#(parameter DATA_WIDTH=256, parameter ADDR_WIDTH=12, parameter OUT_WIDTH=4)
(
input wire [(ADDR_WIDTH-1):0] addr,
input wire clk,
input wire [7:0] index,
output reg [(OUT_WIDTH-1):0] q
);
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
initial
begin
$readmemb("test.txt", rom);
end
always @ (posedge clk)
begin
q <= rom[addr];
end
endmodule
它一次访问一个地址。
以下是一些指导您思考数据结构的想法:
如果需要一次访问4条数据,则需要将它们存储为4条数据的串联,然后将4条数据一起访问。 将 ROM 的宽度设为您之前想象的 4 倍。
您可以使用状态机读取四个地址并以这种方式创建连接,但是需要 4 个时钟才能完成。
如果您确实需要同时随机访问一堆数据位置,请使用寄存器数组,并编写逻辑来获取您想要的内容。 但是,您将无法使用像
$readmemb("test.txt", rom)
这样的单行代码来初始化它。 您需要在重置期间使用一堆分配或使用状态机动态初始化它。