Verilog的定时器设计

Verilog的定时器设计,第1张

module mc(bo,h1,h0,s0,s1,m1,m0,clk,start,rst,sh,sm,ss,md)//ss,sm,sh设定时间,md控制按键加减

input clk,sh,sm,ss,start,md,rst

wire clks,clks0,clkm0,clkh0

reg clkm,clkh

reg[7:0] h,m,s

output[6:0] h1,h0,s0,s1,m1,m0

output reg bo

initial begin h=0m=1s=0end //陪册初始化定时器 \

fp m21(.clk_in(clk),.clk_out(clks))//分频模块

assign clks0=clks&&start||!ss||!rst//百分秒计时块

always@(posedge clks0 )

if(!rst) s<=0

else if(md) begin s<=s+1if(s==99)s<=0end

else if((h==0)&&(m==0)&&(s==0)) s<=0

else if(s==0) begin

s<=99clkm<=1end

else begin s<=s-1clkm<=0end

assign clkm0=clkm||!sm||!rst//秒计时块

always@(posedge clkm0 )

if(!rst) m<=0

else if(md)begin m<=m+1if(m==59)m<=0end

else if(m==0) begin m<=59clkh<=1end

else begin m<=m-1clkh<=0end

assign clkh0=clkh||!sh||!rst//早衡分计时块

always@(posedge clkh0 )

if(!rst) h<=0

else if(md)begin h<=h+1if(h==60)h<=0end

else if (h==0) h<=60

else h<=h-1

always@(h,s,m ) //定时终点报时块

if(h==0&&m==0&&s==0) begin bo=1end

else bo=0

m10led

m20(.h(h),.m(m),.s(s),.h1(h1),.h0(h0),.m1(m1),.m0(m0),.s0(s0),.s1(s1))//数码管显示块

endmodule

module fp(clk_in,clk_out)//将27MHz分频为1Hz

input clk_in

output reg clk_out

reg [31:0] q

initial q=0

always@(posedge clk_in)

if(q==13500000) begin clk_out<=1q<=q+1end

else if(q==27000000) begin clk_out<=0q<=0end

else q<=q+1

endmodule

module m10led(h,m,s,h1,h0,m1,m0,s0,s1)//时分秒的个位十位分离成两组十六进制数

input[7:0] h,m,s

wire [6:0] a0,a1,b0,b1,c0,c1

output[7:0] h1,h0,s0,s1,m1,m0

wire[7:0] seg0,seg1,seg2

assign a0=s%10,a1=s/10

assign {seg0[7:4],seg0[3:0]}={a1[3:0],a0[3:0]}//分离分

led m00(.SW(seg0),.HEX1(s1),.HEX0(s0))//调用子模块led

assign b0=m%10,b1=m/10

assign {seg1[7:4],seg1[3:0]}={b1[3:0],b0[3:0]}

led m01(.SW(seg1),.HEX1(m1),.HEX0(m0))//调用子模块led

assign c0=h%10,c1=h/10/陆乱做/分离时

assign {seg2[7:4],seg2[3:0]}={c1[3:0],c0[3:0]}

led m10(.SW(seg2),.HEX1(h1),.HEX0(h0))//调用子模块led

endmodule

module led(SW,HEX1,HEX0)//将两组十六进制数转码为数码管显示的数值

input [7:0]SW

output reg[6:0]HEX1,HEX0

parameter seg0= 7'b1000000,

seg1 = 7'b1111001,

seg2 = 7'b0100100,

seg3 = 7'b0110000,

seg4= 7'b0011001,

seg5 = 7'b0010010,

seg6 = 7'b0000010,

seg7 = 7'b1111000,

seg8 = 7'b0000000,

seg9 = 7'b0010000,

sega = 7'b0001000,

segb = 7'b0000011,

segc = 7'b1000110,

segd = 7'b0100001,

sege = 7'b0000110,

segf = 7'b0001110

always @(*)

case(SW[3:0]) //第一组十六进制转换

4'h0: HEX0[6:0] = seg0

4'h1: HEX0[6:0] = seg1

4'h2: HEX0[6:0] = seg2

4'h3: HEX0[6:0] = seg3

4'h4: HEX0[6:0] = seg4

4'h5: HEX0[6:0] = seg5

4'h6: HEX0[6:0] = seg6

4'h7: HEX0[6:0] = seg7

4'h8: HEX0[6:0] = seg8

4'h9: HEX0[6:0] = seg9

4'ha: HEX0[6:0] = sega

4'hb: HEX0[6:0] = segb

4'hc: HEX0[6:0] = segc

4'hd: HEX0[6:0] = segd

4'he: HEX0[6:0] = sege

4'hf: HEX0[6:0] = segf

default:HEX0[6:0] = seg0

endcase

always @(*)

case(SW[7:4])//第一组十六进制转换

4'h0: HEX1[6:0] = seg0

4'h1: HEX1[6:0] = seg1

4'h2: HEX1[6:0] = seg2

4'h3: HEX1[6:0] = seg3

4'h4: HEX1[6:0] = seg4

4'h5: HEX1[6:0] = seg5

4'h6: HEX1[6:0] = seg6

4'h7: HEX1[6:0] = seg7

4'h8: HEX1[6:0] = seg8

4'h9: HEX1[6:0] = seg9

4'ha: HEX1[6:0] = sega

4'hb: HEX1[6:0] = segb

4'hc: HEX1[6:0] = segc

4'hd: HEX1[6:0] = segd

4'he: HEX1[6:0] = sege

4'hf: HEX1[6:0] = segf

default:HEX1[6:0] = seg0

endcase

endmodule

module Timer_Design( 

input wire clk, //时钟信号输入端F = 1Hz P = 1s

input wire res,    //复位信号,Low Active低有效

input wire [1:0] data,   //定时模式[长短]选择

output  reg x       

)

/*******************************功能描述***************************

data = 2'b00 -> 无定时, 告警信号X一直为0

data = 2'b01 -> 5s定时, 告警信号X保持6s的高,但是5s就会输出一个

    告警,这个有一点冲突

data = 2'b10 -> 10s定时,每隔10s输出一个告警信号,告警信号保持6s

data = 2'b11 -> 15s定时,每隔15输出一个告警有效信号

******************************************************************/

//这里有一个不明确的地方,是否定时是一直在运行,如果一直在运行定时,那么第一个假设定时时间是5s

//5s到了之后告警信号拉高,此时定时清零继续运行,告警信号要保持6s的高,那么5s定时到的时候告警信

//号依旧是高,以此循环,5S定时的话X会一直保持高。

//另外一种情罩世况是定时一直在运行,但困闷游是X持续高时间需要低于定时周期5s

//第三种可能是定时不一直运行,定时到5s之后,X输出6s的高,此时定时是停止的,6s之后重新开始定时

//但是这个定时周期的定义就有问题了

//所以考虑以上情况,我选择第二种,将X持续时间缩短到3s

reg [3:0] timer_cnt

always @(posedge clk,negedge res) begin

if(!rss) begin

x <= 1'b0

timer_cnt <= 4'd0

end

else case(data)

2'b00 : begin

x <= 1'b0

timer_cnt <= 4'd0

end

2'b01 : begin //定时5s

if(timer_cnt <= 4'd1) begin

x <= x //刚开始定时的时候不能将之拉高,所以这里用保持

timer_cnt <= timer_cnt + 1'b1

end

else if(timer_cnt <= 4'd3) begin

timer_cnt <= timer_cnt + 1'b1

x <= 1'b0

end

else begin //timer_cnt = 4

timer_cnt  <= 4'd0

x <= 1'b1

end

end

2'b10 : begin //定时10

if(timer_cnt <= 4'd1) begin //x保持3s的高

x <= x  //刚开始定时的时候不能将之拉高,所以这里用保持

timer_cnt <= timer_cnt + 1'b1

end

else if(timer_cnt <= 4'd8) begin

timer_cnt <= 汪销timer_cnt + 1'b1

x <= 1'b0

end

else begin //timer_cnt = 9

timer_cnt  <= 4'd0

x <= 1'b1

end

end

2'b11 : begin //定时15

if(timer_cnt <= 4'd1) begin //x保持3s的高

x <= x  //刚开始定时的时候不能将之拉高,所以这里用保持

timer_cnt <= timer_cnt + 1'b1

end

else if(timer_cnt <= 4'd13) begin   //cnt = 2~(14-1)

timer_cnt <= timer_cnt + 1'b1

x <= 1'b0

end

else begin //timer_cnt = 14

timer_cnt  <= 4'd0

x <= 1'b1

end

end

            default :

endcase

end

endmodule

有问题可以补充。。。

首先PLL应用就不用说明了,这个直接调用内部软核来实现,没有涉及到代码。就分频代码我简单写个仿信8分频的代码,其他的大同小异。

module div_8(clk_100M,rst,clk_125M)

input clk_100M,rst

output reg clk_125M//8分频输出12.5M

reg[3:0] temp

always@(posedge clk_100M or negedge rst)

begin

if(!rst)

begin

temp<=4'b0000

clk_125M<=1'孙物b0

end

else if(temp==4'd3)

begin

clk_125M<=~clk_125M

temp<=4'b0000

end

else

temp<=temp+1'b1

end

endmodule

这个只是8分则大液频代码,其他的16分频可参考这个来写,原理是一样的。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12460084.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存