基于CPLD的主板上电时序控制--状态机方式
目錄
- 1. 前言
- 1.1 需求
- 2. 背景介紹
- 3. 代碼部分
- 3.1 定義端口
- 3.2 定義參數
- 3.3 定義變量
- 3.4 例化模塊
- 3.5 邏輯部分
- 3.5.1 輔助邏輯
- 3.5.2 CPU狀態獲取邏輯
- 3.5.3 狀態機邏輯
- 3.5.4 按鍵捕捉
- 4. 后言
1. 前言
博主第一份工作做FPGA工程師,公司給了CPLD的任務給我練手,大大小小參與了幾款主板上電的設計,同一套代碼進行了多次修改運用。跳槽后,把代碼整理一下,改善代碼結構,優化可移植性。
CLPD是安路的,CPU是FT2000系列;
常用的上電控制有使用單片機和CPLD或者EC的方式,本文使用CPLD實現上電控制操作
如果覺得對你有幫助的話,還請不忘點個贊!!!!
1.1 需求
以下需求均可完成
需求如下:
串口通信和看門狗以后有機會再補充。
2. 背景介紹
上電時序控制說到底,是要求芯片在限定的時間對電源發出Enable信號,并檢測Power Good信號,在繼續下一電源的上電。所以打算使用狀態機的方式進行時序控制。
CPU狀態能夠通過PWR_CTR0-1引腳進行獲取
不同CPU的反饋不相同,要根據芯片參考手冊。
FT2000的上電要求如下:
掉電要求如下:
3. 代碼部分
3.1 定義端口
端口的名稱最好按照硬件設計師給出的原理圖進行相似的命名,方便交流
input CPLD_CLK_50M, //1.8V //CPU reset low active output reg FT_POR_N, //CPU power state out and control 1.8output reg FT_GPIO0_A1,input FT_PWR_CTR1,input FT_PWR_CTR0, output LED0, //DDR reset ,low activeoutput MEM_RESET_S3_N, // POWER CONTROLoutput reg VDD_CORE_EN, input VDD_CORE_PWRGD,output reg VDDQ_EN, input VDDQ_PWRGD, output reg VTT_EN, output reg VPP_EN, output reg P3V3_EN, output reg P1V8_EN, //control input RST_IN, input RST_OUT, input PWRBTN, input PS_ON3.2 定義參數
定義了狀態機的所有狀態和需要用到的延時值
//state machine parameter S0_WAIT_PWOER_ON = 5'd0; parameter S1_IDLE = 5'd1;parameter S2_OTHER_ON = 5'd2;parameter S3_CPU_CORE_UP = 5'd3;parameter S4_P1V8_ON = 5'd4;parameter S5_GPIO0_A1_DOWN = 5'd5;parameter S6_PCIE_RST = 5'd6;parameter S7_FT_RST_N_UP = 5'd7;parameter S8_WAIT_CPU_ACK = 5'd8;parameter S9_RECEIVE_CPU_ACK = 5'd9;parameter S10_S0_WORK = 5'd10;parameter S11_POWER_DOWN = 5'd11;parameter S12_PCIe_FT_DOWN = 5'd12;parameter S13_IO_PWR_DOWN = 5'd13;parameter S14_CORE_PWR_DOWN = 5'd14;parameter S15_OTHER_PWR_DOWN = 5'd15;// delay timeparameter TIME_20ms = 27'd20;parameter TIME_120ms = 27'd120; parameter TIME_140ms = 27'd140;parameter TIME_150ms = 27'd150;parameter TIME_1000ms = 27'd1000;3.3 定義變量
定義了一些變量:
3.4 例化模塊
例化了兩次模塊,因為按鍵輸入分為電源鍵和復位鍵,模塊支持復用,代碼在最后。
3.5 邏輯部分
見下文:
3.5.1 輔助邏輯
3.5.2 CPU狀態獲取邏輯
暫時不貼出來,需要的可以評論留言!
3.5.3 狀態機邏輯
//***** Three-stage state machine *****//// firstalways @(posedge CPLD_CLK_50M) begincurrent_state <= next_state;end//secondalways @(*) begincase (current_state)S0_WAIT_PWOER_ON:beginif (first_power_on_flag && first_sys_rst_flag && (delay_cnt== TIME_1000ms)) beginnext_state =S1_IDLE;end else if(soft_reset_flag ) beginnext_state =S1_IDLE;end else if(hard_power_on_flag || hard_reset_flag) beginnext_state =S1_IDLE;end else begin next_state =S0_WAIT_PWOER_ON;endend//S1_IDLE:beginif (delay_cnt== TIME_20ms) beginnext_state =S2_OTHER_ON;end else begin next_state =S1_IDLE;end endS2_OTHER_ON :beginif ( (delay_cnt== TIME_20ms)) beginnext_state =S3_CPU_CORE_UP;end else begin next_state =S2_OTHER_ON;end endS3_CPU_CORE_UP :beginif ( (delay_cnt== TIME_20ms)) beginnext_state =S4_P1V8_ON;end else begin next_state =S3_CPU_CORE_UP;end endS4_P1V8_ON :beginif ((delay_cnt== TIME_20ms)) beginnext_state =S5_GPIO0_A1_DOWN;end else begin next_state =S4_P1V8_ON;end endS5_GPIO0_A1_DOWN :beginif ( (delay_cnt== TIME_140ms)) beginnext_state =S6_PCIE_RST;end else begin next_state =S5_GPIO0_A1_DOWN;end endS6_PCIE_RST :beginif ((delay_cnt== TIME_20ms)) beginnext_state =S7_FT_RST_N_UP;end else begin next_state =S6_PCIE_RST;end endS7_FT_RST_N_UP :beginif ((delay_cnt== TIME_120ms)) beginnext_state =S8_WAIT_CPU_ACK;end else begin next_state =S7_FT_RST_N_UP;end endS8_WAIT_CPU_ACK :beginif (receive_cpu_1p == 1'b1) beginnext_state =S9_RECEIVE_CPU_ACK;end else begin next_state =S8_WAIT_CPU_ACK;end endS9_RECEIVE_CPU_ACK:beginif (cpu_ack==1'b1) beginnext_state =S10_S0_WORK;end else begin next_state =S9_RECEIVE_CPU_ACK;end endS10_S0_WORK :beginif((soft_power_off_flag == 1'b1) || (soft_reset_flag == 1'b1))begin next_state = S11_POWER_DOWN;end else if(hard_power_off_flag || hard_reset_flag) beginnext_state = S11_POWER_DOWN;end else begin next_state = S10_S0_WORK;endend S11_POWER_DOWN :beginif ((delay_cnt== TIME_20ms)) beginnext_state =S12_PCIe_FT_DOWN;end else begin next_state =S11_POWER_DOWN;end endS12_PCIe_FT_DOWN :beginif ((delay_cnt== TIME_150ms)) beginnext_state =S13_IO_PWR_DOWN;end else begin next_state =S12_PCIe_FT_DOWN;end endS13_IO_PWR_DOWN :beginif ((delay_cnt== TIME_20ms)) beginnext_state =S14_CORE_PWR_DOWN;end else begin next_state =S13_IO_PWR_DOWN;end endS14_CORE_PWR_DOWN :beginif ((delay_cnt== TIME_20ms)) beginnext_state =S15_OTHER_PWR_DOWN;end else begin next_state =S14_CORE_PWR_DOWN;end endS15_OTHER_PWR_DOWN :beginif ((delay_cnt== TIME_1000ms)) beginnext_state =S0_WAIT_PWOER_ON;end else begin next_state =S15_OTHER_PWR_DOWN;end enddefault: beginnext_state <= S0_WAIT_PWOER_ON;endendcase end //thirdalways @(posedge CPLD_CLK_50M)beginif(sys_rst) beginVDD_CORE_EN <=1'b0; VDDQ_EN <=1'b0; VTT_EN <=1'b0; VPP_EN <=1'b0; P3V3_EN <=1'b0; P1V8_EN <=1'b0; FT_GPIO0_A1 <=1'b1;FT_POR_N <=1'b0; clear_hard_flag <=1'b1; endelse begincase (current_state)S0_WAIT_PWOER_ON :begindelay_cnt_enable <=1'b1;delay_time_set <=TIME_1000ms;end //S1_IDLE :beginVDD_CORE_EN <=1'b0; VDDQ_EN <=1'b0; VTT_EN <=1'b0; VPP_EN <=1'b0; P3V3_EN <=1'b0; P1V8_EN <=1'b0; FT_GPIO0_A1 <=1'b1;FT_POR_N <=1'b0; // GAMC_RST_N <=1'b0; delay_time_set <=TIME_20ms;endS2_OTHER_ON :beginVDDQ_EN <=1'b1; VTT_EN <=1'b1; VPP_EN <=1'b1; P3V3_EN <=1'b1;delay_time_set <=TIME_20ms;endS3_CPU_CORE_UP :beginVDD_CORE_EN <=1'b1;delay_time_set <=TIME_20ms;endS4_P1V8_ON :beginP1V8_EN <=1'b1; delay_time_set <=TIME_20ms;endS5_GPIO0_A1_DOWN :beginFT_GPIO0_A1 <=1'b0;delay_time_set <=TIME_140ms; endS6_PCIE_RST :begin//GAMC_RST_N <=1'b1; //display card reset,pcie,low activedelay_time_set <=TIME_20ms; endS7_FT_RST_N_UP :beginFT_POR_N <=1'b1;delay_time_set <=TIME_120ms; endS8_WAIT_CPU_ACK :begincpu_ack <= 1'b1;clear_hard_flag <= 1'b1;delay_time_set <=TIME_20ms;endS9_RECEIVE_CPU_ACK :beginclear_hard_flag <=1'b0;delay_time_set <=TIME_20ms;endS10_S0_WORK :begindelay_time_set <=TIME_20ms;endS11_POWER_DOWN :beginpower_on_flag <=1'b0; delay_time_set <=TIME_20ms;endS12_PCIe_FT_DOWN :beginFT_POR_N <=1'b0;delay_time_set <=TIME_150ms; endS13_IO_PWR_DOWN :beginP1V8_EN <=1'b0;delay_time_set <=TIME_20ms; endS14_CORE_PWR_DOWN :beginVDD_CORE_EN <=1'b0;delay_time_set <=TIME_20ms; endS15_OTHER_PWR_DOWN :beginVDDQ_EN <=1'b0; VTT_EN <=1'b0; VPP_EN <=1'b0; P3V3_EN <=1'b0; delay_time_set <=TIME_1000ms; enddefault: begin;endendcaseendend// ******** sequential logic ******** //3.5.4 按鍵捕捉
見我的另一篇博客:
4. 后言
我的代碼在我參與的項目中能夠穩定運行,但是如果讀者想要進行移植和二次開發還需要結合自己項目的實際情況,最好是理解設計代碼。
完整代碼不貼了,代碼不是最完善的狀態,歡迎批評指正,本篇博客僅供參考!
有任何疑問歡迎評論留言
總結
以上是生活随笔為你收集整理的基于CPLD的主板上电时序控制--状态机方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Luogu P4168] [BZOJ
- 下一篇: 人物专访 | 从《黑客帝国》到《花木兰》