FPGA之道(66)代码中的约束信息(三)存储器以及寄存器的相关约束
文章目录
- 前言
- 存储器的相关约束
- ram_extract
- ram_style
- rom_extract
- rom_style
- 寄存器的相关约束
前言
这是这个话题的第三篇,最重要的前言是本文节选自:《FPGA之道》。
存储器的相关约束
与乘法器类似,当我们需要使用RAM或ROM作数据存储时,通常的做法也是调用IP核来进行配置。因此,当涉及到大量不同存储模块调用或修改的时候,我们同样面临着令人头疼的工作。所以,掌握一些基本的存储器相关实现约束是非常必要的。
ram_extract
ram_extract是针对RAM的一项综合约束,它的意思是是否从HDL代码中提取RAM结构。即,一旦使能该约束,编译器便会对我们的HDL代码进行分析,看内部是不是有跟RAM功能吻合的描述。如果存在这种描述,那么编译器将认为这是一个RAM,并采取相应的方式来实现RAM,否则很可能就按照寄存器形式来实现这部分存储代码。由此可见,要想通过HDL自己编写RAM,必须首先使能ram_extract约束。
下面列举出在HDL中嵌入ram_extract约束的语法:
– VHDL syntax
– 第一步,先要声明ram_extract约束;
attribute ram_extract : string;
– 第二步,为ram_extract语法指定约束线网名称和属性取值;
attribute ram_extract of <{signal_name|entity_name}> : {signal|entity} is “{yes|no}”;
// Verilog syntax
(* ram_extract = “{yes|no}” *)
// 上述约束会作用于紧随其后调用的实体、模块或信号
ram_style
ram_style是针对RAM的另一项综合约束,它表明了RAM的实现风格。
下面列举出在HDL中嵌入ram_style约束的语法:
– VHDL syntax
– 第一步,先要声明ram_style约束;
attribute ram_style : string;
– 第二步,为ram_style语法指定约束线网名称和属性取值;
attribute ram_style of <{signal_name|entity_name}> : {signal|entity} is
“{auto|block|distributed|pipe_distributed}”;
// Verilog syntax
(* ram_style = “{auto|block|distributed|pipe_distributed}” *)
// 上述约束会作用于紧随其后调用的实体、模块或信号
从上述语法可以看出,ram_style约束具有四个属性值,分别为:auto——由编译器自动选择实现风格;block——使用BLOCK RAM资源;distributed——使用离散RAM资源(即LUT);pipe_distributed——通过流水线的思路来提高使用离散RAM资源时RAM的性能(即会消耗大量寄存器资源)。
结合ram_extract和ram_style,我们可以自己编写RAM模块,并制定使用何种资源来实现。下述即为一个使用BRAM实现RAM存储的示例:
-- VHDL example
type ram_type is array (1023 downto 0) of std_logic_vector (15 downto 0);
signal RAM : ram_type;
attribute ram_extract : string;
attribute ram_extract of RAM : signal is "yes";
attribute ram_style : string;
attribute ram_style of RAM : signal is "block"; ……
process (clk)
beginif (clk'event and clk = '1') thenif (wr = '1') thenRAM(conv_integer(wrAddr)) <= D;end if; Q <= RAM(conv_integer(rdAddr));end if;
end process;
// Verilog example
(* ram_extract = "yes" *)
(* ram_style = "block" *)
reg [15:0] RAM[1023:0];
……
always@(posedge clk)
beginif(wr == 1’b1)beginRAM(conv_integer(wrAddr)) <= D;endQ <= RAM(conv_integer(rdAddr));
end
注意,编译器是否能达到约束中使用BRAM资源的预期,很大程度上取决于对RAM读取时的描述。这里请大家记住一点,那就是无论对RAM的读取逻辑有多么复杂,都切记读取到Q的赋值语句只能出现一次。例如,你想在复位时改变RAM的输出,那么可以在Q前面再加一级寄存器Qs,然后用复位去控制Qs即可,否则编译器很可能不能用BRAM来实现你的RAM。正确的示例如下:
- VHDL example
type ram_type is array (1023 downto 0) of std_logic_vector (15 downto 0);
signal RAM : ram_type;
attribute ram_extract : string;
attribute ram_extract of RAM : signal is "yes";
attribute ram_style : string;
attribute ram_style of RAM : signal is "block"; ……
process (rst, clk)
beginif(rst = '1')then<some initial but not on Q>;elseif (clk'event and clk = '1') thenif (wr = '1') thenRAM(conv_integer(wrAddr)) <= D;end if; Q <= RAM(conv_integer(rdAddr));end if;end if;
end process;
// Verilog example
(* ram_extract = "yes" *)
(* ram_style = "block" *)
reg [15:0] RAM[1023:0];
……
always@(posedge rst, posedge clk)
beginif(rst == 1'b1)begin<some initial but not on Q>;endelsebeginif(wr == 1’b1)beginRAM(conv_integer(wrAddr)) <= D;endQ <= RAM(conv_integer(rdAddr));end
end
rom_extract
rom_extract约束是关于ROM的一个综合约束,它和ram_extract约束的意义几乎一样,只不过它是针对ROM来说的。
下面列举出在HDL中嵌入rom_extract约束的语法:
– VHDL syntax
– 第一步,先要声明rom_extract约束;
attribute rom_extract : string;
– 第二步,为rom_extract语法指定约束线网名称和属性取值;
attribute rom_extract of <{signal_name|entity_name}> : {signal|entity} is “{yes|no}”;
// Verilog syntax
(*rom_extract = “{yes|no}” *)
// 上述约束会作用于紧随其后调用的实体、模块或信号
rom_style
rom_style是针对ROM的另一项综合约束,它和ram_style约束的意义几乎一样,只不过它表明了ROM的实现风格。
下面列举出在HDL中嵌入rom_style约束的语法:
– VHDL syntax
– 第一步,先要声明rom_style约束;
attribute rom_style : string;
– 第二步,为rom_style语法指定约束线网名称和属性取值;
attribute rom_style of <{signal_name|entity_name}> : {signal|entity} is
“{auto|block|distributed }”;
// Verilog syntax
(* rom_style = “{auto|block|distributed }” *)
// 上述约束会作用于紧随其后调用的实体、模块或信号
对比ram_style的语法可以发现,rom_style约束的属性取值中少了一项pipe_distributed,这大概是由于只读存储实现起来比读写存储本身就要简洁的原因。
寄存器的相关约束
作为一名FPGA开发者,寄存器是我们再熟悉不过的东西了,不过可能很少会有人关心自己项目中所使用的寄存器到底是属于哪一类资源的。经过【知己知彼篇->FPGA内部资源介绍】章节的学习,我们了解到,FPGA芯片中的绝大多数寄存器资源都位于逻辑资源块内部,因此在进行HDL程序设计时,我们所描述的具有寄存器功能的代码,几乎都会被编译器最终映射到逻辑资源块中去。但是有些时候,这样的默认操作很可能会导致FPGA设计的失败或者性能降低。因为我们发现,其实在FPGA芯片的其他资源内部也是有寄存器分布的,例如接口资源,想必这样的安排一定是有其原因的。最显而易见的原因就是距离问题,以接口资源为例,这部分资源和FPGA芯片的pin(或pad)脚距离最近,外部信号必须要经过接口资源才能传递到内部的逻辑资源块,而距离决定了线延迟,因此,当处理高速输入接口时,为了保证设计的性能,有时候必须要使用位于接口资源内部的寄存器。
要使用接口内部的寄存器资源,约束语法如下:
– VHDL syntax
– 第一步,先要声明iob约束;
attribute iob: string;
– 第二步,为iob语法指定约束线网名称和属性取值;
attribute iob of {component_name|entity_name|label_name}:
<{component|entity|label}> is “{TRUE|FALSE|AUTO}”;
// Verilog syntax
(* IOB = “{TRUE|FALSE|AUTO}” *)
// 上述约束会作用于紧随其后调用的实体、模块或信号
例如,下面就是一种使用接口资源内部寄存器进行高速输入信号采集的示例,不过请注意,由于接口资源内部的寄存器通常不具有复位端口,因此在用HDL描述时,切记不要对想放入接口资源的寄存器进行复位操作。
-- VHDL example
signal IlogicData : std_logic; attribute IOB : string;attribute IOB of IlogicData : signal is "TRUE";process(clk)begin if (clk'event and clk = '1') thenIlogicData <= inputPin;end if; end process;
// Verilog example
(* IOB = "TRUE" *)reg IlogicData; always@(posedge clk)beginIlogicData <= inputPin;end
需要说明的一点是,上例仅仅是示范了iob约束的使用方法,真要实现高性能的输入接口,时钟信号的来源也很重要,具体的方法已在【本篇->编程思路->关于外界接口的编程思路】章节中进行过介绍,这里就不再赘述。
FPGA之道(66)代码中的约束信息(三)存储器以及寄存器的相关约束相关推荐
- FPGA之道(67)代码中的约束信息(四)状态机的相关约束
文章目录 前言 状态机的相关约束 fsm_extract fsm_style fsm_encoding enum_encoding safe_implementation safe_recovery_ ...
- FPGA之道(65)代码中的约束信息(二)乘法器的相关约束
文章目录 前言 乘法器的相关约束 use_dsp48 mult_style 前言 这是这个话题的第二篇,最重要的前言是本文节选自:<FPGA之道>. 乘法器的相关约束 通常,FPGA开发者 ...
- 单片机DPTR(DPH,DPL)和SP特殊寄存器C语言中应用?这三个特殊寄存器对C程序员来说是透明的,不用C程序员操作,编译的时候会自动运用这三个寄存器ACC寄存器和B寄存器也类似
单片机DPTR(DPH,DPL)和SP特殊寄存器C语言中应用?这三个特殊寄存器对C程序员来说是透明的,不用C程序员操作,编译的时候会自动运用这三个寄存器,ACC寄存器和B寄存器也类似 编译器把C译成指 ...
- FPGA之道(77)静态时序分析(三)同步时序逻辑的分析原理
文章目录 前言 同步时序逻辑的分析原理 逻辑锥的概念 逻辑锥的划分 逻辑锥的求解 建立时间求解原理 保持时间求解原理 一般逻辑锥的求解 一般建立时间求解 一般保持时间求解 前言 本文来自于<FP ...
- java代码中获取配置文件信息数据
获取properties文件信息 -- 从properties文件中获取信息 1 创建文件对象 private static Properties config = new Properties(); ...
- FPGA之道(68)原语的使用
文章目录 前言 原语的使用 什么是原语 需要使用原语的情况 时钟相关原语 差分输入.输出原语 接口相关原语 用原语表示IP核的好处 UDP 简介 前言 本文节选自<FPGA之道>. 原语的 ...
- FPGA之道(50)复位的设计
文章目录 前言 复位的设计 为什么FPGA设计中要有复位 复位方式的分类 同步复位 异步复位 复位的设计方法 同步信号同步复位 同步信号异步复位 异步信号同步复位 异步信号异步复位 复位高扇出的解决方 ...
- FPGA之道(18)FPGA设计的编译过程
文章目录 前言 FPGA设计的实现过程 编译概述 编译流程之综合 综合的输入 HDL代码 综合设置 综合的输出 综合的工具 编译流程之翻译融合 翻译融合的输入 翻译融合的输出 翻译融合工具 编译流程之 ...
- FPGA之道(83)功能仿真之仿真语法(Graphic Waveform )
文章目录 前言 仿真语法 Graphic Waveform 数字波形简介 从实际到仿真 实际系统检测 软件仿真模拟 "Hello world"之Graphic Waveform 待 ...
最新文章
- nginx在linux下安装,Nginx在linux下安装及简单命令
- hadoop学习--基于Hive的Hadoop日志分析
- 牛客网Java刷题知识点之什么是代码块、普通代码块、静态代码块、同步代码块、构造代码块以及执行顺序...
- Vue2 源码漫游(一)
- Cactoos中的面向对象的声明式输入/输出
- 计算机科学与技术专业机遇与挑战,科学网—填报专业大类志愿:机遇与挑战 - 雒运强的博文...
- Android 11 将推出系统试用功能,满意后再正式安装
- php http agent,PHP通过http头user-agent判断是否为手机浏览器
- paip.信用卡账单处理系统功能vO22
- 密西根州立大学计算机排名,美国密西根州立大学 Alex X. Liu 教授来我校作学术讲座...
- hexo(sakura)仿gitee添加文章贡献度日历图(echarts)
- c++ stl源码-我理解的空间配置器
- 完美卸载Visual Studio2015的方法汇总
- 单链表的头插法与尾插法
- docker 导出本地所有镜像,带仓库和tag值导出到tar.gz文件
- 7 Hive数据仓库
- HarmonyOS:实现Button按下后颜色加深的效果
- Java反序列化json内存溢出_fastjson反序列化使用不当致使内存泄露
- 开源网络风云变幻,看各家爱恨情仇
- C++程序编译-链接-加载过程初探-符号表
热门文章
- 你真的理解“吃亏是福”么?
- 将多个文件的属性添加到数据库
- Struts2、Hibernate、Spring整合所需要的jar包
- android 原生分享界面_手机资讯:省时省力!直接在锁屏界面打开应用App
- mysql增加字段默认位置_MySQL语句增加字段,修改字段名,修改类型,修改默认值
- oracle votedisk 参数,11g r2 rac votedisk 及 ocr 磁盘破坏后,基于ocr备份的恢复步骤
- java高效编程_Java高效编程
- java中 resource_Java从Resource中读取文本文件
- 非常量引用的初始值必须是左值_C++核心编程--引用
- 树莓派小车python操作流程--龙邱科技