Verilog语法简介(3) |
您所在的位置:网站首页 › 哈尔滨哪里有精工手表专柜 › Verilog语法简介(3) |
运算符和表达式 Verilog HDL中的操作符可以分为下述类型: 1) 算术操作符 2) 关系操作符 3) 相等操作符 4) 逻辑操作符 5) 按位操作符 6) 归约操作符 7) 移位操作符 8) 条件操作符 9) 连接和复制操作符 下表显示了所有操作符的优先级和名称。 操作符从最高优先级(顶行)到最低优先级 (底行)排列。同一行中的操作符优先级相同。 算术运算符在常用的算术运算符主要是 : 加法(二元运算符):“+”; 减法 (二元运算符):“-”; 乘法(二元运算符):“*”; 在算术运算符的使用中,注意如下两个问题: 1. 算术操作结果的位数长度 算术表达式结果的长度由最长的操作数决定。在赋值语句下,算术操作结果的长度由操作符左端目标长度决定。考虑如下实例: reg [3:0] arc, bar, crt; reg [5:0] frx; . . . arc = bar + crt; frx = bar + crt; 第一个加的结果长度由bar ,crt 和a rc 长度决定,长度为4 位。 第二个加法操作的长度同样由frx 的长度决定(frx 、bat 和crt 中的最长 长度),长度为6位。 在第一个赋值中,加法操作的溢出部分被丢弃;而在第二个赋值中,任何溢 出的位存储在结 果位frx [ 4 ]中。 在较大的表达式中,中间结果的长度如何确定?在Verilog HDL 中定义了如 下规则:表达式中的所有中间结果应取最大操作数的长度(赋值时,此规则也包 括左端目标)。考虑另一个实例: wire [4:1] box, drt; wire [5:1] cfg; wire [6:1] peg; wire [8:1] adt; . . . assign adt = (box + cfg) + (drt + peg) ; 表达式右端的操作数最长为6 ,但是将左端包含在内时,最大长度为8 。所以所有的加操作使用8 位进行。 例如:box 和cfg 相加的结果长度为8 位。 2. 有符号数和无符号数在设计中,请先按无符号数进行。 关系运算符关系运算符有: ?>(大于) ?=(不小于) ? 45 结果为假(0 ),而: 52 < 8'hxFF 结果为x 。 如果操作数长度不同,长度较短的操作数在最重要的位方向(左方)添0 补 齐。例如: 'b1000 > = 'b01110 等价于:'b01000 > = 'b01110 结果为假(0 )。 在逻辑相等与不等的比较中,只要一个操作数含有x 或z,比较结果为未知 (x),如: 假定: Data = 'b11x0; Addr = 'b11x0; 那么: Data = = Addr 比较结果不定,也就是说值为x。 逻辑运算符逻辑运算符有: && (逻辑与) || (逻辑或) !(逻辑非) 用法为:(表达式1) 逻辑运算符 (表达式2) .... 这些运算符在逻辑值0(假) 或1(真) 上操作。逻辑运算的结果为0 或1 。 例如, 假定: crd = 'b0; //0 为假 dgs = 'b1; //1 为真 那么: crd && dgs 结果为0 (假) crd || dgs 结果为1 (真) !dgs 结果为0 (假) 逻辑与(&&)的真值表如下: 逻辑或的真值表如下: 按位逻辑运算符按位运算符有: ~(一元非) :(相当于非门运算)(一位数可用!) &(二元与):(相当于与门运算) |(二元或): (相当于或门运算) ^(二元异或) :(相当于异或门运算) ~ ^, ^ ~(二元异或非即同或):(相当于同或门运算) 这些操作符在输入操作数的对应位上按位操作,并产生向量结果。下表显示 对于不同按位逻辑运算符按位操作的结果: 例如: 假定, A = 'b0110; B = 'b0100; 那么: A | B 结果为0110 A & B 结果为0100 如果操作数长度不相等, 长度较小的操作数在最左侧添0补位。 例如, 'b0110 ^ 'b10000 与如下式的操作相同: 'b00110 ^ 'b10000 结果为'b10110。 条件运算符条件操作符根据条件表达式的值选择表达式,形式如下: cond_expr ? expr1 : expr2 如果cond_expr 为真(即值为1 ),选择expr1 ; 如果cond_expr 为假(值为0 ), 选择expr2 。 如果cond_expr 为x 或z ,结果将是按以下逻辑expr1 和expr2 按 位操作的值: 0 与0 得0 ,1 与1 得1 ,其余情况为x 。 如下所示: wire [2:0] student = marks > 18 ? grade_a : grade_c; 计算表达式marks > 18; 如果真,grade_a 赋值为student; 如果marks < =18, grade_c 赋值为student 。 连接运算符连接操作是将小表达式合并形成大表达式的操作。 形式如下: {expr1, expr2, . . .,exprN} 实例如下所示: wire [7:0] Dbus; assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[ 3 ]}; //以反转的顺序将低端4 位赋给高端4 位。 assign Dbus = {Dbus [3:0], Dbus [7:4]}; //高4 位与低4 位交换。 由于非定长常数的长度未知, 不允许连接非定长常数。 例如,下列式子非法: {Dbus,5} //不允许连接操作非定长常数。 条件语句if 语句的语法如下: if(condition_1) procedural_statement_1 {else if(condition_2) procedural_statement_2} {else procedural_statement_3} 如果对condition_1 求值的结果为个非零值, 那么 procedural_statement_1 被执, 如果condition_1 的值为0 、x 或z ,那么 procedural_statement_1 不执行。如果存在一个else 分支,那么这个分支被执 行。 以下是一个例子。 if (sum < 60) begin grade = c; total_c = total _c + 1; end else if(sum < 75) begin grade = b; total_b = total_b + 1; end else begin grade = a; total_a = total_a + 1; end 注意条件表达式必须总是被括起来,如果使用if - if - else 格式,那么 可能会有二义性,如下例 所示: if (clk == 1) if (reset== 1) q = 0; else q = d; 问题是最后一个else 属于哪一个if?它是属于第一个if 的条件(clk)还是 属于第二个if的条件(reset)? 这在Verilog HDL 中已通过将else 与最近的没 有else 的if 相关联来解决。在这个例子中,else 与内层if 语句相关联。 规范建议: 1、条件表达式需用括号括起来。 2、若为if - if 语句,请使用块语句 begin --- end : if(clk == 1) begin if (reset== 1) q = 0; else q = d; end 以上两点建议是为了使代码更加清晰,防止出错。 3、对if 语句,除非在时序逻辑中,if 语句需要有else语句。若没有缺省 语句,设计将产生一个锁存器,锁存器在asic设计中有诸多的弊端。 如下一例: if (t == 1) q = d; 没有else 语句,当t为1(真)时,d 被赋值给q,当t为0(假)时,因为没 有else 语句,电路保持 q 以前的值,这就形成一个锁存器。 case 语句case 语句是一个多路条件分支形式,其语法如下: case(case_expr) case_item_expr{ ,case_item_expr} :procedural_statement . . . [default:procedural_statement] endcase case 语句首先对条件表达式case_expr 求值,然后依次对各分支项求值并 进行比较,第一个与条件表达式值相匹配的分支中的语句被执行。可以在1 个分 支中定义多个分支项;这些值不需要互斥。缺省分支覆盖所有没有被分支表达式 覆盖的其他分支。 例: case (HEX) 4'b0001 : led = 7'b1111001; // 1 4'b0010 : led = 7'b0100100; // 2 4'b0011 : led = 7'b0110000; // 3 4'b0100 : led = 7'b0011001; // 4 4'b0101 : led = 7'b0010010; // 5 4'b0110 : led = 7'b0000010; // 6 4'b0111 : led = 7'b1111000; // 7 4'b1000 : led = 7'b0000000; // 8 4'b1001 : led = 7'b0010000; // 9 4'b1010 : led = 7'b0001000; // a 4'b1011 : led = 7'b0000011; // b 4'b1100 : led = 7'b1000110; // c 4'b1101 : led = 7'b0100001; // d 4'b1110 : led = 7'b0000110; // e 4'b1111 : led = 7'b0001110; // f default : led = 7'b1000000; // 0 endcase 规范建议: case 的缺省项必须写,防止产生锁存器。 说明: 只有组合逻辑才可能产生锁存器,时序逻辑不会产生锁存器。 本文摘录于Verilog 红宝书_语法篇 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |