使用Verilog设计硬件看门狗

文章目录

  • 一、 看门狗简介
  • 二、看门狗分类
  • 三、看门狗模块设计
  • 3.1 看门狗模块设计框图
  • 3.2 顶层
  • 3.3 计数器
  • 3.4 边沿检测器
  • 3.5 信号延迟模块

  • 一、 看门狗简介

      看门狗:也称看门狗定时器,是常见于系统的一种外设;
    看门狗似乎就是一条看门的狗,如果系统一切正常则看门狗不叫,如果程序不正常,则看门狗则会将程序咬死(即程序强制复位)。
      看门狗的作用:当一段程序跑飞,卡死或不受控制时,能使得系统强制重启;
      喂狗:当看门狗被初始化后,需要在程序中每进行一段时间就重置看门狗模块的定时器计数值,防止程序被咬死;
      程序咬死:当程序出现问题时(跑飞或锁死),导致看门狗定时器的计数值没能及时重置,当计数值达到设置的阈值后,看门狗定时器则输出复位信号,使得CPU强制复位;


    二、看门狗分类

      硬件看门狗:看门狗实际上就是一个计数器,硬件看门狗就是以硬件实现的一种计数器,其可以集成在单片机,SOC等系统中,使用硬件看门狗不用消耗额外的软件资源;
      软件看门狗:利用软件实现软件计数器,利用该计数器判断是否计数达到阈值,达到阈值则调用软件复位程序,常与定时器中断一起使用;
      窗口看门狗:独立看门狗在0-重载值之间都可以进行喂狗操作,这样如果程序跑飞反复在喂狗,则程序无法复位;窗口看门狗则对喂狗的时间设置了阈值(上下限),喂狗操作只能在阈值间进行喂狗,其他时间喂狗都无效;


    三、看门狗模块设计

    3.1 看门狗模块设计框图

    3.2 顶层

    module wtd_counter_top#(
        parameter integer   COUNTER_WIDTH = 16,
        parameter integer   RST_SIG_WIDTH = 2
        )(
            input  wire                            ref_clk,//system reference clock
            input  wire                               nrst,//system reset signal, Valid: 1'b0
            input  wire                                 en,//system enable signal, Valid: 1'b1
            input  wire [COUNTER_WIDTH - 1:0] up_threshold,//system upside threshold
            output wire [COUNTER_WIDTH - 1:0]        count,//system clock counter
            output wire                            wtd_rst 
        );
    
       wire                    rst_req;
       wire [RST_SIG_WIDTH :0] rst_req_dff; 
    
       assign rst_req  = (count == up_threshold) ? 1'b1:1'b0;
       assign wtd_rst = |rst_req_dff;
    
       genvar DFF_inist_index;
       generate 
            for(DFF_inist_index = 0;
                DFF_inist_index < RST_SIG_WIDTH;
                DFF_inist_index = DFF_inist_index +1)
             begin: dff_cell_inist//
                dff#(.DFF_LEVEL(1),.DATA_WIDTH(1)
                )dff_inist(
                    .clk(ref_clk),
                    .din(rst_req_dff[DFF_inist_index]),
                    .dout(rst_req_dff[DFF_inist_index+1]),
                    .nrst(nrst)
                );
             end
        endgenerate
    
        edge_check edge_check_inist0(
            .ref_clk(ref_clk),
            .nrst(nrst),
            .din(rst_req),
            .dout(rst_req_dff[0])
        );
         wtd_counter#(
            .COUNTER_WIDTH(COUNTER_WIDTH)
        )wtd_counter_inist0(
            .ref_clk(ref_clk),//system reference clock
            .nrst(nrst),//system reset signal, Valid: 1'b0
            .en(en),//system enable signal, Valid: 1'b1
            .up_threshold(up_threshold),//system upside threshold
            .count(count) //system clock counter 
        );
    endmodule
    

    3.3 计数器

    module wtd_counter#(
            parameter integer   COUNTER_WIDTH = 16
        )(
            input  wire                            ref_clk,//system reference clock
            input  wire                               nrst,//system reset signal, Valid: 1'b0
            input  wire                                 en,//system enable signal, Valid: 1'b1
            input  wire [COUNTER_WIDTH - 1:0] up_threshold,//system upside threshold
            output wire [COUNTER_WIDTH - 1:0]        count //system clock counter 
        );
    
        /**************************wtd inner signal design**************************/
        reg  [COUNTER_WIDTH - 1:0]      count_r;
    
        /**************************wtd inner signal connect**************************/
        assign   count = count_r;
    
        always @(posedge ref_clk) begin : proc_
            if(~nrst) begin
                count_r <= 'b0;
            end else begin
                if(en)
                begin
                    if(count_r != up_threshold)
                        count_r <= count_r + 1'b1;
                    else
                        count_r <= count_r;
                end
                else
                begin
                    count_r <= count_r;
                end
            end
        end
    
    endmodule
    

    3.4 边沿检测器

    module edge_check(
            input  wire    ref_clk,
            input  wire       nrst,
            input  wire        din,
            output wire       dout
        );
    
        reg  din_dff;
    
        assign dout = (din) & (~din_dff);
    
        always @(posedge ref_clk ) begin
            if(~nrst) begin
                din_dff <= 0;
            end 
            else begin
                din_dff <= din;
            end
        end
    
    endmodule
    

    3.5 信号延迟模块

    module dff#(
            parameter integer DFF_LEVEL  = 1,
            parameter integer DATA_WIDTH = 8
    )(
            input wire                     clk,
            input wire [DATA_WIDTH - 1:0]  din,
            input wire [DATA_WIDTH - 1:0] dout,
            input wire                    nrst
        );
    
        reg [DATA_WIDTH - 1:0] din_buff [DFF_LEVEL-1:0];
        assign dout = din_buff[DFF_LEVEL-1];
        integer i;
    
        always @(posedge clk or negedge nrst) begin
            if (~nrst) begin
                // reset
                for(i=0;i<DFF_LEVEL;i=i+1)
                begin
                    din_buff[i] <= 'b0;
                end
            end
            else begin
                for(i=1;i<DFF_LEVEL;i=i+1)
                begin
                    din_buff[i] <= din_buff[i-1];
                end
                    din_buff[0] <= din;
            end
        end
        
    endmodule
    

    结束

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用Verilog设计硬件看门狗

    发表评论