chenming1989 发表于 2011-7-25 21:08:26

想了一天了,还是有点想不通这和问题,新手求指点(FPGA实现的数字时钟)

module clock(clk,key_in,sm_bit,led0,sm_seg); //模块名clock
input 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取反一次嘛
纠结一天了,望明白者指点一下,万分感激!!!!!!

chenming1989 发表于 2011-7-25 21:11:36

补充一下:按键按下为下降沿!

chenming1989 发表于 2011-7-26 08:39:10

悲催了哈,原来是我的引脚分配反了啊..........就说吗,分析的因该没问题的啊。。。。

chenming1989 发表于 2011-7-26 08:43:01

还是希望有人能解释一下2和3两点,这懂了这个时钟才算是彻底的弄明白了。。不胜感激!此贴一回我的积分就100啦,哈哈。。。。向4位数进军!!!!!!

philoman 发表于 2011-7-27 17:59:29

不同verilog,帮丁下;第3点,在always里面取反,与直接取反是不同的,直接取反是组合逻辑,输出与输入之间存在一个很小的时延,而always语句里面取反,是时许逻辑,也就是说,这个取反的动作是跟着时钟的节拍的,输出与输入间的延时为一个时钟周期;
页: [1]
查看完整版本: 想了一天了,还是有点想不通这和问题,新手求指点(FPGA实现的数字时钟)