首页 Verilog数字系统设计教程(夏宇闻)例题源下册例题练习1-9

Verilog数字系统设计教程(夏宇闻)例题源下册例题练习1-9

举报
开通vip

Verilog数字系统设计教程(夏宇闻)例题源下册例题练习1-9 设计示范和上机习题 练习一.简单的组合逻辑设计 //(方法一): //---------------文件名 compare.v ----------------- module compare(equal,a,b); input a,b; output equal; assign equal = (a==b)? 1 : 0; //a等于b时,equal输出为1;a不等于b时,equal输出为0。 endmodule //(方法二): module compare(equal,...

Verilog数字系统设计教程(夏宇闻)例题源下册例题练习1-9
设计示范和上机习题 练习一.简单的组合逻辑设计 //(方法一): //---------------文件名 compare.v ----------------- module compare(equal,a,b); input a,b; output equal; assign equal = (a==b)? 1 : 0; //a等于b时,equal输出为1;a不等于b时,equal输出为0。 endmodule //(方法二): module compare(equal,a,b); input a,b; output equal; reg equal; always @(a or b) if(a==b) //a等于b时,equal输出为1; equal =1; else //a不等于b时,equal输出为0。 equal = 0; //思考:如果不写else 部分会产生什么逻辑? endmodule //------------------------------------------------------------- //----------测试模块源代码(方法之一): `timescale 1ns/1ns // 定义时间单位。 `include "./compare.v" // 包含模块文件。在有的仿真调试环境中并不需要此语句。 //而需要从调试环境的菜单中键入有关模块文件的路径和名称 module t; reg a,b; wire equal; initial // initial常用于仿真时信号的给出。 begin a=0; b=0; #100 a=0; b=1; #100 a=1; b=1; #100 a=1; b=0; #100 a=0; b=0; #100 $stop; //系统任务,暂停仿真以便观察仿真波形。 end compare m(.equal(equal),.a(a),.b(b)); //调用被测试模块t.m endmodule //---------- 测试模块源代码(方法之二):------------------------- `timescale 1ns/1ns // 定义时间单位。 `include "./compare.v" // 包含模块文件。在有的仿真调试环境中并不需要此语句。 //而需要从调试环境的菜单中键入有关模块文件的路径和名称 module t; reg a,b; reg clock; wire equal; initial // initial常用于仿真时信号的给出。 begin a=0; b=0; clock = 0; //定义一个时钟变量 end always #50 clock = ~clock; //产生周期性的时钟 always @ (posedge clock) //在每次时钟正跳变沿时刻产生不同的a 和 b begin a = {$random}%2; // 每次a是 0还是1是随机的。 b = {$random}%2; // 每次b是 0还是1是随机的。 end initial begin #100000 $stop; end //系统任务,暂停仿真以便观察仿真波形。 compare m(.equal(equal),.a(a),.b(b)); //调用被测试模块t.m endmodule 练习二. 简单分频时序逻辑电路的设计 //------------------------- 文件名:half_clk.v -------------------------------- module half_clk(reset,clk_in,clk_out); input clk_in,reset; output clk_out; reg clk_out; always @(posedge clk_in) begin if(!reset) clk_out=0; else clk_out=~clk_out; end endmodule //---------- 测试模块的源代码:------------------------ //------------------- 文件名top.v ----------------------------- `timescale 1ns/100ps `define clk_cycle 50 module top; reg clk,reset; wire clk_out; always #`clk_cycle clk = ~clk; //产生测试时钟 initial begin clk = 0; reset = 1; #10 reset = 0; #110 reset = 1; #100000 $stop; end half_clk m0(.reset(reset),.clk_in(clk),.clk_out(clk_out)); endmodule 练习三. 利用条件语句实现计数分频时序电路 //-------------- 模块源代码:----------------------------- // --------------- fdivision.v ----------------------------- module fdivision(RESET,F10M,F500K); input F10M,RESET; output F500K; reg F500K; reg [7:0]j; always @(posedge F10M) if(!RESET) //低电平复位。 begin F500K <= 0; j <= 0; end else begin if(j==19) //对计数器进行判断,以确定F500K信号是否反转。 begin j <= 0; F500K <= ~F500K; end else j <= j+1; end endmodule //------------- 测试模块源代码:------------------------- //--------------- fdivision_Top.v ------------------------ `timescale 1ns/100ps `define clk_cycle 50 module division_Top; reg F10M,RESET; wire F500K_clk; always #`clk_cycle F10M_clk = ~ F10M_clk; initial begin RESET=1; F10M=0; #100 RESET=0; #100 RESET=1; #10000 $stop; end fdivision fdivision (.RESET(RESET),.F10M(F10M),.F500K(F500K_clk)); endmodule 练习四. 阻塞赋值与非阻塞赋值的区别 // ---------- 模块源代码:---------------------- // ------------- blocking.v --------------- module blocking(clk,a,b,c); output [3:0] b,c; input [3:0] a; input clk; reg [3:0] b,c; always @(posedge clk) begin b = a; c = b; $display("Blocking: a = %d, b = %d, c = %d ",a,b,c); end endmodule //------------- non_blocking.v ------------------- module non_blocking(clk,a,b,c); output [3:0] b,c; input [3:0] a; input clk; reg [3:0] b,c; always @(posedge clk) begin b <= a; c <= b; $display("Non_Blocking: a = %d, b = %d, c = %d ",a,b,c); end endmodule // ---------- 测试模块源代码:-------------------------- //------------- compareTop.v ----------------------------- `timescale 1ns/100ps `include "./blocking.v" `include "./non_blocking.v" module compareTop; wire [3:0] b1,c1,b2,c2; reg [3:0] a; reg clk; initial begin clk = 0; forever #50 clk = ~clk; //思考:如果在本句后还有语句,能否执行?为什么? end initial begin a = 4'h3; $display("____________________________"); # 100 a = 4'h7; $display("____________________________"); # 100 a = 4'hf; $display("____________________________"); # 100 a = 4'ha; $display("____________________________"); # 100 a = 4'h2; $display("____________________________"); # 100 $display("____________________________"); $stop; end non_blocking non_blocking(clk,a,b2,c2); blocking blocking(clk,a,b1,c1); endmodule 练习五. 用always块实现较复杂的组合逻辑电路 //---------------文件名 alu.v -------------------------- `define plus 3'd0 `define minus 3'd1 `define band 3'd2 `define bor 3'd3 `define unegate 3'd4 module alu(out,opcode,a,b); output[7:0] out; reg[7:0] out; input[2:0] opcode; input[7:0] a,b; //操作数。 always@(opcode or a or b) //电平敏感的always块 begin case(opcode) `plus: out = a+b; //加操作。 `minus: out = a-b; //减操作。 `band: out = a&b; //求与。 `bor: out = a|b; //求或。 `unegate: out=~a; //求反。 default: out=8'hx; //未收到指令时,输出任意态。 endcase end endmodule //----------- 指令译码器的测试模块源代码:-------------- //------------- alutest.v ----------------- `timescale 1ns/1ns `include "./alu.v" module alutest; wire[7:0] out; reg[7:0] a,b; reg[2:0] opcode; parameter times=5; initial begin a={$random}%256; //Give a radom number blongs to [0,255] . b={$random}%256; //Give a radom number blongs to [0,255]. opcode=3'h0; repeat(times) begin #100 a={$random}%256; //Give a radom number. b={$random}%256; //Give a radom number. opcode=opcode+1; end #100 $stop; end alu alu1(out,opcode,a,b); endmodule 练习六. 在Verilog HDL中使用函数 //--------------- 模块源代码:--------------- //----------- 文件名 tryfunct.v -------------------- module tryfunct(clk,n,result,reset); output[31:0] result; input[3:0] n; input reset,clk; reg[31:0] result; always @(posedge clk) //clk的上沿触发同步运算。 begin if(!reset) //reset为低时复位。 result<=0; else begin result <= n * factorial(n)/((n*2)+1); end //verilog在整数除法运算结果中不考虑余数 end function [31:0] factorial; //函数定义,返回的是一个32位的数 input [3:0] operand; //输入只有一个四位的操作数 reg [3:0] index; //函数内部计数用中间变量 begin factorial = operand ? 1 : 0; //先定义操作数为零时函数的输出为零,不为零时为1 for(index = 2; index <= operand; index = index + 1) factorial = index * factorial; //表示阶乘的算术迭代运算 end endfunction endmodule //-------------- 测试模块源代码:------------------ `include "./tryfunct.v" `timescale 1ns/100ps `define clk_cycle 50 module tryfuctTop; reg[3:0] n,i; reg reset,clk; wire[31:0] result; initial begin clk=0; n=0; reset=1; #100 reset=0; //产生复位信号的负跳沿 #100 reset=1; //复位信号恢复高电平后才开始输入n for(i=0;i<=15;i=i+1) begin #200 n=i; end #100 $stop; end always #`clk_cycle clk=~clk; tryfunct m(.clk(clk),.n(n),.result(result),.reset(reset)); endmodule 练习七. 在Verilog HDL中使用任务(task) //-------------- 模块源代码:---------------- //-----------------文件名 sort4.v ------------------ module sort4(ra,rb,rc,rd,a,b,c,d); output[3:0] ra,rb,rc,rd; input[3:0] a,b,c,d; reg[3:0] ra,rb,rc,rd; reg[3:0] va,vb,vc,vd; always @ (a or b or c or d) begin {va,vb,vc,vd}={a,b,c,d}; sort2(va,vc); //va 与vc互换。 sort2(vb,vd); //vb 与vd互换。 sort2(va,vb); //va 与vb互换。 sort2(vc,vd); //vc 与vd互换。 sort2(vb,vc); //vb 与vc互换。 {ra,rb,rc,rd}={va,vb,vc,vd}; end task sort2; inout[3:0] x,y; reg[3:0] tmp; if(x>y) begin tmp=x; //x与y变量的内容互换,要求顺序执行,所以采用阻塞赋值方式。 x=y; y=tmp; end endtask endmodule // --------- 测试模块源代码:--------------- `timescale 1ns/100ps `include "sort4.v" module task_Top; reg[3:0] a,b,c,d; wire[3:0] ra,rb,rc,rd; initial begin a=0;b=0;c=0;d=0; repeat(50) begin #100 a ={$random}%15; b ={$random}%15; c ={$random}%15; d ={$random}%15; end #100 $stop; sort4 sort4 (.a(a),.b(b),.c(c),.d(d), .ra(ra),.rb(rb),.rc(rc),.rd(rd)); endmodule 练习八. 利用有限状态机进行时序逻辑的设计 // ------------- 模块源代码:------------------ //---------------- 文件名 seqdet.v ----------------- module seqdet(x,z,clk,rst,state); input x,clk,rst; output z; output[2:0] state; reg[2:0] state; wire z; parameter IDLE='d0, A='d1, B='d2, C='d3, D='d4, E='d5, F='d6, G='d7; assign z = ( state==E && x==0 )? 1 : 0; //当x 序列10010最后一个0刚到时刻,时钟沿立刻将状态变为E,此时z 应该变为高 always @(posedge clk) if(!rst) begin state <= IDLE; end else casex(state) IDLE : if(x==1) //第一个码位对,记状态A begin state <= A; end A: if(x==0) //第二个码位对,记状态B begin state <= B; end B: if(x==0) //第三个码位对,记状态C begin state <= C; end else //第三个码位不对,前功尽弃,记状态为F begin state <= F; end C: if(x==1) //第四个码位对 begin state <= D; end else //第四个码位不对,前功尽弃,记状态为G begin state <= G; end D: if(x==0) //第五个码位对,记状态E begin state <= E; //此时开始应有z 的输出 end else //第五个码位不对,前功尽弃,只有刚进入的1有用,回到第一个码位对状态,记状态A begin state <= A; end E: if(x==0) //连着前面已经输入的x 序列10010考虑,又输入了0码位可以认为第三个码位已对,记状态C begin state <= C; end else //前功尽弃,只有刚输入的1码位对,记状态为A begin state <= A; end F: if(x==1) //只有刚输入的1码位对,记状态为A begin state <= A; end else //又有1码位对,记状态为B begin state <= B; end G: if(x==1) //只有刚输入的1码位对,记状态为A begin state <= F; end default:state=IDLE; //缺省状态为初始状态。 endcase endmodule //----------------- 测试模块源代码:---------------- //---------------文件名 seqdet.v ------------------- `timescale 1ns/1ns `include "./seqdet.v" module seqdet_Top; reg clk,rst; reg[23:0] data; wire[2:0] state; wire z,x; assign x=data[23]; always #10 clk = ~clk; always @(posedge clk) data={data[22:0],data[23]}; //形成数据向左移环行流,最高位与x 连接 initial begin clk=0; rst=1; #2 rst=0; #30 rst=1; data ='b1100_1001_0000_1001_0100; #500 $stop; end seqdet m(x,z,clk,rst,state); endmodule 练习九.利用状态机实现比较复杂的接口设计 //--------- 模块源代码:---------------------------- module writing(reset,clk,address,data,sda,ack); input reset,clk; input[7:0] data,address; output sda,ack; //sda负责串行数据输出;          //ack是一个对象操作完毕后,模块给出的应答信号。 reg link_write; //link_write 决定何时输出。 reg[3:0] state; //主状态机的状态字。 reg[4:0] sh8out_state; //从状态机的状态字。 reg[7:0] sh8out_buf; //输入数据缓冲。 reg finish_F; //用以判断是否处理完一个操作对象。 reg ack; parameter idle=0,addr_write=1,data_write=2,stop_ack=3; parameter bit0=1,bit1=2,bit2=3,bit3=4,bit4=5,bit5=6,bit6=7,bit7=8; assign sda = link_write? sh8out_buf[7] : 1'bz; always @(posedge clk) begin if(!reset) //复位。 begin link_write<= 0; //挂起串行单总线 state <= idle; finish_F <= 0; //结束标志清零 sh8out_state<=idle; ack<= 0; sh8out_buf<=0; end else case(state) idle: begin link_write <= 0; //断开串行单总线 finish_F <= 0; sh8out_state<=idle; ack<= 0; sh8out_buf<=address; //并行地址存入寄存器 state <= addr_write; //进入下一个状态 end addr_write: //地址的输入。 begin if(finish_F==0) begin shift8_out; end //地址的串行输出 else begin sh8out_state <= idle; sh8out_buf <= data; //并行数据存入寄存器 state <= data_write; finish_F <= 0; end end data_write: //数据的写入。 begin if(finish_F==0) begin shift8_out; end //数据的串行输出 else begin link_write <= 0; state <= stop_ack; finish_F <= 0; ack <= 1; //向信号源发出应答。 end end stop_ack: //向信号源发出应答结束。 begin ack <= 0; state <= idle; end endcase end task shift8_out; // 地址和数据的串行输出。 begin case(sh8out_state) idle: begin link_write <= 1; //连接串行单总线,立即输出地址或数据的最高位(MSB) sh8out_state <= bit7; end bit7: begin link_write <= 1; //连接串行单总线 sh8out_state <= bit6; sh8out_buf <= sh8out_buf<<1; //输出地址或数据的次高位(bit 6) end bit6: begin sh8out_state<=bit5; sh8out_buf<=sh8out_buf<<1; end bit5: begin sh8out_state<=bit4; sh8out_buf<=sh8out_buf<<1; end bit4: begin sh8out_state<=bit3; sh8out_buf<=sh8out_buf<<1; end bit3: begin sh8out_state<=bit2; sh8out_buf<=sh8out_buf<<1; end bit2: begin sh8out_state<=bit1; sh8out_buf<=sh8out_buf<<1; end bit1: begin sh8out_state<=bit0; sh8out_buf<=sh8out_buf<<1; //输出地址或数据的最低位(LSB) end bit0: begin link_write<= 0; //挂起串行单总线 finish_F<= 1; //建立结束标志 end endcase end endtask endmodule // ------------- 测试模块源代码:---------------- `timescale 1ns/100ps `define clk_cycle 50 module writingTop; reg reset,clk; reg[7:0] data,address; wire ack,sda; always #`clk_cycle clk = ~clk; initial begin clk=0; reset=1; data=0; address=0; #(2*`clk_cycle) reset=0; #(2*`clk_cycle) reset=1; #(100*`clk_cycle) $stop; end always @(posedge ack) //接收到应答信号后,给出下一个处理对象。 begin data=data+1; address=address+1; end writing writing(.reset(reset),.clk(clk),.data(data), .address(address),.ack(ack),.sda(sda)); endmodule 1 1
本文档为【Verilog数字系统设计教程(夏宇闻)例题源下册例题练习1-9】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_031052
暂无简介~
格式:doc
大小:96KB
软件:Word
页数:17
分类:互联网
上传时间:2018-09-08
浏览量:55