文章目录

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



一、 看门狗简介

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


二、看门狗分类

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


三、看门狗模块设计

3.1 看门狗模块设计框图

微服务 看门狗 verilog 看门狗_fpga开发

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

结束

微服务 看门狗 verilog 看门狗_fpga开发_02