| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-11-18 | zgf | 初次建立 | ===== 实验五:逻辑门实验——基本运算符 ===== ==== 一、 实验目的与意义 ==== - 学习逻辑运算符的定义。 - 掌握Verilog HDL语言中基本运算符的使用方法。 - 掌握HqFpga软件的使用方法。 ==== 二、 实验设备及平台 ==== - iCore3L 双核心板。 - XiST USB Cable(或相同功能)仿真器。 - Micro USB线缆。 - 装有HqFpga2.8.5版本开发软件的电脑一台。 ==== 三、 实验原理 ==== * 运算符是用来执行程序代码运算的,是一段代码的重要组成部分。在Verilog HDL中按照功能划分,运算符可分为算术运算符、逻辑运算符、关系运算符、条件运算符、按位运算符、拼接运算符、移位运算符、等式运算符、赋值运算符等类型。按照运算符所带的操作数的个数划分可分为3类,即: * (1)单目操作符,运算符可带一个操作数; * (2)双目操作符,运算符可带两个操作数; * (3)三目操作符,运算符可带三个操作数。 === 1、算术运算符 === * 在Verilog HDL中的算术运算符有多种,其中最常用的有4种,如表5-1所示。 * 表5-1 算术算符运 |操作符 |执行的操作 |操作数个数 |表达式| |+ |加法运算 |2 |rega + 10| |- |减法运算 |2 |rega - 10| |* |乘法运算 |2 |rega * 10| |/ |除法运算 |2 |23 / 10,运行结果为2。| * 在基本算术运算符应用过程中需要注意: * (1)在进行整数除法运算时,省略所有小数部分,只保留整数部分; * (2)在进行算术运算操作时,如果操作符的某个操作数出现x或z时,则整个操作的运算结果为x。 === 2、逻辑运算符 === * 在Verilog HDL中有三种逻辑运算符,如表5-2所示。逻辑运算的结果只有两种:0(假)和1(真),其逻辑真值如表5-3所示。 * 表5-2 逻辑运算符 |操作符 |执行的操作 |操作数个数 |表达式| |! |逻辑求反 |1 |!a| |&& |逻辑与 |2 |a && b| |''||'' |逻辑或 |2 |''a || b'' | * 表5-3 逻辑运算真值表 |a |b |!a |!b |a && b |''a || b'' | |1 |1 |0 |0 |1 |1| |1 |0 |0 |1 |0 |1| |0 |1 |1 |0 |0 |1| |0 |0 |1 |1 |0 |0| === 3、关系运算符 === * 关系运算符主要表征两者之间的关系,常用于两个操作数的比较,常用的有四种符号类型,如表5-4所示。 * 表5-4 关系运算符 |操作符 |执行的操作 |操作数个数| 表达式| |< |小于 |2 |a < b| |> |大于 |2 |a > b| |< = |小于等于 |2 |a <= b| |>= |大于等于 |2 |a >= b| * 在进行关系运算时,如果表达式的两个操作数之间的关系时正确的,则运行结果为1(真),否则,运行结果为0(假);如果表达式中的某个操作数为不定值(x和z),则运行结果为x。 === 4、条件运算符 === * 条件运算是根据条件表达式的运行结果来选择执行表达式的,有3个操作数,其符号为“?:”,使用方式如下: con_expression ? true_expression : false_expression; * 在运行条件运算符时,若条件表达式(con_expression)为真,则运行真表达式(true_expression),否则,运行假表达式(false_expression)。例如: wire data_out = sel_en ? a : b; * 其运行结果为:若sel_en为真,data_out的值取a;否则,data_out的值取b。 === 5、按位运算符 === * 按位运算是两个操作数按照对应位进行“与”、“或”、“非”等逻辑操作,常用的按位运算符有5种,如表5-5所示。 * 表5-5 按位运算符 |操作符 |执行的操作 |操作数个数 |表达式| |~ |按位求反 |1 |''~a''| |& |按位与 |2 |''a & b''| |''|'' |按位或 |2 |''a | b''| |''^'' |按位异或 |2 |''a ^ b''| |''~^,^~'' |按位同或 |2 |''a ~^ b,a ^~ b''| * 在按位运算中,若两个操作数的位宽不一致,则会自动将两个操作数右对齐,高位补0后进行运算。 === 6、拼接运算符 === * 拼接运算是将两个或多个操作数的某些位拼接起来得到一个新数据的表达式,其运算符号为“{}”,被拼接的操作数用“,”隔开,其表达式如下: {signal1,signal2} === 7、移位运算符 === * 在Verilog HDL中有两种移位运算符,如表5-6所示。 * 表5-6 移位运算符 |操作符 |执行的操作 |操作数个数 |表达式| |>> |右移 |2 |a >> m,a为操作数,m为移的位数| |<< |左移 |2 |a << m,a为操作数,m为移的位数| === 8、等式运算符 === * 在Verilog HDL中有四种等式运算符,如表5-7所示。 * 表5-7 等式运算符 |操作符 |执行的操作 |操作数个数 |表达式| |== |等于 |2 |a == b| |!= |不等于 |2 |a != b| |=== |等于 |2 |a === b| |!== |不等于 |2 |a !=== b| * 在进行等式运算中,“==”和“!=”又被称作是逻辑等式运算符,由于等式运算中的两个操作数有可能是x和z,因此其运算结果可能是不定值x。但是,“===”和“!==”对比时要求两个操作数必须完全一致,因此其运行结果只有0和1两种。 === 9、赋值运算符 === * 赋值运算就是Verilog HDL的赋值语句,根据赋值操作后变量改变方式的不同,赋值语句又分为连续赋值和过程赋值两种,如表5-8所示。 * 表5-8 赋值运算符 |操作符 |执行的操作 |操作数个数 |表达式| |= |连续赋值 |不定 |a = b| |= |过程赋值 |不定 |a = b| |<= |过程赋值 |不定 |a <= b| * 通常,连续赋值运算用于“assign”语句中,用于对wire型变量进行赋值,“=”两侧的操作数是随时变化的,例如: * assign a = b,当b信号发生变化时,a也随之变化。 * 在过程赋值中,按照操作数改变时刻的不同,分为阻塞赋值(=)和非阻塞赋值(<=)两种。 * (1)阻塞赋值方式 * 1) 赋值语句执行完成后,才结束块的运行; * 2) 操作数在赋值语句执行后立刻改变变量值; * (2)非阻塞赋值方式 * 1)在语句块中,赋值语句执行完成后,在块结束前,赋值语句中操作数的值保持不变; * 2)块结束后,对操作数进行赋值操作,且所赋值为上一次赋值得到的; * 3)非阻塞赋值方式常用于编写可综合的时序逻辑模块中。 ==== 四、 代码讲解 ==== === 1、算术运算符表达式 === * 其代码如下: /*************************************************/ //算数运算符:"+"、"-"、"*"、“/” assign out_a = x1 + y1;//加法运算符表达式 assign out_b = y1 - x1;//减法运算符表法式 assign out_c = 2 * x1;//乘法运算符 assign out_d = y1 / 5;//除法运算符 === 2、逻辑运算符表达式 === * 其代码如下: /*************************************************/ //逻辑运算符:“!”、“&&”、“||”,逻辑运算符的结果只能是“1”或者“0” assign out_e = !x2;//逻辑求反表达式 assign out_f = x2 && y2;//逻辑与表达式 assign out_g = x2 || y2;//逻辑或表达式 === 3、关系运算符表达式 === * 其代码如下: /*************************************************/ //关系运算符:“<”、“>”、“<=”、“>=” //条件运算符表达式:con_expression ? true_expression ? false_expression; assign out_h = (x3 < y3) ? (y3 - x3) : 4'd0;//小于号表达式 assign out_i = (x3 > y3) ? 4'd0 : (y3 + x3);//大于号表达式 assign out_j = (y3 <= z3) ? (y3 - x3) : 4'd0;//小于等于号表达式 assign out_k = (y3 >= z3) ? (y3 - x3) : 4'd0;//大于等于号表达式 === 4、按位运算符表达式 === * 其代码如下: /*************************************************/ //按位运算符:“~”、“&”、“|”、“^”、“~^” //在按位运算中,若两个操作数的位宽不一致,则会自动将两个操作数右对齐,高位补0后进行运算 assign out_l = ~x4;//按位求反表达式 assign out_m = x4 & y4;//按位与表达式 assign out_n = x4 | y4;//按位或表达式 assign out_o = x4 ^ y4;//按位异或表达式 assign out_p = x4 ~^ y4;//按位同或表达式 === 5、拼接运算符 === * 其代码如下: /*************************************************/ //拼接运算符 assign q = {x5,y5};//拼接运算符表达式 === 6、移位运算符表达式 === * 其代码如下: /*************************************************/ //移位运算符:“<<”、“>>” assign r = x6 << 3;//左移表达式 assign s = x6 >>3;//右移表达式 ==== 五、 实验步骤 ==== 1、 将下载器连接到iCore3L双核心板; 2、 通过Micro USB线给iCore3L供电; 3、 将编写好的代码进行编译,编译无报错之后点击“全部运行”按钮,进行全编译。 {{ :icore3l:icore3l_fpga_5_1.png?direct&900 |图5-1 全编译工程}} 4、 全编译通过后,点击左上角的“调试模式”按钮,进入调试模式。然后点击“采集调试信息”按钮。 {{ :icore3l:icore3l_fpga_5_2.png?direct&900 |图5-2 采集调试信息}} 5、 将clk_25m信号设置为采样时钟,rst_n设置为采样且触发,其他信号设置为仅采样;然后点击红框中“ILVA配置”按钮,即红框中齿轮状图标。 {{ :icore3l:icore3l_fpga_5_3.png?direct |图5-3 设置采样信号}} 6、 将采样深度设置为1024,然后点击确定,并点击“文件”按钮,下拉菜单中点击“保存工程…”。 {{ :icore3l:icore3l_fpga_5_4.png?direct |图5-4 设置采样深度}} 7、 点击“实现→下载”按钮,将仿真文件下载到FPGA中,然后点击实时调试按钮。 {{ :icore3l:icore3l_fpga_5_5.png?direct&900 |图5-5 将仿真文件下载到FPGA}} 8、 单击rst_n信号,设置触发表达式,将触发类型设置为“算数比较”,“等于”,“1’h1”,然后点击确定,再点击左上角的“运行”,开始进行信号的采集。 {{ :icore3l:icore3l_fpga_5_6.png?direct&900 |图5-6 设置触发表达式及运行}} 9、 信息输出窗口出现“Done:1”,表示调试完成,同时会出现下图中调试完成的提示,点击“OK”即可;然后点击工具栏红框中的“波形”按钮,查看调试波形。 {{ :icore3l:icore3l_fpga_5_7.png?direct&900 |图5-7 调试完成提示}} 10、 如果出现如下弹窗,则检查触发条件设置是否满足触发要求,或者采样深度是深度是否过大等原因。 {{ :icore3l:icore3l_fpga_5_8.png?direct |图5-8 调试失败提示}} 11、 通过HqInsight Debugger工具对运算结果进行采集,进行对比验证HqInsight Debugger采集到的运算结果与逻辑运算的实验结果。 {{ :icore3l:icore3l_fpga_5_9.png?direct&900 |图5-9 波形图显示运行结果1}} {{ :icore3l:icore3l_fpga_5_10.png?direct |图5-10 波形图显示运行结果2}} ==== 六、 拓展实验 ==== - 更改实验代码中的变量的初始值,看看运算结果有何不同; - 深刻理解阻塞赋值与非阻塞赋值的区别。