一、xpm_memory_tdpram原语介绍
xpm_memory_tdpram #(
.ADDR_WIDTH_A(16), // DECIMAL,A口地址[15:0]
.ADDR_WIDTH_B(16), // DECIMAL,B口地址[15:0]
.AUTO_SLEEP_TIME(0), // DECIMAL
.BYTE_WRITE_WIDTH_A(72), // DECIMAL A口写宽度为72,4个像素点
.BYTE_WRITE_WIDTH_B(72), // DECIMAL B口写宽度为72,4个像素点
.CASCADE_HEIGHT(0), // DECIMAL
.CLOCKING_MODE("common_clock"), // String
.ECC_MODE("no_ecc"), // String
// .MEMORY_INIT_FILE("none"), // String
.MEMORY_INIT_FILE("triangle_192_256.mem"), // String
.MEMORY_INIT_PARAM("0"), // String
.MEMORY_OPTIMIZATION("true"), // String
.MEMORY_PRIMITIVE("ultra"), // String
.MEMORY_SIZE(3538944), // DECIMAL 内存bits数,192*1024*18=192*256*72=3538944,生成192行1024列的图像,18为图像颜色的深度
.MESSAGE_CONTROL(0), // DECIMAL 禁能消息报告
.READ_DATA_WIDTH_A(72), // DECIMAL A口读数据位宽[71:0],4个像素点
.READ_DATA_WIDTH_B(72), // DECIMAL B口读数据位宽[71:0],4个像素点
.READ_LATENCY_A(1), // DECIMAL 读延迟1个时钟 内存大于2MB时,延迟必须大于8
.READ_LATENCY_B(1), // DECIMAL 读延迟1个时钟 内存大于2MB时,延迟必须大于8
.READ_RESET_VALUE_A("0"), // String
.READ_RESET_VALUE_B("0"), // String
.RST_MODE_A("SYNC"), // String
.RST_MODE_B("SYNC"), // String
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
.USE_EMBEDDED_CONSTRAINT(0), // DECIMAL
.USE_MEM_INIT(0), // DECIMAL
.USE_MEM_INIT_MMI(0), // DECIMAL
.WAKEUP_TIME("disable_sleep"), // String
.WRITE_DATA_WIDTH_A(72), // DECIMAL A口读数据位宽[71:0],4个像素点
.WRITE_DATA_WIDTH_B(72), // DECIMAL B口读数据位宽[71:0],4个像素点
.WRITE_MODE_A("no_change"), // String
.WRITE_MODE_B("no_change"), // String
.WRITE_PROTECT(1) // DECIMAL,使用写使能信号
ram_inst (
.dbiterra(),// 1-bit output: 指示A口数据输出有双bits错误发生
.dbiterrb(),// 1-bit output: 指示B口数据输出有双bits错误发生
.sbiterra(),// 1-bit output: 指示A口数据输出有单bits错误发生
.sbiterrb(), // 1-bit output: 指示B口数据输出有单bits错误发生
.ena(1'b1), //RAM A口使能信号,高电平有效
.enb(1'b1), //RAM B口使能信号,高电平有效
.injectdbiterra(1'b0),//控制双bits错误注入
.injectdbiterrb(1'b0),//控制双bits错误注入
.injectsbiterra(1'b0),//控制单bits错误注入
.injectsbiterrb(1'b0),//控制单bits错误注入
.regcea(1'b1), //输入端口,输出数据路径的上一个寄存器阶段,时钟使能
.regceb(1'b1), //输入端口,输出数据路径的上一个寄存器阶段,时钟使能
.rsta(1'b0), //复位信号,高电平有效
.rstb(1'b0),//复位信号,高电平有效
.sleep(1'b0), //高电平使能动态降低功耗功能,此处禁能
.douta(douta), //READ_DATA_WIDTH_A bits 输出,[71:0],B口读数据
.doutb(doutb), //READ_DATA_WIDTH_B bits 输出,[71:0],B口读数据
.addra(addra),//ADDR_WIDTH_A bits输入 [15:0]A口写地址
.addrb(addrb),//ADDR_WIDTH_B bits输入 [15:0]B口写地址
.clka(clk_300M), //A口输入时钟
.clkb(clk_300M), //B口输入时钟
.dina(dina), // WRITE_DATA_WIDTH_A bits A口数据输入[71:0]
.dinb(dinb), // WRITE_DATA_WIDTH_B bits B口数据输入[71:0]
.wea(wea), //A口写使能信号,宽度为 WRITE_DATA_WIDTH_A / BYTE_WRITE_WIDTH_A =72/72=1
.web(web) //B口写使能信号,宽度为 WRITE_DATA_WIDTH_B / BYTE_WRITE_WIDTH_B =72/72=1
当需要指定RAM内初始化数值时,可以使用原语中的参数MEMORY_INIT_FILE,指向一个尾缀为.mem的文件。该文件内的内容要求必须时十六进制的,与$readmemh函数读取的文件内容格式一致,用空格或者回车将数据隔开即可。
另外需要注意的是,本着节约使用ultra RAM的想法,一个ultra RAM的数据位宽为72bits,因此72bits拆分为18bits,即ultra RAM的一个地址上,保存着4个18bits的像素数据。
二、如何生成.mem文件
借助于matlab,与生成.coe文件类似,matlabl示例程序如下:
M = 192;
N = 1024 ;
y = zeros(M , N) ;%生成192行1024列的矩阵
for i = 1:1:M
for j = 1:1:N
if(j <= N/2) %锯齿波,从0到512时,下降斜率直线
if( i == round(191/512*j))
y(i,j) = 255 ;%出现在斜率线附近的点赋值255
y(i,j) = 0 ;%不在斜率线附近的点赋值0
if(j > N/2)%%锯齿波,从512到1024时,上升斜率直线
if( i == round(382-191/511*j) )
y(i,j) = 255 ;%出现在斜率线附近的点赋值255
y(i,j) = 0 ;%不在斜率线附近的点赋值0
imshow(y)
% plot(y(i,j));%绘图预览
%y矩阵4个点拼成1个点
fpga_y_dec = zeros(M , N/4) ;
fpga_y_dec_49152=zeros(49152,1);%将矩阵变为1列
fpga_y_hex = zeros(M*N/4,8) ;
for i = 1:1:M
for j = 1:1:N/4
fpga_y_dec(i,j)=y(i,4*j-3)*256*256*256+y(i,4*j-2)*256*256+y(i,4*j-1)*256+y(i,4*j);
fpga_y_dec_49152(i*256-256+j,1)=fpga_y_dec(i,j);
fid1 = fopen('triangle_192_256.mem','wt');
%COE文件格式
% fprintf( fid1, 'MEMORY_INITIALIZATION_RADIX = 16;\n');
% fprintf( fid1, 'MEMORY_INITIALIZATION_VECTOR =\n');
%输出十进制数据,保存至文件
for i = 1:1:49152
if(i == 49152)
fprintf(fid1,'%s%c%c%c%c%c%c%c%c',"0000000000",fpga_y_hex(i,1),fpga_y_hex(i,2),fpga_y_hex(i,3),fpga_y_hex(i,4),fpga_y_hex(i,5),fpga_y_hex(i,6),fpga_y_hex(i,7),fpga_y_hex(i,8)); %最后一个点时,标点为分号,其余时候为逗号
fprintf(fid1,'%s%c%c%c%c%c%c%c%c\n',"0000000000",fpga_y_hex(i,1),fpga_y_hex(i,2),fpga_y_hex(i,3),fpga_y_hex(i,4),fpga_y_hex(i,5),fpga_y_hex(i,6),fpga_y_hex(i,7),fpga_y_hex(i,8));
fclose(fid1);%关闭文件
生成 如下图所示的三角波图像:
生成的文件的部分内容如下:
三、仿真xpm_memory_tdpram原语
仿真xpm_memory_tdpram原语原语,将初始化文件内容读出,观察是否与文件内容一致。
`timescale 1ns/1ps
module top();
reg clk_100M = 1'b0;
reg rst = 1'b1;
reg rd_enable =1'b0;
//生成100M时钟
always
begin
clk_100M <= ~clk_100M;
//延迟100ns,复位拉高
initial
begin
#100 rst <= 1'b0;
#200 rd_enable <= 1'b1;
wire [71:0] douta;
wire [71:0] doutb;
reg [15:0] addra =0;
reg [15:0] addrb =0;
wire [71:0] dina;
wire [71:0] dinb;
wire wea;
wire web;
//不写入新的数据,仅读
assign dina = 72'b0;
assign dinb = 72'b0;
assign wea = 1'b0;
assign web = 1'b0;
always@(posedge clk_100M)
begin
if(rd_enable) begin
addra <= addra + 1'b1;
addrb <= addrb + 1'b1;
xpm_memory_tdpram #(
.ADDR_WIDTH_A(16), // DECIMAL,A口地址[15:0]
.ADDR_WIDTH_B(16), // DECIMAL,B口地址[15:0]
.AUTO_SLEEP_TIME(0), // DECIMAL
.BYTE_WRITE_WIDTH_A(72), // DECIMAL A口写宽度为72,4个像素点
.BYTE_WRITE_WIDTH_B(72), // DECIMAL B口写宽度为72,4个像素点
.CASCADE_HEIGHT(0), // DECIMAL
.CLOCKING_MODE("common_clock"), // String
.ECC_MODE("no_ecc"), // String
// .MEMORY_INIT_FILE("none"), // String
.MEMORY_INIT_FILE("triangle_192_256.mem"), // String
.MEMORY_INIT_PARAM("0"), // String
.MEMORY_OPTIMIZATION("true"), // String
.MEMORY_PRIMITIVE("ultra"), // String
.MEMORY_SIZE(3538944), // DECIMAL 内存bits数,192*1024*18=192*256*72=3538944,生成192行1024列的图像,18为图像颜色的深度
.MESSAGE_CONTROL(0), // DECIMAL 禁能消息报告
.READ_DATA_WIDTH_A(72), // DECIMAL A口读数据位宽[71:0],4个像素点
.READ_DATA_WIDTH_B(72), // DECIMAL B口读数据位宽[71:0],4个像素点
.READ_LATENCY_A(0), // DECIMAL
.READ_LATENCY_B(0), // DECIMAL
.READ_RESET_VALUE_A("0"), // String
.READ_RESET_VALUE_B("0"), // String
.RST_MODE_A("SYNC"), // String
.RST_MODE_B("SYNC"), // String
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
.USE_EMBEDDED_CONSTRAINT(0), // DECIMAL
.USE_MEM_INIT(0), // DECIMAL
.USE_MEM_INIT_MMI(0), // DECIMAL
.WAKEUP_TIME("disable_sleep"), // String
.WRITE_DATA_WIDTH_A(72), // DECIMAL A口读数据位宽[71:0],4个像素点
.WRITE_DATA_WIDTH_B(72), // DECIMAL B口读数据位宽[71:0],4个像素点
.WRITE_MODE_A("no_change"), // String
.WRITE_MODE_B("no_change"), // String
.WRITE_PROTECT(1) // DECIMAL,使用写使能信号
ram_inst (
.dbiterra(),// 1-bit output: 指示A口数据输出有双bits错误发生
.dbiterrb(),// 1-bit output: 指示B口数据输出有双bits错误发生
.sbiterra(),// 1-bit output: 指示A口数据输出有单bits错误发生
.sbiterrb(), // 1-bit output: 指示B口数据输出有单bits错误发生
.ena(1'b1), //RAM A口使能信号,高电平有效
.enb(1'b1), //RAM B口使能信号,高电平有效
.injectdbiterra(1'b0),//控制双bits错误注入
.injectdbiterrb(1'b0),//控制双bits错误注入
.injectsbiterra(1'b0),//控制单bits错误注入
.injectsbiterrb(1'b0),//控制单bits错误注入
.regcea(1'b1), //输入端口,输出数据路径的上一个寄存器阶段,时钟使能
.regceb(1'b1), //输入端口,输出数据路径的上一个寄存器阶段,时钟使能
.rsta(rst), //复位信号,高电平有效
.rstb(rst),//复位信号,高电平有效
.sleep(1'b0), //高电平使能动态降低功耗功能,此处禁能
.douta(douta), //READ_DATA_WIDTH_A bits 输出,[71:0],B口读数据
.doutb(doutb), //READ_DATA_WIDTH_B bits 输出,[71:0],B口读数据
.addra(addra),//ADDR_WIDTH_A bits输入 [15:0]A口写地址
.addrb(addrb),//ADDR_WIDTH_B bits输入 [15:0]B口写地址
.clka(clk_100M), //A口输入时钟
.clkb(clk_100M), //B口输入时钟
.dina(dina), // WRITE_DATA_WIDTH_A bits A口数据输入[71:0]
.dinb(dinb), // WRITE_DATA_WIDTH_B bits B口数据输入[71:0]
.wea(wea), //A口写使能信号,宽度为 WRITE_DATA_WIDTH_A / BYTE_WRITE_WIDTH_A =72/72=1
.web(web) //B口写使能信号,宽度为 WRITE_DATA_WIDTH_B / BYTE_WRITE_WIDTH_B =72/72=1
endmodule
xpm_memory_sdpram #(
.ADDR_WIDTH_A ( 9 ) , // DECIMAL
.ADDR_WIDTH_B ( 9 ) , // DECIMAL
.AUTO_SLEEP_TIME ( 0 ) , // DECIMAL
.BYTE_WRITE_W...
书本中对于RAM的三种操作读优先级(read_first)、写优先(write_first)和保持(no_change)使用等效的verilog来描述,简单明了,记录于此。
在vivado里利用 Xilinx Parameterized Macros(XPM) 原语例化的 直接仿真会出现 module找不到的错误, 在tcl里输入一下指令就好了,
set_property XPM_LIBRARIES {XPM_CDC XPM_MEMORY} [current_project]
整理:比特波特首先,什么是XPM?可能很多人没听过也没用过,它的全称是Xilinx Parameterized Macros,也就是Xilinx的参数化的宏,跟原语的例化和使用方式一样。可以在Vivado中的Tools->Language Templates中查看都有哪些XPM可以例化。从上图中可以看出,目前可以例化的XPM主要有三种:跨时钟域处理、FIFO和MEMORY。我们以MEMORY...
在Vmware10中安装的是Ubuntu。使用时,某一天出现如下问题:
Unrecoverable Memory Allocation Failure
之后是ubuntu起不来,一直出现这样的问题。笔者的解决办法是,进入Ubuntu的Recovery模式,对文件系统进行了检测,然后就可以正常使用了。
转:https://zhuanlan.zhihu.com/p/147058600
上一篇文章介绍了 单比特跨时钟域 的不同应用场景的区别(基于Xilinx Parameterized Macros),主要有:
同步Reset (XPM_CDC_SYNC_RESET)
异步Reset (XPM_CDC_ASYNC_RESET)
电平信号 (XPM_CDC_SINGLE)
脉冲信号 (XPM_CDC_PULSE)
这篇我们来看一下这几个Macro的具体设计细节和原理。我会基于Xilinx Guide的
以上三种宏都可以用来实现跨时钟域的处理,FIFO与RAM的跨时钟域处理主要是通过缓存的方式实现。利用宏和IP核来实现FIFO、RAM的例化,功能上相差不大,就是使用方式略有区别。
以下主要介绍一下XPM_CDC,通过程序注释的方式进行介...
目录原语简介原语的分类时钟相关的原语IBUFGIBUFGDSBUFGBUFGPBUFGCEBUFGMUXBUFGDLLDCM接口相关的原语IDDRODDR
原语简介
原语,即primitive,原语类似最底层的描述方法,是不同厂商针对自己FPGA芯片提供的底逻辑资源的描述。因此不同的厂商,原语不同,同一家的FPGA,由于不同系列的芯片内部资源一般不同,原语也是不通用的。使用原语的好处,可以直接例化使用,不用定制IP。我们在进行FPGA开发时的HDL代码在进行综合后的输出就是由原语组成的逻辑网表,因此原语是不