本文目录
本文记录了Verilog语言的入门基础知识,并通过一些代码实例帮助大家上手,主要基于Xilinx Vivado完成,以下个人学习经验仅供参考。
(1)关键字必须小写,如reg、input
(2)标识符区分大小写,开头必须是字母或下划线,如CLK、clk(两者不同)
(3)每行必须以;结束
(4)单行注释用//xxx,跨行注释用/* xxx */
(1)基本数值种类:0(0 或 假)、1(1 或 真)、x/X(未知)、z/Z(高阻)
(2)整数基数格式:二进制('b 或 'B),八进制('o 或 'O),十进制('d 或 'D),十六进制('h 或 'H)
(3)整数表示方法:4’b1001(指明位宽,4位二进制“1001”)或100(不指明位宽,默认十进制“100”)
(4)负数表示方法:-4’b1001(指明位宽时)或-100(不指明位宽时)
(5)实数表示方法:十进制(0.001)或科学记数法(1.2e4)
(6)字符串表示方法:需要定义相应大小的存储单元,比如字符串"www.csdn.net"需要12*8bit的存储单元,代码如下:
reg [12*8-1:0] str;
assign str = "www.csdn.net";
(1)线网:wire,表示硬件单元之间的物理连线,由其连接的器件输出端连续驱动
(2)寄存器:reg,表示存储单元,它会保持数据原有的值直到被改写
(3)向量:当位宽大于 1 时线网或寄存器即可表示向量,举例如下:
wire [8-1:0] addr;
reg [8-1:0] addr_temp;
addr_temp[7:6] = addr[1:0] + 1'b1 ;
(4)整数:用integer声明,注意变量为有符号数
(5)实数:用 real 声明,十进制或科学计数法表示
(6)时间:用time声明, 通过调用系统函数 $time 获取当前时间
(7)数组:数组中的每个元素都可视为一个标量或者向量,形如<数组名字>[<位数>],举例如下:
integer flag [7:0] ; //8个整数组成的数组flag
reg [3:0] counter [3:0] ; //4个4位reg型变量组成的数组counter
wire [7:0] addr [3:0] ; //4个8位wire型变量组成的数组addr
flag [1] = 32'd0 ; //将flag中第2个元素赋值为32位的0值
counter [3] = 4'hF ; //将counter中第4个元素赋值为4位的十六进制数F
assign addr [0] = 8'b0 ; //将addr中第1个元素赋值为0
(8)参数:用parameter或localparam声明,表示常量
(1)表达式:由操作符和操作数构成,目的是根据操作符的意义得到一个计算结果
(2)操作数:可以是任意数据类型,如常数、整数、实数、线网、寄存器、时间、函数等
(3)操作符:包括算术、关系、等价、逻辑、按位、归约、移位、拼接、条件操作符等,圆括号内表达式优先执行,同类型操作符之间除条件操作符从右往左关联,其余操作符都是自左向右关联
(4)算术操作符:包括单目操作符(“+”、“-”,表示操作数正负,优先级最高)和双目操作符(加“+”、减“-”、乘“*”、除“/”、求幂(两个星号)、取模“%”)
(5)关系操作符:大于“>”、小于“<”、大于等于“> =”、小于等于“< =”,结果为真“1”或假“0”
(6)等价操作符:逻辑相等“= =”、逻辑不等“! =”、全等”= = =“、非全等“! = =”,结果为真“1”或假“0”
(7)逻辑操作符:逻辑与“& &”、逻辑或“| |”、逻辑非“!”
(8)按位操作符:取反“~ ”、与“&”、或“|”、异或“^”、同或“~ ^”
(9)归约操作符:归约与“&”、归约与非“~ &”、归约或“|”、归约或非“~ |”、归约异或“^”、归约同或“~ ^”
(10)移位操作符:左移“<<”、右移“>>”、算术左移“<<<”、算术右移“>>>”
(11)拼接操作符:用大括号 {,} 表示,用于将多个操作数拼接成新的操作数,每个操作数必须指定位宽
(12)条件操作符:判断条件condition是否满足,满足执行true对应语句,不满足执行false对应语句,可嵌套执行多次判断,格式如下:
condition ? true : false
(1)宏定义编译指令(与C一致)
`define
`undef
(2)条件编译指令(与C一致)
`ifdef
`ifndef
`else
`elsif
`endif
(3)`include:用于将全局或公用头文件包含在设计文件里,使用相对或绝对路径皆可
(4)`timescale:定义时间单位和时间精度,两者都是由数字和单位(s、ms、us、ns、ps、fs)组成,时间精度大小小于等于时间单位大小,举例如下:
`timescale 1ns/100ps //合法
//`timescale 100ps/1ns //不合法
(5)`resetall:将所有编译指令重设为缺省值
(6)单元模块定义(cell)
`celldefine
`endcelldefine
举例如下:
`celldefine
module (
input clk,
input rst,
output A,
output B );
endmodule
`endcelldefine
(1)initial语句:
initial语句从0时刻开始执行,单次执行,多个语句之间并行执行,单个语句内顺序执行;
块内包含多个语句时需要使用关键字begin和end,只有一条语句时可不用
(2)always语句:
always语句从0时刻开始执行,重复执行,多个语句之间并行执行,单个语句内顺序执行;
块内包含多个语句时需要使用关键字begin和end,只有一条语句时可不用
(1)阻塞赋值“=”:语句顺序执行,即下一条语句执行前当前语句一定会执行完毕
(2)非阻塞赋值“<=”:语句并行执行,即其他语句的执行和当前语句的执行同时进行
(1)顺序块:块中语句顺序执行,但非阻塞赋值仍按并行执行,用begin & end表示
(2)并行块:块中语句并行执行,包括阻塞赋值,用fork & join表示
(3)嵌套块:顺序块+并行块
(4)命名块:给块语句结构命名,块中可以声明局部变量,通过层次名引用的方法对变量进行访问,格式如下:
module test;
initial begin: A //块命名为A,disable后禁用命名块
integer B; //变量B可通过text.A.B被其他模块调用
end
endmodule
连续赋值语句“assign”用于对wire型变量进行赋值,格式如下:
wire z, x, y;
assign z = x & y; //只要x、y改变z就会相应改变,注意z必须是wire型变量,x、y可以是wire型或reg型变量
(连续赋值)延时语句“assign #time”用于控制任意操作数发生变化到语句左端赋予新值之间的延时时间,格式如下:
wire z, x, y;
assign #10 z = x & y; //延时10个时间单位后赋值,若信号脉冲宽度小于延时则对输出无影响,称为惯性延时
(1)延时控制:包括常规延时控制与内嵌延时控制
常规延时格式为:(先延时再赋值,无惯性延时问题)
#10;
y = x; //或直接合并为#10 y = x;
内嵌延时格式为:(先赋值再延时,有惯性延时问题)
y = #10 x;
(2)事件控制:包括边沿触发事件控制与电平敏感事件控制
边沿触发事件格式为:
always @(posedge clk or negedge rst_n) //用@表示边沿触发条件,只有当信号发生特定变化时才能继续执行语句A
begin
A;
end
posedge指信号边沿正向跳变时触发,negedge指信号边沿负向跳变时触发,未指明时正负边沿跳变都会触发;
用关键字or连接多个变量,当变量很多时可简写为@(*),表示对所有输入变量的边沿跳变都会触发;
命名事件控制是一种特殊的事件控制,用关键字event声明并触发该变量来识别该事件是否发生,格式如下:
event A;
always @(posedge clk) begin //clk上升沿作为A触发
-> A; //->表示触发
end
always @(A) begin //A触发时执行B
B;
end
电平敏感事件格式为:
wait (x); //x为电平敏感条件,只有当电平敏感条件为真时才能继续执行语句A
begin
A;
end
条件语句“if”用于根据条件判断是否执行相应语句,格式如下:
if (x) A; //如果满足条件x则执行A语句(若语句不只一行则应用“ begin A end; ”格式)
else if (y) B; //如果满足条件y则执行B语句(else if可有多级或者没有)
else C; //否则执行C语句
多路分支语句"case"用于解决if语句中条件选项过多时使用不方便的问题,格式如下:
case (variable)
x : A; //variable = x时执行A语句(若语句不只一行则应用“ begin A end; ”格式)
y : B; //variable = y时执行B语句(除x、y还可以有多级case)
default : Z; //default语句可没有
(1)while循环语句(所有循环语句只能在“always”或“initial”块中使用)
while (x)
begin
A; //满足x条件时执行A语句,A只有一行时begin & end可省略
end
(2)for循环语句
for (x; y; z) //x为初始条件,y为终止条件,z为控制变量的过程赋值语句,注意增加或减少变量计数不能写成 i++或i--
begin
A;
end
(3)repeat循环语句
repeat (n) //执行固定次数n个循环
begin
A;
end
(4)forever循环语句
forever //相当于while(1),表示永久循环,通过系统函数$finish退出
begin
A;
end
(1)assign(过程赋值) & deassign(取消过程赋值):
赋值对象只能是reg型变量而不能是wire型变量,赋值过程中对寄存器连续赋值,寄存器中的值被保留直到被重新赋值
(2)force(强制赋值) & release(取消强制赋值):
赋值对象可以是reg型或wire型变量;
force作用在寄存器上时,寄存器当前值被覆盖,release时该寄存器值将继续保留强制赋值时的值;
force作用在线网上时,线网当前值被覆盖,但release时该线网值马上变为原有的驱动值
(1)十进制有符号数转二进制补码:
正数的补码为原码;
负数的补码有两种计算方式:
a、将有符号数最高位符号位改写为1,剩余数值部分取反加1
比如4位数字-7的数值部分为4’b0111,高位改写后为4’b1111,剩余数值部分取反加1后为4’b1001
b、将有符号数直接与其代表的最大数值范围相加
比如4位数字-7与16(2的4次幂)的和为9, 即对应4’b1001
(2)二进制补码转十进制有符号数:
补码最高位为0时其数值大小即为表示的十进制正数;
补码最高位为1时有两种计算方式:
a、将补码取反加1,并增加符号位
比如4位数字-7的补码为4’b1001,取反加1后为4’b0111,增加符号位后为-7
b、将补码对应的无符号数与其代表的最大数值范围相减
比如4位数字-7的补码为4’b1001,无符号数为9,9-16=-7
(3)求二进制补码的绝对值:
将补码取反加1,比如4位数字-7的补码为4’b1001,取反加1后为4’b0111,即7
(4)符号位扩展:
将代表符号位的最高位填充至扩展的高位数据位中,比如4’b1011(-7)扩展到8位为8’b11111010(-7)
代码如下:
function integer log2(input integer n);
integer i;
for( i=0; 2**i<=n; i=i+1)
log2 = i + 1;
endfunction
假设n=15(0000 1111),那么log2=4,也就是4位;
假设n=16(0001 0000),那么log2=5,也就是5位。
代码如下:
reg x;
x <= ((x == 4'd0) ? A : ((x == 4'd1) ? B : ((x == 4'd2) ? C : D)));
变量x为4’d0执行A语句,为4’d1执行B语句,为4’d2执行C语句,否则执行D语句。
代码如下:
(*mark_debug = "true"*)reg [5:0] CNT;
always @ (posedge CLK or negedge RST)
begin
if(!RST)
CNT <= 1'b0;
else
CNT <= (CNT==最大计数-1) ? 1'd0 : CNT + 1'd1;
end
“最大计数”位置应给定一个值,CNT将在0~最大计数区间内循环+1。注意第一句(mark_debug = “true”)表示监视该变量。
代码如下:
reg triger, triger_dly1, triger_dly2;
always @ (posedge CLK or negedge RST)
begin
if(!RST)
begin
triger_dly1 <= 1'b0;
triger_dly2 <= 1'b0;
end
else
begin
triger_dly1 <= triger;
triger_dly2 <= triger_dly1;
end
end
wire posedge_triger = triger_dly1 && (~triger_dly2);
wire negedge_triger = (~triger_dly1) && triger_dly2;
对triger延时1拍和2拍产生triger_dly1和triger_dly2变量,triger_dly1为上升沿时通过posedge_triger捕捉,triger_dly2为下降沿时通过negedge_triger捕捉。
如果文章中有错误或疏漏之处烦请指正,希望大家多交流共同进步!
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg