您好,欢迎来到小奈知识网。
搜索
您的当前位置:首页Verilog及FPGA学习考试必备经典程序(五)

Verilog及FPGA学习考试必备经典程序(五)

来源:小奈知识网
目录

1. 非流水线方式8 位全加器 ............................................................................... 2 2. 4 级流水方式的 8 位全加器 ........................................................................... 2 3. 两个加法器和一个选择器的实现方式 ................................................................ 4 4. 两个选择器和一个加法器的实现方式 ................................................................ 4 5. 状态机设计的例子 .......................................................................................... 5 6. 自动转换量程频率计控制器 ............................................................................. 6 7. 8 位全加器 .................................................................................................... 9 8. 8 位寄存器 .................................................................................................... 9 9. 累加器顶层连接文本描述 .............................................................................. 10 10. 用`include 描述的累加器 .............................................................................. 10 11. 阻塞赋值方式描述的移位寄存器 1 ................................................................. 11 12. 阻塞赋值方式描述的移位寄存器2 .................................................................. 11 13. 阻塞赋值方式描述的移位寄存器3 .................................................................. 12 14. 非阻塞赋值方式描述的移位寄存器 ................................................................. 12 15. 长帧同步时钟的产生 ..................................................................................... 12 16. 引入了D 触发器的长帧同步时钟的产生 ......................................................... 13 17. 数字跑表 ...................................................................................................... 14 18. 4 位数字频率计控制模块 .............................................................................. 16 19. 4 位数字频率计计数子模块 ........................................................................... 17 20. 频率计锁存器模块 ........................................................................................ 17 21. 交通灯控制器 ............................................................................................... 18 22. “梁祝”乐曲演奏电路 .................................................................................. 21 23. 自动售饮料机 ............................................................................................... 26

1

1. 非流水线方式8 位全加器

module adder8(cout,sum,ina,inb,cin,clk); output[7:0] sum; output cout; input[7:0] ina,inb; input cin,clk;

reg[7:0] tempa,tempb,sum; reg cout; reg tempc;

always @(posedge clk) begin

tempa=ina; tempb=inb; tempc=cin; //输入数据锁存 end

always @(posedge clk) begin

{cout,sum}=tempa+tempb+tempc; end endmodule

2. 4 级流水方式的 8 位全加器

module pipeline(cout,sum,ina,inb,cin,clk); output[7:0] sum; output cout; input[7:0] ina,inb; input cin,clk;

reg[7:0] tempa,tempb,sum;

reg tempci,firstco,secondco,thirdco,cout;

reg[1:0] firsts,thirda,thirdb;

2

reg[3:0] seconda,secondb,seconds; reg[5:0] firsta,firstb,thirds; always @(posedge clk) begin

tempa=ina; tempb=inb; tempci=cin; //输入数据缓存 end

always @(posedge clk) begin

{firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci;

//第一级加(低2位) firsta=tempa[7:2]; //未参加计算的数据缓存 firstb=tempb[7:2]; end

always @(posedge clk) begin

{secondco,seconds}={firsta[1:0]+firstb[1:0]+firstco,firsts}; //第二级加(第2、3位相加) seconda=firsta[5:2]; //数据缓存 secondb=firstb[5:2]; end

always @(posedge clk) begin

{thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds}; //第三级加(第 4、5位相加) thirda=seconda[3:2]; //数据缓存 thirdb=secondb[3:2]; end

3

always @(posedge clk) begin

{cout,sum}={thirda[1:0]+thirdb[1:0]+thirdco,thirds}; //第四级加(高两位相加) end endmodule

3. 两个加法器和一个选择器的实现方式

module resource1(sum,a,b,c,d,sel); parameter size=4; output[size:0] sum;

input sel;

input[size-1:0] a,b,c,d; reg[size:0] sum;

always @(a or b or c or d or sel) begin

if(sel) sum=a+b; else sum=c+d; end endmodule

4. 两个选择器和一个加法器的实现方式

module resource2(sum,a,b,c,d,sel); parameter size=4; output[size-1:0] sum; input sel;

input[size-1:0] a,b,c,d; reg[size-1:0] atemp,btemp; reg[size:0] sum;

always @(a or b or c or d or sel)

4

begin

if(sel)begin atemp=a; btemp=b; end else begin atemp=c; btemp=d; end sum=atemp+btemp; end endmodule

5. 状态机设计的例子

module FSM(clk,clr,out,start,step2,step3); input clk,clr,start,step2,step3; output[2:0] out; reg[2:0] out;

reg[1:0] state,next_state;

parameter state0=2'b00,state1=2'b01, state2=2'b11,state3=2'b10;

/*状态编码,采用格雷(Gray)编码方式*/

always @(posedge clk or posedge clr) /*该进程定义起始状态*/ begin

if (clr) state <= state0; else state <= next_state;

end

always @(state or start or step2 or step3) /*该进程实现状态的转换*/ begin case (state) state0: begin

if (start) next_state <=state1; else next_state <=state0;

5

end state1: begin

next_state <= state2; end state2: begin

if (step2) next_state <=state3; else next_state <=state0; end state3: begin

if (step3) next_state <=state0; else next_state <=state3; end

default: next_state <=state0; /*default语句*/ endcase end

always @(state) /*该进程定义组合逻辑(FSM的输出)*/ begin case(state)

state0: out=3'b001; state1: out=3'b010; state2: out=3'b100; state3: out=3'b111;

default:out=3'b001; /*default语句,避免锁存器的产生*/

endcase end endmodule

6. 自动转换量程频率计控制器

6

/*信号定义:

clk: 输入时钟;

clear: 为整个频率计的异步复位信号; reset: 用来在量程转换开始时复位计数器; std_f_sel: 用来选择标准时基; cntover: 代表超量程; cntlow: 代表欠量程。

状态A,B,C,D,E,F采用一位热码编码 */ module control(std_f_sel,reset,clk,clear,cntover,cntlow); output[1:0] std_f_sel; output reset;

input clk,clear,cntover,cntlow; reg[1:0] std_f_sel; reg reset;

reg[5:0] present,next; //用于保存当前状态和次态的中间变量 parameter start_fl00k=6'b000001, //状态A编码,采用 1位热码 fl00k_cnt=6'b000010, //状态B start_fl0k=6'b000100, //状态 C fl0k_cnt=6'b001000, //状态 D start_flk=6'b010000, //状态E flk_cnt=6'b100000; //状态 F always @(posedge clk or posedge clear) begin

if(clear) present<=start_fl0k; //start_fl0k为起始状态

7

else present<=next; end

always @(present or cntover or cntlow) begin

case(present) //用case语句描述状态转换 start_fl00k: next<=fl00k_cnt; fl00k_cnt: begin

if(cntlow) next<=start_fl0k; else next<=fl00k_cnt; end

start_fl0k: next<=fl0k_cnt; fl0k_cnt: begin

if(cntlow) next<=start_flk; else if(cntover) next<=start_fl00k;

else next<=fl0k_cnt; end

start_flk: next<=flk_cnt; flk_cnt:

begin

if(cntover) next<=start_fl0k; else next<=flk_cnt; end

default:next<=start_fl0k; //缺省状态为起始状态 endcase end

8

always @(present) //该进程产生各状态下的输出 begin case(present)

start_fl00k: begin reset=1; std_f_sel=2'b00; end fl00k_cnt: begin reset=0; std_f_sel=2'b00; end start_fl0k: begin reset=1; std_f_sel=2'b01; end fl0k_cnt: begin reset=0; std_f_sel=2'b01; end start_flk: begin reset=1; std_f_sel=2'b11; end flk_cnt: begin reset=0; std_f_sel=2'b11; end default: begin reset=1; std_f_sel=2'b01; end endcase end endmodule

7. 8 位全加器

module add8(sum,cout,b,a,cin); output[7:0] sum; output cout; input[7:0] a,b; input cin;

assign {cout,sum}=a+b+cin; endmodule

8. 8 位寄存器

module reg8(qout,in,clk,clear); output[7:0] qout; input[7:0] in; input clk,clear;

reg[7:0] qout;

always @(posedge clk or posedge clear)

9

begin

if(clear) qout=0; //异步清 0 else qout=in; end endmodule

9. 累加器顶层连接文本描述

module acc(accout,cout,accin,cin,clk,clear); output[7:0] accout; output cout; input[7:0] accin; input cin,clk,clear; wire[7:0] sum;

add8 accadd8(sum,cout,accout,accin,cin); //调用 add8子模块 reg8 accreg8(accout,sum,clk,clear); //调用 reg8子模块 endmodule

10. 用`include 描述的累加器

`include “add8.v”; `include “reg8.v”;

module accn(accout,cout,accin,cin,clk,clear); output[7:0] accout; output cout; input[7:0] accin; input cin,clk,clear; wire[7:0] sum;

add8 accadd8(sum,cout,accout,accin,cin); //调用 add8子模块 reg8 accreg8(accout,sum,clk,clear); //调用 reg8子模块 endmodule

10

11. 阻塞赋值方式描述的移位寄存器 1

module block1(Q0,Q1,Q2,Q3,din,clk); output Q0,Q1,Q2,Q3; input clk,din;

reg Q0,Q1,Q2,Q3; always @(posedge clk) begin

Q3=Q2; //注意赋值语句的顺序 Q2=Q1; Q1=Q0; Q0=din; end endmodule

12. 阻塞赋值方式描述的移位寄存器2

module block2(Q0,Q1,Q2,Q3,din,clk); output Q0,Q1,Q2,Q3; input clk,din; reg Q0,Q1,Q2,Q3; always @(posedge clk) begin Q3=Q2;

Q1=Q0; //该句与下句的顺序与例 10.11颠倒 Q2=Q1; Q0=din; end endmodule

11

13. 阻塞赋值方式描述的移位寄存器3

module block3(Q0,Q1,Q2,Q3,din,clk); output Q0,Q1,Q2,Q3; input clk,din; reg Q0,Q1,Q2,Q3; always @(posedge clk) begin

Q0=din; //4条赋值语句的顺序与例 10.11完全颠倒 Q1=Q0; Q2=Q1; Q3=Q2; end endmodule

14. 非阻塞赋值方式描述的移位寄存器

module block4(Q0,Q1,Q2,Q3,din,clk); output Q0,Q1,Q2,Q3; input clk,din; reg Q0,Q1,Q2,Q3; always @(posedge clk) begin Q3<=Q2; Q1<=Q0; Q2<=Q1; Q0<=din; end endmodule

15. 长帧同步时钟的产生

module longframe1(clk,strb); parameter delay=8;

12

input clk; output strb; reg strb; reg[7:0] counter; always@(posedge clk) begin

if(counter==255) counter=0;

else counter=counter+1; end always@(counter) begin

if(counter<=(delay-1)) strb=1; else strb=0; end endmodule

16. 引入了D 触发器的长帧同步时钟的产生

module longframe2(clk,strb); parameter delay=8; input clk; output strb; reg[7:0] counter; reg temp; reg strb;

always@(posedge clk)

begin

if(counter==255) counter=0;

else counter=counter+1;

13

end

always@(posedge clk) begin

strb=temp; //引入一个触发器 end always@(counter) begin

if(counter<=(delay-1)) temp=1; else temp=0; end endmodule

17. 数字跑表

/*信号定义:

CLK: CLK为时钟信号; CLR: 为异步复位信号; PAUSE: 为暂停信号;

MSH,MSL: 百分秒的高位和低位; SH,SL: 秒信号的高位和低位; MH,ML: 分钟信号的高位和低位。 */

module paobiao(CLK,CLR,PAUSE,MSH,MSL,SH,SL,MH,ML); input CLK,CLR; input PAUSE;

output[3:0] MSH,MSL,SH,SL,MH,ML; reg[3:0] MSH,MSL,SH,SL,MH,ML;

reg cn1,cn2; //cn1为百分秒向秒的进位,cn2为秒向分的进位 //百分秒计数进程,每计满 100,cn1产生一个进位 always @(posedge CLK or posedge CLR)

14

begin

if(CLR) begin //异步复位 {MSH,MSL}<=8'h00; cn1<=0; end

else if(!PAUSE) //PAUSE为 0时正常计数,为 1时暂停计数 begin

if(MSL==9) begin MSL<=0; if(MSH==9)

begin MSH<=0; cn1<=1; else MSH<=MSH+1; end else begin

MSL<=MSL+1; cn1<=0; end end end

//秒计数进程,每计满 60,cn2产生一个进位 always @(posedge cn1 or posedge CLR) begin

if(CLR)begin //异步复位 {SH,SL}<=8'h00; cn2<=0; end

else if(SL==9) //低位是否为 9 begin SL<=0;

15

end if(SH==5) begin SH<=0; cn2<=1; end else SH<=SH+1; end else

begin SL<=SL+1; cn2<=0; end end

//分钟计数进程,每计满 60,系统自动清零 always @(posedge cn2 or posedge CLR) begin if(CLR)

begin {MH,ML}<=8'h00; end //异步复位 else if(ML==9) begin ML<=0;

if(MH==5) MH<=0; else MH<=MH+1; end else ML<=ML+1; end

endmodule

18. 4 位数字频率计控制模块

module fre_ctrl(clk,rst,count_en,count_clr,load); output count_en,count_clr,load; input clk,rst; reg count_en,load; always @(posedge clk) begin

if(rst)begin count_en=0; load=1; end

16

else begin

count_en=~count_en;

load=~count_en; //load信号的产生 end end

assign count_clr=~clk&load; //count_clr信号的产生 endmodule

19. 4 位数字频率计计数子模块

module count10(out,cout,en,clr,clk); output[3:0] out; output cout; input en,clr,clk; reg[3:0] out;

always @(posedge clk or posedge clr) begin

if (clr) out = 0; //异步清 0 else if(en) begin

if(out==9) out=0; else out = out+1; end end

assign cout =((out==9)&en)?1:0; //产生进位信号 endmodule

20. 频率计锁存器模块

module latch_16(qo,din,load); output[15:0] qo;

17

input[15:0] din; input load; reg[15:0] qo;

always @(posedge load) begin qo=din; end endmodule

21. 交通灯控制器

/* 信号定义与说明: CLK: 为同步时钟;

EN: 使能信号,为 1的话,则控制器开始工作;

LAMPA: 控制A 方向四盏灯的亮灭;其中,LAMPA0~LAMPA3,分别控制A 方向的 左拐灯、绿灯、黄灯和红灯;

LAMPB: 控制 B方向四盏灯的亮灭;其中,LAMPB0 ~ LAMPB3,分别控制B方向的 左拐灯、绿灯、黄灯和红灯;

ACOUNT:用于A 方向灯的时间显示,8位,可驱动两个数码管; BCOUNT:用于B方向灯的时间显示,8位,可驱动两个数码管。 */ module traffic(CLK,EN,LAMPA,LAMPB,ACOUNT,BCOUNT); output[7:0] ACOUNT,BCOUNT; output[3:0] LAMPA,LAMPB; input CLK,EN; reg[7:0] numa,numb; reg tempa,tempb; reg[2:0] counta,countb;

reg[7:0] ared,ayellow,agreen,aleft,bred,byellow,bgreen,bleft; reg[3:0] LAMPA,LAMPB; always @(EN) if(!EN)

18

begin //设置各种灯的计数器的预置数 ared <=8'd55; //55秒 ayellow <=8'd5; //5秒 agreen <=8'd40; //40秒 aleft <=8'd15; //15秒 bred <=8'd65; //65秒 byellow <=8'd5; //5秒 bleft <=8'd15; //15秒 bgreen <=8'd30; //30秒 end

assign ACOUNT=numa; assign BCOUNT=numb;

always @(posedge CLK) //该进程控制A 方向的四种灯 begin if(EN) begin

if(!tempa) begin tempa<=1;

case(counta) //控制亮灯的顺序

0: begin numa<=agreen; LAMPA<=2; counta<=1; end 1: begin numa<=ayellow; LAMPA<=4; counta<=2; end 2: begin numa<=aleft; LAMPA<=1; counta<=3; end 3: begin numa<=ayellow; LAMPA<=4; counta<=4; end 4: begin numa<=ared; LAMPA<=8; counta<=0; end

19

default: LAMPA<=8; endcase end

else begin //倒计时 if(numa>1)

if(numa[3:0]==0)begin

numa[3:0]<=4'b1001; numa[7:4]<=numa[7:4]-1; end

else numa[3:0]<=numa[3:0]-1; if (numa==2) tempa<=0; end end

else begin

LAMPA<=4'b1000;

counta<=0; tempa<=0; end end

always @(posedge CLK) //该进程控制 B方向的四种灯 begin if (EN) begin if(!tempb) begin tempb<=1;

case (countb) //控制亮灯的顺序

0: begin numb<=bred; LAMPB<=8; countb<=1; end 1: begin numb<=bgreen; LAMPB<=2; countb<=2; end

20

2: begin numb<=byellow; LAMPB<=4; countb<=3; end 3: begin numb<=bleft; LAMPB<=1; countb<=4; end 4: begin numb<=byellow; LAMPB<=4; countb<=0; end default: LAMPB<=8; endcase end else

begin //倒计时 if(numb>1)

if(!numb[3:0]) begin numb[3:0]<=9;

numb[7:4]<=numb[7:4]-1; end

else numb[3:0]<=numb[3:0]-1; if(numb==2) tempb<=0; end end

else begin

LAMPB<=4'b1000; tempb<=0; countb<=0; end end endmodule

22. “梁祝”乐曲演奏电路

//信号定义与说明:

//clk_4Hz: 用于控制音长(节拍)的时钟频率; //clk_6MHz:用于产生各种音阶频率的基准频率;

//speaker: 用于激励扬声器的输出信号,本例中为方波信号;

21

//high, med, low:分别用于显示高音、中音和低音音符,各驱动一个数码管来显示。 module song(clk_6MHz,clk_4Hz,speaker,high,med,low); input clk_6MHz, clk_4Hz; output speaker;

output[3:0] high,med,low;

reg[3:0] high,med,low; reg[13:0] divider,origin; reg[7:0] counter; reg speaker; wire carry;

assign carry=(divider==16383); always @(posedge clk_6MHz)

begin if(carry) divider=origin; else divider=divider+1; end

always @(posedge carry) begin

speaker=~speaker; end

always @(posedge clk_4Hz) begin

case({high,med,low}) 'b000000000011: origin=7281; 'b000000000101: origin=8730; 'b000000000110: origin=9565; 'b000000000111: origin=10310; 'b000000010000: origin=107;

22

//2分频产生方波信号 //分频比预置 'b000000100000: origin=11272; 'b000000110000: origin=11831; 'b000001010000: origin=12556; 'b000001100000: origin=12974; 'b000100000000: origin=13516; 'b000000000000: origin=16383; endcase end

always @(posedge clk_4Hz) begin

if(counter==63) counter=0; else counter=counter+1; case(counter)

0: {high,med,low}='b000000000011; 1: {high,med,low}='b000000000011; 2: {high,med,low}='b000000000011; 3: {high,med,low}='b000000000011;

4: {high,med,low}='b000000000101; 5: {high,med,low}='b000000000101; 6: {high,med,low}='b000000000101;

7: {high,med,low}='b000000000110; 8: {high,med,low}='b000000010000; 9: {high,med,low}='b000000010000; 10: {high,med,low}='b000000010000;

11: {high,med,low}='b000000100000; 23

//计时,以实现循环演奏 //记谱 //低音“3” //持续 4个时钟节拍 //低音“5” //发 3个时钟节拍 //低音“6” //中音“1” //发 3个时钟节拍 //中音“2”

12: {high,med,low}='b000000000110; //低音“6” 13: {high,med,low}='b000000010000; 14: {high,med,low}='b000000000101; 15: {high,med,low}='b000000000101;

16: {high,med,low}='b000001010000; //中音“5” 17: {high,med,low}='b000001010000; //发 3个时钟节拍 18: {high,med,low}='b000001010000; 19: {high,med,low}='b000100000000; 20: {high,med,low}='b000001100000; 21: {high,med,low}='b000001010000; 22: {high,med,low}='b000000110000; 23: {high,med,low}='b000001010000; 24: {high,med,low}='b000000100000; 25: {high,med,low}='b000000100000; 26: {high,med,low}='b000000100000; 27: {high,med,low}='b000000100000; 28: {high,med,low}='b000000100000; 29: {high,med,low}='b000000100000; 30: {high,med,low}='b000000100000; 31: {high,med,low}='b000000100000; 32: {high,med,low}='b000000100000; 33: {high,med,low}='b000000100000; 34: {high,med,low}='b000000100000; 35: {high,med,low}='b000000110000; 36: {high,med,low}='b000000000111; 37: {high,med,low}='b000000000111;

24

//高音“1” //中音“2”

//持续 11个时钟节拍//中音“3” //低音“7”

38: {high,med,low}='b000000000110; //低音“6” 39: {high,med,low}='b000000000110;

40: {high,med,low}='b000000000101; //低音“5” 41: {high,med,low}='b000000000101; 42: {high,med,low}='b000000000101;

43: {high,med,low}='b000000000110; //低音“6” 44: {high,med,low}='b000000010000; 45: {high,med,low}='b000000010000;

46: {high,med,low}='b000000100000; 47: {high,med,low}='b000000100000;

48: {high,med,low}='b000000000011; 49: {high,med,low}='b000000000011;

50: {high,med,low}='b000000010000; 51: {high,med,low}='b000000010000; 52: {high,med,low}='b000000000110;

53: {high,med,low}='b000000000101; : {high,med,low}='b000000000110;

55: {high,med,low}='b000000010000; 56: {high,med,low}='b000000000101; 57: {high,med,low}='b000000000101; 钟节拍

58: {high,med,low}='b000000000101; 59: {high,med,low}='b000000000101; 60: {high,med,low}='b000000000101; 61: {high,med,low}='b000000000101; 62: {high,med,low}='b000000000101; 63: {high,med,low}='b000000000101;

25

//中音“1” //中音“2” //低音“3” //中音“1” //低音“5” //中音“1” //低音“5” //持续 8个时 endcase end endmodule

23. 自动售饮料机

/*信号定义:

clk: 时钟输入; reset: 为系统复位信号; half_dollar: 代表投入 5角硬币; one_dollar: 代表投入 1元硬币; half_out: 表示找零信号;

dispense: 表示机器售出一瓶饮料;

collect: 该信号用于提示投币者取走饮料。 */ module sell(one_dollar,half_dollar,

collect,half_out,dispense,reset,clk); parameter idle=0,one=2,half=1,two=3,three=4;

//idle,one,half,two,three为中间状态变量,代表投入币值的几种情况 input one_dollar,half_dollar,reset,clk; output collect,half_out,dispense; reg collect,half_out,dispense; reg[2:0] D;

always @(posedge clk) begin

if(reset) begin

dispense=0; collect=0; half_out=0; D=idle; end

26

case(D) idle:

if(half_dollar) D=half; else if(one_dollar) D=one; half:

if(half_dollar) D=one; else if(one_dollar) D=two; one:

if(half_dollar) D=two; else if(one_dollar) D=three; two:

if(half_dollar) D=three; else if(one_dollar) begin

dispense=1; //售出饮料 collect=1; D=idle; end three:

if(half_dollar) begin

dispense=1; //售出饮料

collect=1; D=idle; end

else if(one_dollar) begin

27

dispense=1; //售出饮料 collect=1; half_out=1; D=idle; end endcase end endmodule

28

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo3.com 版权所有 蜀ICP备2023022190号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务