chisel学习--用到的Verilog语法细节

数据类型

逻辑值的概念

逻辑值:4种逻辑值

01XZ
不确定高阻,浮动状态

强度值:用以解决不同强度驱动源之间的赋值冲突

76543210
SupplyStrongPullLargeWeakMediumSmallHighz

数值的表示

形式:<位宽>‘<进制><数值>
申请方式: integer

进制二进制八进制十进制十六进制
表示bodh
举例4’b1011(4位)6‘o87_25(6位,_忽略)8’12(8位,d可省)‘h2f(32位)
x/z代表1位代表3位-代表4位

线网的概念

线网:类似实际使用的电线,数值一般只能通过连续赋值,由赋值符右侧连接的驱动源决定。
申请方式: wrie

wriesupply0supply1tritri0tri1triregtriandtriorwandworuwire
默认,连接单元的连线低电平0高电平1多个驱动源驱动同一根线强度为pull的0值作驱动强度为pull的1值作驱动0,1,x三态驱动源某个驱动源为0则值为0某个驱动源为1则值为1与triand一致与trior一致-

寄存器的概念

寄存器存储数值的变量,初始值为x
申请方式:reg

输入-> 输出线网寄存器
线网允许不允许
寄存器允许不允许

向量的概念

对于线网wire寄存器reg类型:
标量:没有声明位宽的量
向量:声明位宽范围并且位宽范围大于1的量
申请方式:<类型名称> [n:0] <自定义的名字>
使用时:<自定义的名字>[i]

-标量向量特定位赋值位溢出缺位宽
操作wire b;reg [3:0] c;c[2:0]=3’b101舍弃最左边最左边补0

数组的概念

对于reg,integer,time,real,realtime类型
数组:维度没有限制,元素为向量或者标量
申请方式:<类型名称> [n:0] <数组名字> [0:m]
使用时:<数组名字> [j]

-可用数据类型
向量wire,reg
数组reg,integer,time,real,realtime
区别向量是一个单独的元件,位宽是n;数组由多个元件组成,共长m,其中每个元件的位宽为n或者1

参数的概念

参数:参数parameter和局部参数localparam
用途:在模块内定义常数,不能赋值

-参数重定义的方式和范围
parameter通过“#”进行重新定义
localparam不可以重定义

非常见运算符

按位与按位或按位异或按位同或缩减操作符逻辑移位算术移位拼接重复拼接条件
a&b竖杠a^b^~ / ~^所有位参与>>或<<符号位可填充{a,b}{n{a}}?:

模块的概念

简单模块

模块:module,相当于函数,实际意义是代表硬件电路上的逻辑实体
形如:

module <模块名>(<输入输出端口列表>);

<定义,指定数据对象为寄存器型、存储器型、线型以及过程块,相当于初始化>

<模块条目,将上面定义和端口组合起来,说明这个模块要做什么,相当于计算过程>

endmodule

举例:

module add_sub  #(
					parameter DATAWIDTH = 8   //参数
				)(
  input                         clock,
  input                         reset,
  input                     i_add_sub,
  input signed  [DATAWIDTH-1:0]   i_a,
  input signed  [DATAWIDTH-1:0]   i_b,
  output reg signed [DATAWIDTH:0] o_result, //排列的输入输出的端口声明
);
always@(posedge clock or negedge reset)  //设置输入激励
begin     //计算过程开始
		if( !reset )
			o_result <= 9'd0;
		else if( i_add_sub )
			o_result <= i_a - i_b;
		else 
			o_result <= i_a + i_b;
end  //计算过程结束
endmodule

模块例化

模块例化:将上述定义的模块module例化,相当于创建一个实例
形式如下(与上节定义的函数对应):

add_sub  #(
				.DATAWIDTH(16)   //参数由8改动为16
		  )  add_sub_01(
	.clock               (clock_01),
	.reset               (reset_01),
	.i_add_sub       (i_add_sub_01),
	.i_a                   (i_a_01),
	.i_b                   (i_b_01),
	.o_result         (o_result_01),
	);
遵循的规则端口连接位宽匹配未连接端口外部信号带参数的例化
做法模块内部,输入只能线网,输出线网reg;对模块外部刚好相反最好一致,不一致时最好将宽位宽截位允许未连接状态顺序对应时可省略内部端口的书写参数改与不改灵活掌握

模块测试

模块测试:可使用一个顶层模块(通常称为测试平台Testbench),通过实例调用所定义的模块来进行测试,相当于test函数
特点:由于这个顶层模块不需要被上层调用,没有输入输出端口
举例:

module add_sub_tb; 
     reg                         clock,
     reg                          reset,
     reg                      i_add_sub,
     reg signed  [7:0]              i_a,
     reg signed  [7:0]              i_b,
     wire signed  [7:0]        o_result, //对于外部,输出只能是wire
    );
    always # 5 clock <= ~clock;   //生成时钟 
    always@(posedge clock or negedge reset)  //设置输入激励
    
    //生成输入信号
    begin     
    		if( !reset )
    			begin
    				i_a <= 8'd0; 
    				i_b <= 8'd0; 
    			end
    		else 
    			begin
    				i_a <=  $ random; 
    				i_b <=  $ random; 
    			end
    end  
    
    //实例调用add_sub模块,名字为add_sub
	 add_sub  add_sub(
	.clock               (clock),
	.reset               (reset),
	.i_add_sub       (i_add_sub),
	.i_a                   (i_a),
	.i_b                   (i_b),
	.o_result         (o_result),
	);
	
	initial    //初始化输入
	begin
		clock = 0;
		reset = 0;
		i_add_sub = 0;
		i_a = 0;
		i_b = 0;
		# 100;
		reset = 1;
		#1000;
		i_add_sub = 1; 
	end
endmodule

过程语句

两个过程
always过程不断循环执行,除非使用**$ finish**
initial过程:关键字开始后只能执行一次
特点:一个模块可以包含多个过程,多个过程互相之间并发执行过程不能嵌套多条语句需要使用关键字包裹成代码块

代码块:内部代码一体,可以通过关键字决定顺序执行或并行执行,代码块可以嵌套

代码块包装begin-endfork-join
说明顺序代码块并行代码块

赋值

寄存器变量的过程赋值

阻塞赋值: 符号为 =,该赋值未成功,后边语句不会执行
非阻塞赋值: 符号为** <= **,该句执行时不会阻碍下一语句执行,并且后一句涉及前边的非阻塞赋值变量时,两个语句会同时执行,且后句用到的是前一个语句执行前的数值。

线网变量的连续赋值

连续赋值:将标量或者向量的数值驱动给网线,右边的值有变化,马上就将值赋给左边的变量
使用方式:使用关键字assgin
特点不能像寄存器那样存储当前数值,需要驱动源提供信号,且驱动源是连续不断的、

举例比较(假设a=0,b=1):

赋值操作阻塞赋值非阻塞赋值连续赋值
举例a = b; b= aa<=b ; b<=awire a,b,y; assign y= a&b
结果a=1,b=1a=1,b=0y随a,b而一直变化

时序控制

延时时序控制

延时的参考时间:是这一句本该开始执行的时间
常规延时:赋值语句左边,先进行延时,延时完成后再计算表达式
内嵌延时:赋值语句右边先立即计算表达式,再进行延时,最后把表达式结果赋值给左边
使用方式:使用关键字 # ,“# <延时的时间数字>”

事件时序控制

事件时序控制:如果指定事件发生,则代码被触发执行
指定事件:若是变量,则指的是产生变化时触发;若是指定触发条件如posedge(上升沿)或者negedge(下降沿),则是满足条件时触发;若是监视多个变量时,可用关键字 or“,”,任意一个变量发生变化才触发
使用方式:使用关键字 @,“@(变量或事件名称)”

电平敏感时序控制

电平时序控制:电平或者变量为时,执行后边的代码块

时序控制比较:

时序控制举例结果
常规延时# 5 x = 3;5个系统周期延时后将x赋值为3
变量常规延时parameter latancy=8; # latency x = 38个系统周期延时后将x赋值为3
内嵌延时z = # 8 (x + y);当前时刻的x,y计算结果,8个系统周期延时后赋给z
变量事件延时@(clk) x = 1;变量clk发生变化时将1赋值给x
触发条件事件延时@(posedge clk) x=1变量clk上升沿时将1赋值给x,(下降沿为negedge)
多事件敏感延时@(a or b or c) 或@(a , b)a或b或c任一变化时,触发代码块
所有事件敏感延时@ * 或 @(*)对所有输入变量敏感
电平延时wait(a)变量a为真,执行后边代码块

条件语句

任务和函数

编译指令

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值