此文章是vip文章,如何查看?  

1,点击链接获取密钥 http://nicethemes.cn/product/view29882.html

2,在下方输入文章查看密钥即可立即查看当前vip文章


用计数器设计12小时时钟

  • 时间:
  • 浏览:
  • 来源:互联网

计数器设计12小时时钟

  • 题目
  • 代码

题目

Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).

reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.

The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.

在这里插入图片描述
这个题目的几个要求:

	能够进行12小时计数,那就要求有秒,分钟,小时;
	使用BCD计数器来实现;
	复位有效时,复位到12点;
	要能够区分上下午,上午pm为0,下午pm为1;
	复位比使能优先级更高;
	由于是时钟,所以是从1点到12点;

代码

题目中的时钟周期已经给出是1s,因此可直接用于计数。
不妨先设计出模60的BCD计数器和模12的BCD计数器。

模60的BCD计数器代码如下:

module counter_60 (
	input clk,
    input en,
    input reset,
    output reg[7:0] cout_out
);
    
    always @(posedge clk) begin
        if(reset)
            cout_out <= 0;
        else if(en) begin
            if (cout_out == 8'h59)
                cout_out <= 0;
            else begin
                if(cout_out[3:0] == 9) begin                
                    cout_out[3:0] <= 0;
                    cout_out[7:4] <= cout_out[7:4] + 1;
            	end
            	else 
                    cout_out[3:0] <= cout_out[3:0] + 1;                
            end  
        end
    end 
endmodule

模12的BCD计数器代码如下:

module counter_12 (
	input clk,
    input en,
    input reset,
    output reg[7:0] cout_out
);
    
    always @(posedge clk) begin
        if(reset)
            cout_out <= 8'h12;
        else if(en) begin
            if (cout_out == 8'h12)
                cout_out <= 1;
            else begin
                if(cout_out[3:0] == 9) begin               
                    cout_out[3:0] <= 0;
                    cout_out[7:4] <= cout_out[7:4] + 1;
            	end
            	else 
                    cout_out[3:0] <= cout_out[3:0] + 1;                
            end  
        end
    end 
endmodule

最后是顶层模块:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
        
    counter_12 counter1(
        .clk(clk),
        .reset(reset),
        .en(ena&(ss == 8'h59)&(mm == 8'h59)),
        .cout_out(hh)
    );
    
    counter_60 counter2(
        .clk(clk),
        .reset(reset),
        .en(ena&(ss == 8'h59)),
        .cout_out(mm)
    );
    
	counter_60 counter3(
        .clk(clk),
        .reset(reset),
        .en(ena),
        .cout_out(ss)
    );
    
    always@(posedge clk) begin
        if(reset) pm <= 0;
        else if(hh == 8'h11 && ss == 8'h59&& mm == 8'h59) pm <= ~pm;
        else ;
	end
endmodule

注意,顶层模块中,小时位,也就是counter1的计数使能en要设置为:

.en(ena&(ss == 8'h59)&(mm == 8'h59))

分钟位,也就是counter2的计数使能en要设置为:

.en(ena&(ss == 8'h59))

这段意思为:当秒数为59时,分钟位才能计数一次,分钟数为59时,小时位才能计数一次。

本文参考:HDLBits 系列(19) 12小时时钟的Verilog设计.

本文链接http://element-ui.cn/news/show-577026.aspx