想了一天了,还是有点想不通这和问题,新手求指点(FPGA实现的数字时钟)
module clock(clk,key_in,sm_bit,led0,sm_seg); //模块名clockinput clk; //输入时钟
input key_in; //输入按键
output sm_bit; //数码管选择输出引脚
output sm_seg; //数码管段输出引脚
outputled0;
assignled0 = 1'b0;
reg sm_seg_r; //定义数码管输出寄存器
reg sm_bit_r; //定义数码管选择输出寄存器
reg disp_dat; //定义显示数据寄存器
regcount; //定义计数寄存器
reghour; //定义现在时刻寄存器
reg sec,keyen; //定义标志位
regdout1,dout2,dout3; //寄存器
wirekey_done; //按键消抖输出
assign sm_bit = sm_bit_r; //输出数码管选择
assign sm_seg = sm_seg_r; //输出数码管译码结果
//秒信号产生部分
always @(posedge clk) //定义clock上升沿触发
begin
count = count + 1'b1;
if(count == 25'd25000000) //0.5S到了吗?
begin
count = 25'd0; //计数器清零
sec = ~sec; //置位秒标志
end
end
//按键消抖处理部分
assign key_done = (dout1 | dout2 | dout3);//按键消抖输出
always @(posedge count)
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
always @(negedge key_done)
begin
keyen = ~keyen; //将琴键开关转换为乒乓开关
end
//数码管动态扫描显示部分
always @(posedge clk) //count大约1ms改变一次
begin
case(count) //选择扫描显示数据
3'd0:disp_dat = hour; //秒个位
3'd1:disp_dat = hour; //秒十位
3'd2:disp_dat = 4'ha; //显示"-"
3'd3:disp_dat = hour; //分个位
3'd4:disp_dat = hour; //分十位
3'd5:disp_dat = 4'ha; //显示"-"
3'd6:disp_dat = hour; //时个位
3'd7:disp_dat = hour; //时十位
endcase
case(count) //选择数码管显示位
3'd0:sm_bit_r = 8'b11111110; //选择第一个数码管显示
3'd1:sm_bit_r = 8'b11111101; //选择第二个数码管显示
3'd2:sm_bit_r = 8'b11111011; //选择第三个数码管显示
3'd3:sm_bit_r = 8'b11110111; //选择第四个数码管显示
3'd4:sm_bit_r = 8'b11101111; //选择第五个数码管显示
3'd5:sm_bit_r = 8'b11011111; //选择第六个数码管显示
3'd6:sm_bit_r = 8'b10111111; //选择第七个数码管显示
3'd7:sm_bit_r = 8'b01111111; //选择第八个数码管显示
endcase
end
always @(posedge clk)
begin
case(disp_dat)
4'h0:sm_seg_r = 8'hc0; //显示0
4'h1:sm_seg_r = 8'hf9; //显示1
4'h2:sm_seg_r = 8'ha4; //显示2
4'h3:sm_seg_r = 8'hb0; //显示3
4'h4:sm_seg_r = 8'h99; //显示4
4'h5:sm_seg_r = 8'h92; //显示5
4'h6:sm_seg_r = 8'h82; //显示6
4'h7:sm_seg_r = 8'hf8; //显示7
4'h8:sm_seg_r = 8'h80; //显示8
4'h9:sm_seg_r = 8'h90; //显示9
4'ha:sm_seg_r = 8'hbf; //显示-
default:sm_seg_r = 8'hff; //不显示
endcase
if((count== 3'd2)&sec)
sm_seg_r = 8'hff;
end
//计时处理部分
always @(negedge sec or negedge key_done)//计时处理
begin
if(!key_done) //是清零键吗?
begin
hour = 24'h0; //是,则清零
end
else if(!keyen)
begin
hour = hour + 1'b1; //秒加1
if(hour == 4'ha)
begin
hour = 4'h0;
hour = hour + 1'b1; //秒的十位加一
if(hour == 4'h6)
begin
hour = 4'h0;
hour = hour + 1'b1;//分个位加一
if(hour == 4'ha)
begin
hour = 4'h0;
hour = hour + 1'b1;//分十位加一
if(hour == 4'h6)
begin
hour = 4'h0;
hour = hour + 1'b1;//时个位加一
if(hour == 4'ha)
begin
hour = 4'h0;
hour = hour + 1'b1;//时十位加一
end
if(hour == 8'h24)
hour = 8'h0;
end
end
end
end
end
end
endmodule
这个程序我大体上还是看懂了,可是具体的细节还是有点像不通。。。在板子上实现后key_done键是复位功能,key_done键为时钟停止键。希望在以下几点给解释一下。新手不胜感激!!!!!
1. if(!key_done) //是清零键吗?
begin
hour = 24'h0; //是,则清零
end
按理说一直按住key_done应该是时钟清零啊???
2. if((count== 3'd2)&sec)
sm_seg_r = 8'hff;
这句没看懂。。。。。
3.always @(negedge key_done)
begin
keyen = ~keyen; //将琴键开关转换为乒乓开关
end
将琴键开关转换为乒乓开关???不就是按下key_done键,keyen取反一次嘛
纠结一天了,望明白者指点一下,万分感激!!!!!! 补充一下:按键按下为下降沿! 悲催了哈,原来是我的引脚分配反了啊..........就说吗,分析的因该没问题的啊。。。。 还是希望有人能解释一下2和3两点,这懂了这个时钟才算是彻底的弄明白了。。不胜感激!此贴一回我的积分就100啦,哈哈。。。。向4位数进军!!!!!! 不同verilog,帮丁下;第3点,在always里面取反,与直接取反是不同的,直接取反是组合逻辑,输出与输入之间存在一个很小的时延,而always语句里面取反,是时许逻辑,也就是说,这个取反的动作是跟着时钟的节拍的,输出与输入间的延时为一个时钟周期;
页:
[1]