Menu Close

复杂数字钟设计(3)—BCD码计数

在数字中的设计中BCD计数是核心部分,不仅要按照秒、分、时、天、月方式计数,还要考虑到计数的矫正(包括初始化矫正等)。因此本部分程序要与预定义按键的功能相结合。设计的思路如下:

  1. 采用自顶向下的设计方法
  2. 采用模块例化的方法,使代码可以重用。
  3. 子模块按功能方式例化传递不同的参数。

顶层代码如下:

module count
(
    input rst,
    input clk,
    input s_p,

    input sw_in_l,
    input sw_in_r,
    input sw_in_p,
    input sw_in_m,

    output [ 3: 0 ] s_out_l,
    output [ 3: 0 ] s_out_h,
    output [ 3: 0 ] m_out_l,
    output [ 3: 0 ] m_out_h,
    output [ 3: 0 ] h_out_l,
    output [ 3: 0 ] h_out_h,
    output [ 3: 0 ] d_out_l,
    output [ 3: 0 ] d_out_h,
    output [ 3: 0 ] mh_out_l,
    output [ 3: 0 ] mh_out_h,
    output reg [ 9: 0 ] dp_out_pos

);


wire m_p;
wire h_p;
wire d_p;
wire mh_p;

always@( posedge clk or posedge rst )
if ( rst )
begin
    dp_out_pos <= 10'b1;
end
else
begin
    if ( dp_out_pos == 0 )
        dp_out_pos <= 10'b1;

    if ( sw_in_l )
        if ( !dp_out_pos[ 9 ] )
        begin
            dp_out_pos <= { dp_out_pos[ 8: 0 ], dp_out_pos[ 9] };
        end

    if ( sw_in_r )
        if ( !dp_out_pos[ 0 ] )
        begin
            dp_out_pos <= { dp_out_pos[ 0 ], dp_out_pos[ 9: 1 ] };
        end

end



counter
#(
    .RADIX1( 9 ),
    .RADIX2( 5 ),
    .RADIX3( 0 )
)
counter_second
(
    .rst ( rst ),
    .clk ( clk ),
    .dp_in_pos( dp_out_pos[ 1: 0 ] ),
    .sw_in_p ( sw_in_p ),
    .sw_in_m ( sw_in_m ),
    .x_in_p ( s_p ),
    .x_out_l ( s_out_l ),
    .x_out_h ( s_out_h ),
    .x_out_p ( m_p )


);



counter
#(
    .RADIX1( 9 ),
    .RADIX2( 5 ),
    .RADIX3( 0 )
)
counter_minute
(
    .rst ( rst ),
    .clk ( clk ),
    .dp_in_pos( dp_out_pos[ 3: 2 ] ),
    .sw_in_p ( sw_in_p ),
    .sw_in_m ( sw_in_m ),
    .x_in_p ( m_p ),
    .x_out_l ( m_out_l ),
    .x_out_h ( m_out_h ),
    .x_out_p ( h_p )

);


counter
#(
    .RADIX1( 3 ),
    .RADIX2( 2 ),
    .RADIX3( 3 )
)
counter_hour
(
    .rst ( rst ),
    .clk ( clk ),
    .dp_in_pos ( dp_out_pos[ 5: 4 ] ),
    .sw_in_p ( sw_in_p ),
    .sw_in_m ( sw_in_m ),
    .x_in_p ( h_p ),
    .x_out_l ( h_out_l ),
    .x_out_h ( h_out_h ),
    .x_out_p ( d_p )

);

counter
#(
    .RADIX1( 1 ),
    .RADIX2( 3 ),
    .RADIX3( 2 )
)
counter_day
(
    .rst ( rst ),
    .clk ( clk ),
    .dp_in_pos ( dp_out_pos[ 7: 6 ] ),
    .sw_in_p ( sw_in_p ),
    .sw_in_m ( sw_in_m ),
    .x_in_p ( d_p ),
    .x_out_l ( d_out_l ),
    .x_out_h ( d_out_h ),
    .x_out_p ( mh_p )

);


counter
#(
    .RADIX1( 2 ),
    .RADIX2( 1 ),
    .RADIX3( 1 )
)
counter_month
(
    .rst ( rst ),
    .clk ( clk ),
    .dp_in_pos( dp_out_pos[ 9: 8 ] ),
    .sw_in_p ( sw_in_p ),
    .sw_in_m ( sw_in_m ),
    .x_in_p ( mh_p ),
    .x_out_l ( mh_out_l ),
    .x_out_h ( mh_out_h ),
    .x_out_p ()

);

endmodule

 

 

两位BCD码计数器:

module counter
#(
    parameter RADIX1 = 9,   
    parameter RADIX2 = 5,   
    parameter RADIX3 = 0     // 0 => second or minute;  1 => month; 2 => day ; 3 => hour.
)
(
    input rst,
    input clk,
    input [ 1: 0 ] dp_in_pos,   // position
    input sw_in_p,              // button ++
    input sw_in_m,              // button -- 
    input x_in_p,               // x input pulse enable  carry_in

    output reg[ 3: 0 ] x_out_l,
    output reg[ 3: 0 ] x_out_h,
    output reg[ 3: 0 ] month,
    output reg x_out_p          // carry out
);




always@( posedge clk or posedge rst )
if ( rst )
begin
    x_out_l <= (RADIX3 == 2 || RADIX3 == 1 ) ? 1 : 0;

    x_out_h <= 0;
    x_out_p <= 1'b0;
    month <= 1;
end
else
begin
    x_out_p <= 1'b0;

    if ( sw_in_p )  // button ++
    begin
        if ( dp_in_pos[ 0 ] )
        begin
//            if ( x_out_l == RADIX1 ) x_out_l <= 0;
            if ( x_out_l == 9 ) x_out_l <= 0;
            else                     x_out_l <= x_out_l + 1;
        end
        else if ( dp_in_pos[ 1 ] )
        begin
//            if ( x_out_h == RADIX2 ) x_out_h <= 0;
            if ( x_out_h == 9 ) x_out_h <= 0;
            else                     x_out_h <= x_out_h + 1;
        end
    end

    if ( sw_in_m ) // button --
    begin
        if ( dp_in_pos[ 0 ] )
        begin
//            if ( x_out_l == 0 ) x_out_l <= RADIX1;
            if ( x_out_l == 0 ) x_out_l <= 9;
            else                x_out_l <= x_out_l - 1;
        end
        else if ( dp_in_pos[ 1 ] )
        begin
//            if ( x_out_h == 0 ) x_out_h <= RADIX2;
            if ( x_out_h == 0 ) x_out_h <= 9;
            else                x_out_h <= x_out_h - 1;
        end
    end

    if ( x_in_p )
    begin
        if ( RADIX3 == 0 )
        begin
            if ( x_out_l == RADIX1 )
            begin
                x_out_l <= 0;

                if ( x_out_h == RADIX2 )
                begin
                    x_out_h <= 0;
                    x_out_p <= 1'b1;
                end
                else
                    x_out_h <= x_out_h + 1;
            end
            else
                x_out_l <= x_out_l + 1;
        end
        else if (( RADIX3 == 1 )||( RADIX3 == 3 ))
        begin
            if ( ( x_out_l == RADIX1 ) && ( x_out_h == RADIX2 ) )
            begin
                x_out_l <= (RADIX3 == 1) ? 1'b1 : 1'b0;
                x_out_h <= 0;
                x_out_p <= 1'b1;
            end
            else if ( x_out_l == 9 )
            begin
                x_out_l <= 0;
                x_out_h <= x_out_h + 1;
            end
            else
                x_out_l <= x_out_l + 1;
        end
        else if ( RADIX3 == 2 )
        begin
            case ( month )
                1, 3, 5, 7, 8, 10, 12:
                begin
                    if ( ( x_out_l == 1 ) && ( x_out_h == 3 ) )
                    begin
                        x_out_l <= 1;
                        x_out_h <= 0;
                        x_out_p <= 1'b1;
                        month <= month + 1;
                    end
                    else
                    begin
                        if ( x_out_l == 9 )
                        begin
                            x_out_l <= 0;
                            x_out_h <= x_out_h + 1;
                        end
                        else
                            x_out_l <= x_out_l + 1;

                    end
                end

                2:// possibly developed for leap year adjustment
                begin
                    if ( ( x_out_l == 8 ) && ( x_out_h == 2 ) )
                    begin
                        x_out_l <= 1;
                        x_out_h <= 0;
                        x_out_p <= 1'b1;
                        month <= month + 1;
                    end
                    else
                    begin
                        if ( x_out_l == 9 )
                        begin
                            x_out_l <= 0;
                            x_out_h <= x_out_h + 1;
                        end
                        else
                            x_out_l <= x_out_l + 1;

                    end
                end

                4, 6, 9, 11:
                begin
                    if ( ( x_out_l == 0 ) && ( x_out_h == 3 ) )
                    begin
                        x_out_l <= 1;
                        x_out_h <= 0;
                        x_out_p <= 1'b1;
                        month <= month + 1;
                    end
                    else
                    begin
                        if ( x_out_l == 9 )
                        begin
                            x_out_l <= 0;
                            x_out_h <= x_out_h + 1;
                        end
                        else
                            x_out_l <= x_out_l + 1;

                    end
                end

                default:
                    month <= 1;

            endcase
        end

    end
end



endmodule

 

 

在本系统程序设计时采用信号或输入、输出端口的命名方法如下:

(1)对变量的定义一般采用多个能体现变量含义的单词或缩写,中间采用下划线”_”级联,如:sw_in_l(按键-输入-左),sw_in_r(按键-输入-右)。

(2)对接口设计的输入端一般都采用“in”指示信号的方向为输入。如:sw_in_r。

(3)对接口的输出端一般都采用“out”指示信号的方向为输出。 如:sw_out_r。

(4)对于模块之间的级联的变量,设为中性,即不带“in”或“out”标志。如:h_p。

 

Posted in FPGA, FPGA, Quartus II, Verilog, Verilog, Vivado, 开发语言, 教材与教案, 文章

发表评论

相关链接