FPGA|CPLD|ASIC论坛
直播中

whyil

8年用户 37经验值
擅长:嵌入式技术 控制/MCU 嵌入式技术 控制/MCU
私信 关注
[问答]

FPGA三段式状态机里涉及到定时等待时如何处理?

  1. module auto_lock(

  2.                         input clk,                                //系统时钟
  3.                         input rst_n,                        //系统复位
  4.                         input lock_signal,        //失锁锁定输入
  5.                                                
  6.                         output reg analog_switch_1,        //模拟开关1输出
  7.                         output reg analog_switch_2,        //模拟开关2输出
  8.                         output reg [13:0] dac_ch1,                //温度dac
  9.                         output reg sawtooth_control,        //锯齿波控制
  10.                        
  11.                         input signed [15:0]adc_ch1_data,        //adc ch1电压值

  12. /*                        //按键输入
  13.                         input key1_in,
  14.                         input key2_in,
  15.                         input key3_in,
  16.                         input key4_in,
  17. */
  18.                         //系统状态指示
  19.                         output lock_status_led        //led
  20.                        
  21.                         //DEBUG数据
  22. //                        output [23:0]debug_state_value,
  23. //                        output [23:0]debug_pdh_ok_count_value
  24.     );
  25.          
  26.         parameter ON = 1'b1,OFF = 1'b0;
  27.         parameter LOCK = 1'b1,UNLOCK = 1'b0;
  28.         parameter START = 1'b1,END = 1'b0;
  29.        
  30.         parameter DIR_UP = 2'd0,DIR_DOWN = 2'd1,DIR_EXPAND_SCOPE = 2'd2;
  31.        
  32.         parameter DAC_TO_TEMPERATURE_INIT = 14'd8192;        //0

  33.          
  34.         parameter T10MS        = 32'd49_999_9;
  35.         parameter T100MS         = 32'd49_999_99;
  36.         parameter T1S                 = 32'd49_999_999;


  37. /*
  38.         parameter T10MS        = 32'd4;
  39.         parameter T100MS         = 32'd49;
  40.         parameter T1S                 = 32'd49_9;
  41. */               
  42.        
  43.         parameter T2S         = 8'd2;
  44.         parameter T5S         = 8'd5;       
  45.         parameter T10S = 8'd10;
  46.         parameter T20S = 8'd20;       
  47.        

  48. //        assign debug_pdh_ok_count_value = pdh_ok_count;
  49.        
  50.         /***********************锁定信号触发边沿检测*************************/
  51.         lock_signal_edge_check lock_signal_edge_check_model(

  52.                         .clk        (clk),                                //系统时钟
  53.                         .rst_n        (rst_n),                        //系统复位
  54.                
  55.                         .lock_signal(lock_signal),
  56.                         .locked        (locked),
  57.                         .pdh_ok        (pdh_ok),
  58.                         .lock_status_led        (lock_status_led)
  59.     );
  60.        
  61.         /***********************系统运行*************************/
  62.         parameter PDH_OK_COUNT_N = 8'd2;
  63.         parameter INIT_N = 14'd8;        // N 的初始范围
  64.         parameter K = 14'd2;        //K
  65.        
  66.        
  67.         //运行状态
  68.         parameter         INIT = 8'd0;                        //初始化
  69.         parameter        RUN_INIT_I = 8'd1;        //运行
  70.         parameter         START_PZT_SCANNING = 8'd2;        //开始锯齿波扫描
  71.         parameter         WAIT = 8'd3;
  72.         parameter         IF_PDH_OK = 8'd4;
  73.         parameter         SEARCH_PDH_OK = 8'd5;
  74.         parameter        LOCK_IN_PROCESS = 8'd6;
  75.         parameter        UNLOCK_IN = 8'd7;
  76.         parameter         UNLOCK_IN_RETRY = 8'd8;
  77.         parameter        LOCK_IN = 8'd9;
  78.        


  79.         reg[7:0] pdh_ok_count;
  80.         reg[18:0] pdh_time_count;//在锯齿波为1Hz延时为20ms 频率越高锁定时间越短
  81.         reg pdh_ok_delay_flag;                        //pdh延时标志
  82.         reg [7:0]locked_fail_count;        //锁定失败计数       
  83.        
  84.         reg [13:0]dac_to_temperature_i;                        //温度输出
  85.         reg [13:0]dac_to_temperature_top;                //上限
  86.         reg [13:0]dac_to_temperature_bottom;        //下限
  87.        

  88.         reg [13:0]N;       
  89.         reg [3:0]DIR;        //扫描方向
  90.        
  91.         //计时器
  92.         reg [25:0]time_count;
  93.         reg [7:0]time_ones;       


  94.         //三段式状态机
  95.         reg[7:0]cstate;        //当前状态
  96.         reg[7:0]nstate;        //下一个状态

  97.         //第一部分说明初始状态,和current_state<=next_state
  98.         //每一个时钟沿产生一次可能的状态变化
  99.         always@(posedge clk or negedge rst_n)
  100.                 if(!rst_n)
  101.                         cstate <= INIT;        //复位态
  102.                 else
  103.                         cstate <= nstate;
  104.        

  105.         //第二部分,状态转移,产生下一状态的整合逻辑
  106.         //状态的跳转
  107.         always@(cstate or time_ones or pdh_ok or locked)
  108.                 begin
  109.                        
  110.                         case (cstate)       
  111.                                
  112.                                 INIT:                        //初始化
  113.                                         begin               

  114.                                                 if(time_ones == T20S)        //20s
  115.                                                                 nstate <= RUN_INIT_I;
  116.                                                 else
  117.                                                                 nstate <= INIT;
  118.                                         end
  119.                   
  120.                                 RUN_INIT_I:        //运行        //初始化温度输出
  121.                                         begin
  122.                                                         nstate <= START_PZT_SCANNING;
  123.                                         end
  124.                
  125.                                 START_PZT_SCANNING:        //开始锯齿波扫描
  126.                                         begin
  127.                                                         nstate <= WAIT;
  128.                                         end
  129.                                
  130.                                 WAIT:        //等待锯齿波扫描 4 - 10s
  131.                                         begin
  132.                                                         //PDH OK?        //判断是否找到信号
  133.                                                         if(pdh_ok == LOCK)
  134.                                                                         nstate <= IF_PDH_OK;
  135.                                                         else
  136.                                                                         nstate <= WAIT;
  137.                                         end
  138.                                        
  139.                                 IF_PDH_OK:        //PDH OK判断
  140.                                         begin
  141.                
  142.                                                         if(time_ones == T2S)        //2s
  143.                                                                 begin
  144.                                                                
  145.                                                                         if(pdh_ok_count >= PDH_OK_COUNT_N)        //真信号
  146.                                                                                         nstate <= SEARCH_PDH_OK;        //搜索到pdh
  147.                                                                         else
  148.                                                                                         nstate <= WAIT;        //重新扫描
  149.                                                                                        
  150.                                                                 end       
  151.                                                         else
  152.                                                                 nstate <= IF_PDH_OK;
  153.                                                                
  154.                                         end
  155.                                
  156.                                 SEARCH_PDH_OK:                //扫描到PDH
  157.                                         begin
  158.                                                        
  159.                                                 //100MS等待
  160.                                                 if(time_count == T100MS)        //100ms
  161.                                                         begin
  162.                                                                 nstate <= LOCK_IN_PROCESS;
  163.                                                         end       
  164.                                                        
  165.                                         end
  166.                                        
  167.                                 LOCK_IN_PROCESS:        //锁入过程
  168.                                         begin
  169.                                        

  170.                                                 if(time_ones == T2S)        //2s
  171.                                                         begin
  172.                                                                         if(locked == LOCK)                                                       
  173.                                                                                 nstate <= LOCK_IN; //已锁定
  174.                                                                         else
  175.                                                                                 nstate <= UNLOCK_IN;        //未锁定
  176.                                                                                        
  177.                                                         end                                       
  178.                                        
  179.                                         end
  180.                                        
  181.                                 UNLOCK_IN:        //未锁定       
  182.                                         begin
  183.                                        
  184.                                                         //锁定失败次数小于5次
  185.                                                         if(locked_fail_count < 8'd5)       
  186.                                                                 begin
  187.                                                                         nstate <= UNLOCK_IN_RETRY;
  188.                                                                 end
  189.                                                         else
  190.                                                                 begin
  191.                                                                         nstate <= WAIT;
  192.                                                                 end                                       
  193.                                        
  194.                                         end
  195.                                        
  196.                                 UNLOCK_IN_RETRY:        //重试锁定
  197.                                         begin
  198.                                        
  199.                                                 //2S判断一次
  200.                                                 if(time_ones == T2S)        //2s
  201.                                                         begin
  202.                                                                 nstate <= LOCK_IN_PROCESS;
  203.                                                         end                                               
  204.                                        
  205.                                         end

  206.                                 LOCK_IN:        //已锁定
  207.                                         begin
  208.                                        
  209.                                                 if(locked == UNLOCK)        //unlock
  210.                                                         begin
  211.                                                                 nstate <= START_PZT_SCANNING;  //重新进入扫描模式
  212.                                                         end                                       
  213.                                        
  214.                                         end
  215.                                        
  216.                                        
  217.                                 default:nstate <= INIT;
  218.                         endcase
  219.                 end
  220.        
  221.        
  222.        
  223.         //第三段,产生输出
  224.         always@(posedge clk or negedge rst_n)
  225.                 if(!rst_n)
  226.                         begin
  227.                        
  228.                                 dac_ch1 <= 14'd8192;        //0
  229.                                
  230.                                 analog_switch_1 <= OFF;
  231.                                 analog_switch_2 <= OFF;
  232.                                 sawtooth_control <= OFF;
  233.                                
  234.                                
  235.                                 dac_to_temperature_i <= 14'd8192;        //0V
  236.                                 pdh_time_count <= 0;
  237.                                 pdh_ok_count <= 8'd0;
  238.                                 pdh_ok_delay_flag <= END;
  239. //                                locked_fail_count <= 8'd0;        //锁定失败计数
  240.                                                                                                                                                
  241.                                 N <= INIT_N;
  242.                                 DIR <= DIR_UP;        //init 扫描方向                       

  243.                                 time_count <= 0;
  244.                                 time_ones <= 0;
  245.                                
  246.                                 dac_to_temperature_top <= 14'd8192 + INIT_N;                //上限
  247.                                 dac_to_temperature_bottom  <= 14'd8192 - INIT_N;        //下限
  248.                        
  249.                         end
  250.                 else
  251.                         begin
  252.                                 case(nstate)
  253.                                
  254.                                         INIT:
  255.                                                 begin
  256.                                                        
  257.                                                         //系统预热20s
  258.                                                         if(time_count == T1S)        //1s
  259.                                                                 begin
  260.                                                                         time_ones <= time_ones + 1'b1;
  261.                                                                         time_count <= 0;
  262.                                                                 end
  263.                                                         else
  264.                                                                 time_count <= time_count + 1'b1;
  265.                                                                                                                
  266.                                                 end
  267.                                        
  268.                                 RUN_INIT_I:        //运行        //初始化温度输出
  269.                                         begin
  270.                                                         //init i = 0
  271.                                                         time_ones <= 8'd0;
  272.                                                         dac_to_temperature_i <= 14'd8192;
  273.                                        
  274.                                         end
  275.                                        
  276.                                 START_PZT_SCANNING:        //开始锯齿波扫描
  277.                                         begin
  278.                                                         //start pzt scanning
  279.                                                         analog_switch_1 <= OFF;
  280.                                                         analog_switch_2 <= ON;
  281.                                                        
  282.                                                         //开启锯齿波扫描
  283.                                                         sawtooth_control <= ON;       
  284.                                                        
  285.                                                         //T(i) = V * step * i;
  286.                                                         dac_ch1 <= dac_to_temperature_i;
  287.                                         end       
  288.                                        
  289.                                 WAIT:        //等待锯齿波扫描 4 - 10s
  290.                                         begin
  291.                                        
  292.                                                         //wait 4 - 10s
  293.                                                         if(time_count == T1S)        //1s
  294.                                                                 begin
  295.                                                                         time_ones <= time_ones + 1'b1;
  296.                                                                         time_count <= 0;
  297.                                                                 end
  298.                                                         else
  299.                                                                 time_count <= time_count + 1'b1;
  300.                                                                                
  301.                                                         if(time_ones == T2S)                //2s
  302.                                                                 begin
  303.                                                                         search_mode();        //扫描模式
  304.                                                                         time_ones <= 0;
  305.                                                                 end
  306.                                        
  307.                                                         dac_ch1 <= dac_to_temperature_i;        //更新数据
  308.        
  309.                                                         pdh_ok_delay_flag <= START;        //开始延时
  310.                                                         pdh_time_count <= 0;
  311.                                                         pdh_ok_count <= 8'd0;
  312.                
  313.                                         end

  314.                                 IF_PDH_OK:        //PDH OK判断
  315.                                         begin
  316.                                        
  317.                                        
  318.                                                 //锯齿波扫描延长2S
  319.                                                 if(time_count == T1S)        //1s
  320.                                                         begin
  321.                                                                 time_ones <= time_ones + 1'b1;
  322.                                                                 time_count <= 32'd0;
  323.                                                         end
  324.                                                 else
  325.                                                         time_count <= time_count + 1'b1;
  326.                                                                
  327.                                        
  328.                                                 //pdh误触发处理
  329.                                                 //开始延时
  330.                                                 if(pdh_ok_delay_flag == START)
  331.                                                         begin
  332.                                                                 if(pdh_time_count == T10MS)        //ms
  333.                                                                         begin
  334.                                                                                 pdh_ok_delay_flag <= END;
  335.                                                                                 pdh_time_count <= 32'd0;       
  336.                                                                         end
  337.                                                                 else
  338.                                                                         pdh_time_count <= pdh_time_count + 1'b1;
  339.                                                         end
  340.                                                 else
  341.                                                         begin
  342.                                                                 if(pdh_ok == LOCK)
  343.                                                                         begin
  344.                                                                                 pdh_ok_count <= pdh_ok_count + 1'b1;
  345.                                                                                 pdh_ok_delay_flag <= START;                                                                       
  346.                                                                         end
  347.                                                         end
  348.                                                                
  349.                                         end
  350.                                        
  351.                                 SEARCH_PDH_OK:                //扫描到PDH
  352.                                         begin
  353.                                                        
  354.                                                         time_ones <= 8'd0;
  355.                                                        
  356.                                                         //stop pzt scanning
  357.                                                         analog_switch_2 <= OFF;
  358.                                                         //analog_switch_1 <= ON;
  359.                                                         sawtooth_control <= OFF;
  360.                                                        
  361.                                                         if(time_count == T100MS)        //1s
  362.                                                                         begin
  363.                                                                        
  364.                                                                         end
  365.                                                         else
  366.                                                                         time_count <= time_count + 1'b1;
  367.                                                        
  368.                                                        
  369.                                         end
  370.                                        
  371.                         LOCK_IN_PROCESS:        //锁入过程
  372.                                         begin

  373.                                                         //锁入过程
  374.                                                         //analog_switch_2 <= OFF;
  375.                                                         analog_switch_1 <= ON;
  376.                                                
  377.                                                         //2S判断一次
  378.                                                         if(time_count == T1S)        //1s
  379.                                                                 begin
  380.                                                                         time_ones <= time_ones + 1'b1;
  381.                                                                         time_count <= 32'd0;
  382.                                                                 end
  383.                                                         else
  384.                                                                         time_count <= time_count + 1'b1;
  385.                                                        

  386.                                         end
  387.                                        
  388.                                        
  389.                                 UNLOCK_IN:        //未锁定       
  390.                                         begin
  391.                                        
  392.                                                 //锁定失败计数
  393.                                                 locked_fail_count <= locked_fail_count + 1'b1;
  394.                                                        
  395.                                                 time_ones <= 0;
  396.                                                 time_count <= 0;
  397.                                                
  398.                                                        
  399.                                                 if(locked_fail_count < 8'd5)       
  400.                                                         begin
  401.                                                                
  402.                                                         end
  403.                                                 else
  404.                                                         begin
  405.                                                                 if(dac_to_temperature_i > 14'd0)
  406.                                                                         dac_to_temperature_i <= dac_to_temperature_i - 1'b1;
  407.                                                        
  408.                                                                 analog_switch_1 <= OFF;
  409.                                                                 analog_switch_2 <= ON;       
  410.                                                                
  411.                                                                 locked_fail_count <= 8'd0;

  412.                                                         end
  413.                                        
  414.                                         end
  415.                                
  416.                                 UNLOCK_IN_RETRY:        //重试锁定
  417.                                         begin
  418.                                        
  419.                                                         analog_switch_1 <= OFF;
  420.                                                        
  421.                                                         if(time_count == T1S)        //1s
  422.                                                                 begin
  423.                                                                         time_ones <= time_ones + 1'b1;
  424.                                                                         time_count <= 32'd0;
  425.                                                                 end
  426.                                                         else
  427.                                                                         time_count <= time_count + 1'b1;
  428.                                                                        
  429.                                        
  430.                                         end
  431.                                        
  432.                                 LOCK_IN:        //已锁定
  433.                                         begin
  434.                                        
  435.                                                         //5S判断一次
  436.                                                         if(time_count == T1S)        //1s
  437.                                                                 begin
  438.                                                                         time_ones <= time_ones + 1'b1;
  439.                                                                         time_count <= 32'd0;
  440.                                                                 end
  441.                                                         else
  442.                                                                         time_count <= time_count + 1'b1;
  443.                                                                        
  444.                                                         if(time_ones == T5S)        //5s
  445.                                                                 begin
  446.                                                                
  447.                                                                         //电压 > 1 并且 处于锁定状态
  448.                                                                         if(adc_ch1_data > 16'sd6553 && dac_to_temperature_i < 14'd16383 && locked == LOCK)
  449.                                                                                 begin
  450.                                                                                         dac_to_temperature_i <= dac_to_temperature_i - 1;
  451.                                                                                 end               
  452.                                                                         else if(adc_ch1_data < -16'sd6553 && dac_to_temperature_i > 14'd0 && locked == LOCK)
  453.                                                                                 begin
  454.                                                                                         dac_to_temperature_i <= dac_to_temperature_i + 1;
  455.                                                                                 end               
  456.                                                                                
  457.                                                                         //T(i) = V * step * i;
  458.                                                                         dac_ch1 <= dac_to_temperature_i;       
  459.                
  460.                                                                         time_ones <= 0;
  461.                                                                        
  462.                                                                 end
  463.                                                                
  464.                                         end                                       
  465.                        
  466.                                 default:;
  467.                                 endcase
  468.                         end



        在我上面的三段式状态机中很多地方有涉及到,根据时间来进行状态跳转,我在产生第三段进行计时,第二段里面进行状态跳转,但跳转时如何清零time_count和time_ones呢,我现在是在下一个状态里面清,能在跳转的同时进行清零吗?

       在状态机里面涉及到定时一般是怎么做的啊?


已退回5积分

更多回帖

发帖
×
20
完善资料,
赚取积分