在编写RAM时哪个代码更好?
在data_out
块内分配always
:
module memory(
output reg [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always @(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
data_out <= memory[address];
end
endmodule
使用data_out
声明分配assign
:
module memory(
output [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always @(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
end
assign data_out = memory[address];
endmodule
有什么建议吗?
答案 0 :(得分:9)
这取决于您的要求。
这会记录您的内存输出。如果你将它合成到门,那么你将有16个触发器,而不是情况2.这意味着你使用更多的区域。这也意味着您的输出相对于时钟的传播延迟比情况2少。此外,输出数据在下一个时钟周期之前将不可用。
您的输出数据将在与写入时相同的时钟周期内提供,尽管相对于时钟的传播延迟较长。
您需要根据自己的要求决定使用哪个。
第三种选择是使用生成的RAM,这是一个硬宏。与情况1和2相比,这应具有面积,功率和可能的时序优势。
答案 1 :(得分:7)
添加到工具的答案 - 如果使用异步读取方法(情况2),它将不会映射到FPGA中的RAM块,因为我所知道的所有主要架构中的RAM块都有同步阅读。
答案 2 :(得分:1)
这两种形式都有效,具体取决于您想要的流水线类型。我总是建议遵循Xilinx RAM编码指南 - 这是确保代码合成适当的FGPA结构的好方法。
例如,您的示例1将合成到Xilinx BRAM(即专用Block Ram),因为它是同步读取,您的示例2将合成到Xilinx Distributed Ram(因为它是异步读取)。
请参阅Xilinx文档UG901(Vivado Design Suite用户指南)中的RAM HDL编码技术部分中的编码指南。它还很好地描述了RAM的同步读取和异步读取之间的区别。
答案 3 :(得分:0)
模块mem_try( clk,//控制信号使ram同步 addr,//必须从中获取数据的地址 data_in,//输入数据 rd wr,//控制信号高电平写入,低电平读取; // rst,//输入控制信号 // rd_count, // wr_count, data_out //数据读出 );
parameter addr_length=32,data_width=32,ram_depth= 1 << addr_length;
input [data_width-1:0]data_in;
input clk,rd,wr;
input [addr_length-1:0]addr;
output reg [data_width-1:0]data_out;
reg[data_width-1:0]ram[ram_depth-1:0];//ram variable decalaration
assign write_only =wr&~rd ;
assign read_only =~wr&rd ;
always@(posedge clk) begin
if(write_only) begin
ram[addr]<=data_in;
end
if(read_only) begin
data_out<=ram[addr];
end
end
endmodule
我为32x32 ram编写了此代码,并希望在设计中推断出块ram,但是vivado将其视为分布式ram
答案 4 :(得分:-1)
在第二个程序中,会出现编译错误,因为我们无法分配&#39;一个值为&#39; Reg&#39;。 它会出错:&#39; 注册在连续作业的左侧是非法的&#39;