From 7cf24ce07484a6d86cd97a9af9c240da7e1a4043 Mon Sep 17 00:00:00 2001 From: Raptor Engineering Development Team Date: Fri, 29 Dec 2017 00:34:27 -0600 Subject: Initial conversion pass VHDL to Verilog --- pwrseq.v | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 pwrseq.v (limited to 'pwrseq.v') diff --git a/pwrseq.v b/pwrseq.v new file mode 100644 index 0000000..c4f9f5a --- /dev/null +++ b/pwrseq.v @@ -0,0 +1,207 @@ +// Copyright © 2017 Raptor Engineering, LLC +// Copyright © 2017, International Business Machines Corp. +// All Rights Reserved +// +// See LICENSE file for licensing details + +module pwrseq( + output wire [rail_size - 1:0] EN, + input wire [rail_size - 1:0] PGOOD_A, + input wire SYSEN_A, + output wire SYSGOOD, + inout wire SCL, + inout wire SDA, + input wire CLK_IN + ); + + parameter [31:0] rail_size; + + // Input output buffers and synchronizers + reg [rail_size - 1:0] EN_BUF = 1'b0; + reg [rail_size - 1:0] PGOOD = 1'b0; + reg [rail_size - 1:0] PGOOD_S = 1'b0; + reg SYSEN = 1'b0; + reg SYSEN_S = 1'b0; + reg SYSGOOD_BUF = 1'b0; + + // Sequencer State Machine + parameter [2:0] idleon = 0; + parameter [2:0] shifton = 1; + parameter [2:0] waitpgood = 2; + parameter [2:0] waiten = 3; + parameter [2:0] idleoff = 4; + parameter [2:0] shiftoff = 5; + parameter [2:0] waitoff = 6; + + reg [2:0] state = idleoff; + reg ERR = 1'b0; + reg [15:0] err_msg = 1'b1; + parameter all_on = 1'b1; + parameter all_off = 1'b0; + + // Clocks and timers + parameter counter_size = 20; + reg [counter_size - 1:0] T_COUNT; + + // t_max_wait is max delay from Enable assert to Pgood assert (200 ms assumption 4.125MHz clk) + parameter t_max_wait = 825000; + + // t_delay is delay from Pgood assert to next Enable assert (1ms assumption 4.125MHz clk) + parameter t_delay = 4125; + + //I2C signals + wire i2c_read_req; + reg [7:0] i2c_data_to_master = 8'b00000000; + wire [7:0] i2c_data_from_master; + wire i2c_data_valid; + wire i2c_rst = 1'b0; + reg [7:0] i2c_reg_cur = 8'b00000000; + parameter i2c_addr = 7'b0110001; + parameter i2c_pg_reg_addr1 = 8'b00000001; + parameter i2c_pg_reg_addr2 = i2c_pg_reg_addr1 + 1; + parameter i2c_status_reg_addr = i2c_pg_reg_addr2 + 1; + + I2C_slave #(i2c_addr) + I2C_SLAVE( + SCL, + SDA, + CLK_IN, + i2c_rst, + i2c_read_req, + i2c_data_to_master, + i2c_data_valid, + i2c_data_from_master + ); + + // Handle I2C + // 2 8-bit registers with PGOOD state on error + always @(posedge CLK_IN) begin + //return high byte with any memory address, loop on any consecutive reads + if (i2c_data_valid == 1'b1) begin + i2c_reg_cur <= i2c_data_from_master; + end + else if (i2c_read_req == 1'b1) begin + i2c_reg_cur <= i2c_reg_cur + 1; + end + case(i2c_reg_cur) + i2c_pg_reg_addr1 : begin + i2c_data_to_master <= err_msg[15:8]; + end + i2c_pg_reg_addr2 : begin + i2c_data_to_master <= err_msg[7:0]; + end + i2c_status_reg_addr : begin + i2c_data_to_master <= {6'b000000,SYSEN,SYSGOOD_BUF}; + end + default : begin + i2c_data_to_master <= 8'b00000000; + end + endcase + end + + // Power Sequencer state machine + always @(posedge CLK_IN) begin + // Increase counter + T_COUNT <= T_COUNT + 1; + + // Synchronize Asynchronous inputs to clock + PGOOD_S <= PGOOD_A; + PGOOD <= PGOOD_S; + SYSEN_S <= SYSEN_A; + SYSEN <= SYSEN_S; + + // Decide next state + case(state) + idleoff : begin + //Only leave idle off if system enable active and no error + if (ERR == 1'b1) begin + state <= idleoff; + end + else if (SYSEN == 1'b1) begin + state <= shifton; + end else begin + state <= idleoff; + end + end + shifton : begin + // enable next power rail, reset counter, wait for pgood + EN_BUF[rail_size - 1:1] <= EN_BUF[rail_size - 2:0]; + EN_BUF[0] <= 1'b1; + T_COUNT <= {(((counter_size - 1))-((0))+1){1'b0}}; + state <= waitpgood; + end + waitpgood : begin + // Wait for enabled power rail's PGOOD, after time with no pgood, error + if (T_COUNT > t_max_wait) begin + ERR <= 1'b1; + err_msg <= {16{1'b0}}; + err_msg[rail_size - 1:0] <= EN_BUF & PGOOD; + state <= shiftoff; + end + else if ((EN_BUF & PGOOD) == all_on) begin + state <= idleon; + end + else if (((EN_BUF & PGOOD) == EN_BUF)) begin + T_COUNT <= {(((counter_size - 1))-((0))+1){1'b0}}; + state <= waiten; + end else begin + state <= waitpgood; + end + end + waiten : begin + // delay between last pgood and next enable + if (T_COUNT > t_delay) begin + T_COUNT <= {(((counter_size - 1))-((0))+1){1'b0}}; + state <= shifton; + end else begin + state <= waiten; + end + end + idleon : begin + // stay in idle on unless power rail goes down (error) or system enable removed + SYSGOOD_BUF <= 1'b1; + if ((!(PGOOD == all_on))) begin + ERR <= 1'b1; + err_msg <= {16{1'b0}}; + err_msg[rail_size - 1:0] <= PGOOD; + end + if (((SYSEN == 1'b0) || (ERR == 1'b1))) begin + SYSGOOD_BUF <= 1'b0; + state <= shiftoff; + end else begin + state <= idleon; + end + end + shiftoff : begin + // Turn off enable for next power rail + EN_BUF[rail_size - 2:0] <= EN_BUF[rail_size - 1:1]; + EN_BUF[rail_size - 1] <= 1'b0; + if ((EN_BUF == all_off)) begin + state <= idleoff; + end else begin + T_COUNT <= {(((counter_size - 1))-((0))+1){1'b0}}; + state <= waitoff; + end + end + waitoff : begin + // in controlled shutdown, delay between disabling power rails + if (ERR == 1'b1) begin + state <= shiftoff; + //LED_BUF <= "10"; + end + else if (T_COUNT > t_delay) begin + state <= shiftoff; + //LED_BUF <= "10"; + end else begin + state <= waitoff; + end + end + endcase + end + + // Output enable buffer to pins + assign EN = ~(EN_BUF); + assign i2c_rst = 1'b0; + assign SYSGOOD = SYSGOOD_BUF; + +endmodule \ No newline at end of file -- cgit v1.2.1