diff options
author | Raptor Engineering Development Team <support@raptorengineering.com> | 2017-12-30 17:50:01 -0600 |
---|---|---|
committer | Raptor Engineering Development Team <support@raptorengineering.com> | 2017-12-30 17:50:01 -0600 |
commit | 0b1c5059e5655f31a3d9c229ea5821ece9aee052 (patch) | |
tree | d372e4c673f97acebdc3b4eaf46711da2d872fe9 | |
parent | 7cf24ce07484a6d86cd97a9af9c240da7e1a4043 (diff) | |
download | talos-system-fpga-0b1c5059e5655f31a3d9c229ea5821ece9aee052.tar.gz talos-system-fpga-0b1c5059e5655f31a3d9c229ea5821ece9aee052.zip |
Initial buildable variant for Talos™ II
-rw-r--r-- | Makefile | 105 | ||||
-rw-r--r-- | i2c_slave.v | 50 | ||||
-rw-r--r-- | main.v | 558 | ||||
-rw-r--r-- | power_sequencer.v (renamed from pwrseq.v) | 143 | ||||
-rw-r--r-- | system_fpga.pcf | 76 | ||||
-rw-r--r-- | top.v | 536 |
6 files changed, 847 insertions, 621 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ebfddd3 --- /dev/null +++ b/Makefile @@ -0,0 +1,105 @@ +# This file is part of the Talos™ II system FPGA implementation +# +# © 2017 Raptor Engineering, LLC +# All Rights Reserved +# +# Licensed for exclusive use with Talos™ II systems from Raptor Computing Systems +# https://www.raptorcs.com/TALOSII + +MAX_FPGA_ROUTE_PASSES = 100 + +# Default seed +#ARACHNE_PNR_SEED = 1 + +# Selected seed from fastest placement search +# NOTE: Must be updated every time the Verilog source is modified, no matter how trivially! +# Does not need to be updated if firmware program (C) sources are modified +# 0 automatically uses the best placement result +ARACHNE_PNR_SEED = 0 +#ARACHNE_PNR_SEED = 1 + +YOSYS_ICE40_SIM_LIB = $(shell yosys-config --datdir/ice40/cells_sim.v) + +.PRECIOUS: system_fpga_%.int + +system_fpga_%.tmg: system_fpga_%.int + echo "Total path delay: inf ns (0.0 MHz)" > $@ + -icetime -tmd hx1k -p system_fpga.pcf -P vq100 $< > $@ 2>&1 + +system_fpga_%.int: system_fpga.blif + echo "" > $@ + -arachne-pnr -s $* -d 1k -P vq100 -m $(MAX_FPGA_ROUTE_PASSES) -p system_fpga.pcf $< -o $@ + +system_fpga.int: system_fpga_1.tmg system_fpga_2.tmg system_fpga_3.tmg system_fpga_4.tmg system_fpga_5.tmg system_fpga_6.tmg system_fpga_7.tmg system_fpga_8.tmg system_fpga_9.tmg \ + system_fpga_10.tmg system_fpga_11.tmg system_fpga_12.tmg system_fpga_13.tmg system_fpga_14.tmg system_fpga_15.tmg system_fpga_16.tmg system_fpga_17.tmg system_fpga_18.tmg system_fpga_19.tmg \ + system_fpga_20.tmg system_fpga_21.tmg system_fpga_22.tmg system_fpga_23.tmg system_fpga_24.tmg system_fpga_25.tmg system_fpga_26.tmg system_fpga_27.tmg system_fpga_28.tmg system_fpga_29.tmg \ + system_fpga_30.tmg system_fpga_31.tmg system_fpga_32.tmg system_fpga_33.tmg system_fpga_34.tmg system_fpga_35.tmg system_fpga_36.tmg system_fpga_37.tmg system_fpga_38.tmg system_fpga_39.tmg \ + system_fpga_40.tmg system_fpga_41.tmg system_fpga_42.tmg system_fpga_43.tmg system_fpga_44.tmg system_fpga_45.tmg system_fpga_46.tmg system_fpga_47.tmg system_fpga_48.tmg system_fpga_49.tmg \ + system_fpga_50.tmg system_fpga_51.tmg system_fpga_52.tmg system_fpga_53.tmg system_fpga_54.tmg system_fpga_55.tmg system_fpga_56.tmg system_fpga_57.tmg system_fpga_58.tmg system_fpga_59.tmg \ + system_fpga_60.tmg system_fpga_61.tmg system_fpga_62.tmg system_fpga_63.tmg system_fpga_64.tmg + BEST_TRIAL=0; \ + BEST_TRIAL_RESULT=0; \ + for trial in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64; do \ + CURRENT_TRIAL_RESULT=$$(cat system_fpga_$${trial}.tmg | grep "Total path delay" | awk '{print $$6}' | sed 's/(//g'); \ + if [ "$$CURRENT_TRIAL_RESULT" != "" ]; then \ + echo "system_fpga_$${trial}.tmg : $$CURRENT_TRIAL_RESULT"; \ + COMPARISON_RESULT=$$(echo "$$CURRENT_TRIAL_RESULT > $$BEST_TRIAL_RESULT" | bc -l); \ + if [ $$COMPARISON_RESULT -eq 1 ]; then \ + BEST_TRIAL=system_fpga_$${trial}.tmg; \ + BEST_TRIAL_RESULT=$$CURRENT_TRIAL_RESULT; \ + fi; \ + fi; \ + done; \ + echo "Fastest result: $$BEST_TRIAL : $$BEST_TRIAL_RESULT"; \ + cp `echo $$BEST_TRIAL | sed 's/\.tmg/\.int/g'` system_fpga.int; \ + cp $$BEST_TRIAL system_fpga.tmg +ifneq ($(ARACHNE_PNR_SEED),0) + cp system_fpga_$(ARACHNE_PNR_SEED).int system_fpga.int + cp system_fpga_$(ARACHNE_PNR_SEED).tmg system_fpga.tmg +endif + cat system_fpga.tmg + +system_fpga.ex: system_fpga.int + icebox_explain system_fpga.int > system_fpga.ex + +system_fpga.blif: main.v power_sequencer.v i2c_slave.v + yosys -l yosys.log -q -p "synth_ice40 -top system_fpga_top -blif system_fpga.blif" main.v power_sequencer.v i2c_slave.v + +system_fpga.bin: system_fpga.int + cp system_fpga.int system_fpga.bin + +blank.rom: + dd if=/dev/zero ibs=1M count=4 | tr "\000" "\377" > blank.rom + +system_fpga.rom: blank.rom system_fpga.bin + cp blank.rom system_fpga.rom + dd if=system_fpga.bin of=system_fpga.rom conv=notrunc + +all: system_fpga.rom + +dump_toolchain_info: + -@echo "================================================================================" + -@echo "Base system:\t" + -@echo -n "Architecture:\t" + -@uname -m 2>/dev/null + -@echo -n "gcc:\t\t" + -@gcc -dumpversion 2>/dev/null + -@echo -n "clang:\t\t" + -@clang --version 2>/dev/null | head -n 1 + -@echo "\nFPGA toolchain:" + -@echo -n "Icarus verilog:\t" + -@iverilog -V 2>/dev/null | head -n 1 + -@echo -n "Yosys:\t\t" + -@yosys -V 2>/dev/null + -@echo -n "arachne-pnr:\t" + -@arachne-pnr -v 2>/dev/null + -@echo "================================================================================" + +test: system_fpga.bin + iceprog -S system_fpga.bin + +flash: system_fpga.bin + iceprog system_fpga.bin + +clean: + rm -f system_fpga.blif system_fpga.ex system_fpga.int system_fpga.tmg system_fpga_*.int system_fpga_*.tmg system_fpga.bin yosys.log diff --git a/i2c_slave.v b/i2c_slave.v index 2701ef4..14c97f6 100644 --- a/i2c_slave.v +++ b/i2c_slave.v @@ -1,12 +1,18 @@ -// Copyright © 2017 Raptor Engineering, LLC // Copyright © 2014-2016 Peter Samarin +// Copyright © 2017 Raptor Engineering, LLC // All Rights Reserved // // See I2C_SLAVE_LICENSE file for licensing details -module I2C_slave( - inout wire scl, - inout wire sda, +module i2c_slave( + input wire scl_in, + output wire scl_out, + output wire scl_direction, + + input wire sda_in, + output wire sda_out, + output wire sda_direction, + input wire clk, input wire rst, @@ -17,7 +23,7 @@ module I2C_slave( output wire [7:0] data_from_master ); - parameter [6:0] SLAVE_ADDR; + parameter [6:0] SLAVE_ADDR = 0; //---------------------------------------------------------- @@ -34,32 +40,32 @@ module I2C_slave( reg [2:0] state_reg = i2c_idle; reg cmd_reg = 1'b0; reg [31:0] bits_processed_reg = 0; - reg continue_reg = 1'b0; // Helpers to figure out next state + reg continue_reg = 1'b0; // Helpers to figure out next state reg start_reg = 1'b0; reg stop_reg = 1'b0; reg scl_rising_reg = 1'b0; - reg scl_falling_reg = 1'b0; // Address and data received from master + reg scl_falling_reg = 1'b0; // Address and data received from master reg [6:0] addr_reg = 1'b0; - reg [7:0] data_reg = 1'b0; // Delayed SCL (by 1 clock cycle, and by 2 clock cycles) + reg [7:0] data_reg = 1'b0; // Delayed SCL (by 1 clock cycle, and by 2 clock cycles) reg scl_reg = 1'b1; - reg scl_prev_reg = 1'b1; // Slave writes on scl + reg scl_prev_reg = 1'b1; // Slave writes on scl wire scl_wen_reg = 1'b0; - wire scl_o_reg = 1'b0; // Delayed SDA (1 clock cycle, and 2 clock cycles) + wire scl_o_reg = 1'b0; // Delayed SDA (1 clock cycle, and 2 clock cycles) reg sda_reg = 1'b1; - reg sda_prev_reg = 1'b1; // Slave writes on sda + reg sda_prev_reg = 1'b1; // Slave writes on sda reg sda_wen_reg = 1'b0; - reg sda_o_reg = 1'b0; // User interface + reg sda_o_reg = 1'b0; // User interface reg data_valid_reg = 1'b0; reg read_req_reg = 1'b0; reg [7:0] data_to_master_reg = 1'b0; always @(posedge clk) begin // Delay SCL by 1 and 2 clock cycles - scl_reg <= scl; + scl_reg <= scl_in; scl_prev_reg <= scl_reg; // Delay SDA by 1 and 2 clock cycles - sda_reg <= sda; + sda_reg <= sda_in; sda_prev_reg <= sda_reg; // Detect rising and falling SCL @@ -223,23 +229,25 @@ module I2C_slave( // Reset counter and state on start/stop //------------------------------------------------------ if (start_reg == 1'b1) begin - state_reg <= i2c_get_address_and_cmd; - bits_processed_reg <= 0; + state_reg <= i2c_get_address_and_cmd; + bits_processed_reg <= 0; end if (stop_reg == 1'b1) begin - state_reg <= i2c_idle; - bits_processed_reg <= 0; + state_reg <= i2c_idle; + bits_processed_reg <= 0; end if (rst == 1'b1) begin - state_reg <= i2c_idle; + state_reg <= i2c_idle; end end //-------------------------------------------------------- // I2C interface //-------------------------------------------------------- - assign sda = sda_wen_reg == 1'b1 ? sda_o_reg : 1'bZ; - assign scl = scl_wen_reg == 1'b1 ? scl_o_reg : 1'bZ; + assign sda_out = (sda_o_reg & sda_wen_reg); + assign sda_direction = sda_wen_reg; + assign scl_out = (scl_o_reg & scl_wen_reg); + assign scl_direction = scl_wen_reg; //-------------------------------------------------------- // User interface //-------------------------------------------------------- @@ -0,0 +1,558 @@ +// Copyright © 2017, International Business Machines Corp. +// Copyright © 2017 Raptor Engineering, LLC +// All Rights Reserved +// +// See LICENSE file for licensing details + +module system_fpga_top + ( + // LPC clock + input wire lpc_clock, + + // General I/O + input wire sysen, + output wire sysgood, + input wire debug_in, + + // DD1 temp fix for VCS overcurrent bug + input wire seq_cont, + + // Enable outputs + output wire vdda_en, + output wire vddb_en, + output wire vcsa_en, + output wire vcsb_en, + output wire vdna_en, + output wire vdnb_en, + output wire vioa_en, + output wire viob_en, + output wire vppab_en, + output wire vppcd_en, + output wire vddrab_en, + output wire vttab_en, + output wire vddrcd_en, + output wire vttcd_en, + output wire avdd_en, + output wire miscio_en, + output wire atx_en, + + // Power Good inputs + input wire vdda_pg, + input wire vddb_pg, + input wire vcsa_pg, + input wire vcsb_pg, + input wire vdna_pg, + input wire vdnb_pg, + input wire vioa_pg, + input wire viob_pg, + input wire vppab_pg, + input wire vppcd_pg, + input wire vddrab_pg, + input wire vddrcd_pg, + input wire avdd_pg, + input wire miscio_pg, + input wire atx_pg, + input wire bmc_vr_pg, + + // I2C + inout i2c_scl, + inout i2c_sda, + + // Second CPU Present Detection + input wire cpub_present_n, + output wire cpub_clk_oea, + output wire cpub_clk_oeb, + + // Resets + output wire lpc_rst, + input wire bmc_software_pg, + output wire bmc_rst, + output wire fan_rst, + output wire usbhub_rst, + output wire cpu_stby_rst, + + // Reserved for Future Use + output wire dual_5v_ctrl, + output wire window_open_n + ); + + wire i2c_scl_in; + wire i2c_scl_out; + wire i2c_scl_direction; + + wire i2c_sda_in; + wire i2c_sda_out; + wire i2c_sda_direction; + + SB_IO #( + .PIN_TYPE(6'b101001), + .PULLUP(1'b1) + ) i2c_scl_io ( + .PACKAGE_PIN(i2c_scl), + .OUTPUT_ENABLE(i2c_scl_direction), + .D_OUT_0(i2c_scl_out), + .D_IN_0(i2c_scl_in) + ); + + SB_IO #( + .PIN_TYPE(6'b101001), + .PULLUP(1'b1) + ) i2c_sda_io ( + .PACKAGE_PIN(i2c_sda), + .OUTPUT_ENABLE(i2c_sda_direction), + .D_OUT_0(i2c_sda_out), + .D_IN_0(i2c_sda_in) + ); + + // TODO update version + parameter fpga_version = 8'b00000110; + parameter rail_size = 15; + wire [rail_size - 1:0] en_buf = 1'b0; + wire [rail_size - 1:0] pg_buf; + wire sysgood_buf; + wire clk_in; + wire stdby_sed; + wire sysen_buf; + parameter railarray_0 = 1'b0; + parameter railarray_1 = 1'b1; // synchronizing signals + reg [rail_size - 1:0] pg_s1 = 1'b0; + reg [rail_size - 1:0] pg_s2 = 1'b0; + reg sysen_s1 = 1'b0; + reg sysen_s2 = 1'b0; + reg seq_s1 = 1'b1; + reg seq_s2 = 1'b1; // Timer (Watchdog and Delay) signals + reg [rail_size - 1:0] delay_done = 1'b0; + reg [23:0] w_count = 1'b0; + reg [16:0] d_count = 1'b0; // at 4.16MHz, w_count(23) being one means approximately 100ms have passed, good for checking watchdog between EN and PG + // d_count(16) being one means approximately 15ms have passed, good enough for delay betwen one rail and the next + reg wait_err = 1'b0; + reg operation_err = 1'b0; + reg err_found = 1'b0; + wire clear_err = 1'b0; + + // 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_clr_err_addr = 8'b00000011; + parameter i2c_pg_reg_addr1 = 8'b00000101; + parameter i2c_pg_reg_addr2 = i2c_pg_reg_addr1 + 1; + parameter i2c_status_reg_addr = i2c_pg_reg_addr2 + 1; + parameter i2c_version_reg_addr = 8'b00000000; + reg [15:0] i2c_pg_reg = 1'b0; + reg i2c_clr_err = 1'b0; + + // Divide input 33MHz clock down to 4.125MHz + reg [2:0] clock_divider; + always @(posedge lpc_clock) begin + clock_divider = clock_divider + 1; + end + assign clk_in = clock_divider[2]; + + // I2C device + i2c_slave #( + .SLAVE_ADDR(i2c_addr) + ) + i2c_slave_instance( + .scl_in(i2c_scl_in), + .scl_out(i2c_scl_out), + .scl_direction(i2c_scl_direction), + + .sda_in(i2c_sda_in), + .sda_out(i2c_sda_out), + .sda_direction(i2c_sda_direction), + + .clk(clk_in), + .rst(i2c_rst), + .read_req(i2c_read_req), + .data_to_master(i2c_data_to_master), + .data_valid(i2c_data_valid), + .data_from_master(i2c_data_from_master) + ); + + assign i2c_rst = 1'b0; + // Handle I2C + // 2 8-bit registers with PGOOD state on error + always @(posedge clk_in) begin + i2c_clr_err <= 1'b0; + + if (i2c_data_valid == 1'b1) begin + // data from master is register to be read + i2c_reg_cur <= i2c_data_from_master; + + //pulse clear err signal if i2c master reads register 0x03 + if (((i2c_data_from_master) == i2c_clr_err_addr)) begin + i2c_clr_err <= 1'b1; + end + end + else if (i2c_read_req == 1'b1) begin + i2c_reg_cur <= i2c_reg_cur + 1; + end + case(i2c_reg_cur) + i2c_clr_err_addr : begin + i2c_data_to_master <= 8'b11111111; + end + i2c_pg_reg_addr1 : begin + i2c_data_to_master <= i2c_pg_reg[15:8]; + end + i2c_pg_reg_addr2 : begin + i2c_data_to_master <= i2c_pg_reg[7:0]; + end + i2c_status_reg_addr : begin + // TODO add CPU1 presence detect + i2c_data_to_master <= {3'b000, wait_err, operation_err, err_found, sysen_buf, sysgood_buf}; + end + i2c_version_reg_addr : begin + i2c_data_to_master <= fpga_version; + end + default : begin + i2c_data_to_master <= 8'b00000000; + end + endcase + end + + always @(posedge clk_in) begin + pg_s1 <= pg_buf; + pg_s2 <= pg_s1; + sysen_s1 <= sysen_buf; + sysen_s2 <= sysen_s1; + seq_s1 <= seq_cont; + seq_s2 <= seq_s1; + if ((clear_err == 1'b1)) begin + wait_err <= 1'b0; + operation_err <= 1'b0; + err_found <= 1'b0; + w_count <= {24{1'b0}}; + d_count <= {17{1'b0}}; + end + else if ((sysen_s2 == 1'b0 || err_found == 1'b1)) begin + w_count <= {24{1'b0}}; + d_count <= {17{1'b0}}; + delay_done <= {(((rail_size - 1))-((0))+1){1'b0}}; + end + else if ((pg_s2[0] == 1'b1 && en_buf[0] == 1'b1 && delay_done[0] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[0] <= 1'b1; + end + end + else if ((pg_s2[1] == 1'b1 && en_buf[1] == 1'b1 && delay_done[1] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[1] <= 1'b1; + end + end + else if ((pg_s2[2] == 1'b1 && en_buf[2] == 1'b1 && delay_done[2] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[2] <= 1'b1; + end + end + else if ((pg_s2[3] == 1'b1 && en_buf[3] == 1'b1 && delay_done[3] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[3] <= 1'b1; + end + end + else if ((pg_s2[4] == 1'b1 && en_buf[4] == 1'b1 && delay_done[4] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[4] <= 1'b1; + end + end + else if ((pg_s2[5] == 1'b1 && en_buf[5] == 1'b1 && delay_done[5] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[5] <= 1'b1; + end + end + else if ((pg_s2[6] == 1'b1 && en_buf[6] == 1'b1 && delay_done[6] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[6] <= 1'b1; + end + end + else if ((pg_s2[7] == 1'b1 && en_buf[7] == 1'b1 && delay_done[7] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[7] <= 1'b1; + end + end + else if ((pg_s2[8] == 1'b1 && en_buf[8] == 1'b1 && delay_done[8] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[8] <= 1'b1; + end + end + else if ((pg_s2[9] == 1'b1 && en_buf[9] == 1'b1 && delay_done[9] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[9] <= 1'b1; + end + end + else if ((pg_s2[10] == 1'b1 && en_buf[10] == 1'b1 && delay_done[10] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[10] <= 1'b1; + end + end + else if ((pg_s2[11] == 1'b1 && en_buf[11] == 1'b1 && delay_done[11] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[11] <= 1'b1; + end + end + else if ((pg_s2[12] == 1'b1 && en_buf[12] == 1'b1 && delay_done[12] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[12] <= 1'b1; + end + end + else if ((pg_s2[13] == 1'b1 && en_buf[13] == 1'b1 && delay_done[13] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[13] <= 1'b1; + end + end + else if ((pg_s2[14] == 1'b1 && en_buf[14] == 1'b1 && delay_done[14] == 1'b0)) begin + w_count <= {24{1'b0}}; + d_count <= d_count + 1; + if ((d_count[16] == 1'b1)) begin + d_count <= {17{1'b0}}; + delay_done[14] <= 1'b1; + end + end + + // Error Checks + // Check time between Enables going high and PGOODs arriving. Error out after 100ms + else if ((pg_s2[0] == 1'b0 && en_buf[0] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[1] == 1'b0 && en_buf[1] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[2] == 1'b0 && en_buf[2] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[3] == 1'b0 && en_buf[3] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[4] == 1'b0 && en_buf[4] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[5] == 1'b0 && en_buf[5] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[6] == 1'b0 && en_buf[6] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[7] == 1'b0 && en_buf[7] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[8] == 1'b0 && en_buf[8] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[9] == 1'b0 && en_buf[9] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[10] == 1'b0 && en_buf[10] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[11] == 1'b0 && en_buf[11] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[12] == 1'b0 && en_buf[12] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[13] == 1'b0 && en_buf[13] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + else if ((pg_s2[14] == 1'b0 && en_buf[14] == 1'b1)) begin + w_count <= w_count + 1; + if ((w_count[23] == 1'b1)) begin + w_count <= {24{1'b0}}; + wait_err <= 1'b1; + end + end + if ((( ~(delay_done & ~pg_s2)) != railarray_1)) begin + operation_err <= 1'b1; + end + if (((wait_err | operation_err) == 1'b1 && clear_err == 1'b0)) begin + err_found <= 1'b1; + end else begin + i2c_pg_reg[14:0] <= pg_s2[14:0]; + end + end + + // Assign Ports to Enables + assign atx_en = ~en_buf[0]; + assign miscio_en = en_buf[1]; + assign vdna_en = en_buf[2]; + assign vdnb_en = en_buf[3] & ~cpub_present_n; + assign avdd_en = en_buf[4]; + assign vioa_en = en_buf[5]; + assign viob_en = en_buf[6] & ~cpub_present_n; + assign vdda_en = en_buf[7]; + assign vddb_en = en_buf[8] & ~cpub_present_n; + assign vcsa_en = en_buf[9]; + assign vcsb_en = en_buf[10] & ~cpub_present_n; + assign vppab_en = en_buf[11]; + assign vppcd_en = en_buf[12] & ~cpub_present_n; + assign vddrab_en = en_buf[13]; + assign vttab_en = en_buf[13]; + assign vddrcd_en = en_buf[14] & ~cpub_present_n; + assign vttcd_en = en_buf[14] & ~cpub_present_n; + + // Assign Ports to PGood buffer + assign pg_buf[0] = atx_pg; + assign pg_buf[1] = miscio_pg; + assign pg_buf[2] = vdna_pg; + assign pg_buf[3] = vdnb_pg | (cpub_present_n & en_buf[3]); + assign pg_buf[4] = avdd_pg; + assign pg_buf[5] = vioa_pg; + assign pg_buf[6] = viob_pg | (cpub_present_n & en_buf[6]); + assign pg_buf[7] = vdda_pg; + assign pg_buf[8] = vddb_pg | (cpub_present_n & en_buf[8]); + assign pg_buf[9] = vcsa_pg; + assign pg_buf[10] = vcsb_pg | (cpub_present_n & en_buf[10]); + assign pg_buf[11] = vppab_pg; + assign pg_buf[12] = vppcd_pg | (cpub_present_n & en_buf[12]); + assign pg_buf[13] = vddrab_pg; + assign pg_buf[14] = vddrcd_pg | (cpub_present_n & en_buf[14]); + + // Enable outputs + // Shut everything off if an error has occurred + // Otherwise, if system enable is up, then enable short delay is done after previous rail + // Otherwise, disable after next rail goes down + assign en_buf[0] = (sysen_s2 | pg_s2[1]) & ~err_found; + assign en_buf[1] = ((sysen_s2 & delay_done[0]) | pg_s2[2]) & ~err_found; + assign en_buf[2] = ((sysen_s2 & delay_done[1]) | pg_s2[3]) & ~err_found; + assign en_buf[3] = ((sysen_s2 & delay_done[2]) | pg_s2[4]) & ~err_found; + assign en_buf[4] = ((sysen_s2 & delay_done[ + 1]) | pg_s2[ + 1]) & ~err_found; + assign en_buf[5] = ((sysen_s2 & delay_done[4]) | pg_s2[6]) & ~err_found; + assign en_buf[6] = ((sysen_s2 & delay_done[5]) | pg_s2[7]) & ~err_found; + assign en_buf[7] = ((sysen_s2 & delay_done[6]) | pg_s2[8]) & ~err_found; + assign en_buf[8] = ((sysen_s2 & delay_done[7]) | pg_s2[9]) & ~err_found; + assign en_buf[9] = (( ~seq_s2 & sysen_s2 & delay_done[8]) | pg_s2[10]) & ~err_found; + assign en_buf[10] = ((sysen_s2 & delay_done[9]) | pg_s2[11]) & ~err_found; + assign en_buf[11] = ((sysen_s2 & delay_done[10]) | pg_s2[12]) & ~err_found; + assign en_buf[12] = ((sysen_s2 & delay_done[11]) | pg_s2[13]) & ~err_found; + assign en_buf[13] = ((sysen_s2 & delay_done[12]) | pg_s2[14]) & ~err_found; + assign en_buf[14] = (sysen_s2 & delay_done[13]) & ~err_found; + + // ERR state reset + assign clear_err = i2c_clr_err; + + // CPUB clk enables + assign cpub_clk_oea = ~cpub_present_n; + assign cpub_clk_oeb = ~cpub_present_n; + + // System PWRGOOD + assign sysgood_buf = delay_done[14]; + assign sysgood = sysgood_buf & bmc_software_pg; + assign lpc_rst = sysgood_buf; + + // CPU Reset + assign cpu_stby_rst = en_buf[0]; + + // BMC RESETs + assign bmc_rst = bmc_vr_pg; + assign usbhub_rst = sysgood_buf & bmc_software_pg; + assign fan_rst = ~bmc_vr_pg; + + // debug_in override allows non-BMC control of CPLD + assign sysen_buf = sysen | ~debug_in; + // assign sysen_buf = ~debug_in; + + assign dual_5v_ctrl = 1'b0; + assign window_open_n = 1'b0; + +endmodule diff --git a/pwrseq.v b/power_sequencer.v index c4f9f5a..d099cbf 100644 --- a/pwrseq.v +++ b/power_sequencer.v @@ -1,28 +1,35 @@ -// Copyright © 2017 Raptor Engineering, LLC // Copyright © 2017, International Business Machines Corp. +// Copyright © 2017 Raptor Engineering, LLC // 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 + output wire [rail_size - 1:0] en, + input wire [rail_size - 1:0] pgood_a, + input wire sysen_a, + output wire sysgood, + + input wire scl_in, + output wire scl_out, + output wire scl_direction, + + input wire sda_in, + output wire sda_out, + output wire sda_direction, + + input wire clk_in ); - parameter [31:0] rail_size; + parameter [31:0] rail_size = 15; // 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; + 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; @@ -34,14 +41,14 @@ module pwrseq( parameter [2:0] waitoff = 6; reg [2:0] state = idleoff; - reg ERR = 1'b0; + 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; + 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; @@ -61,21 +68,29 @@ module pwrseq( 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 + i2c_slave #( + .SLAVE_ADDR(i2c_addr) + ) + i2c_slave_instance( + .scl_in(scl_in), + .scl_out(scl_out), + .scl_direction(scl_direction), + + .sda_in(sda_in), + .sda_out(sda_out), + .sda_direction(sda_direction), + + .clk(clk_in), + .rst(i2c_rst), + .read_req(i2c_read_req), + .data_to_master(i2c_data_to_master), + .data_valid(i2c_data_valid), + .data_from_master(i2c_data_from_master) ); // Handle I2C - // 2 8-bit registers with PGOOD state on error - always @(posedge CLK_IN) begin + // 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; @@ -91,7 +106,7 @@ module pwrseq( i2c_data_to_master <= err_msg[7:0]; end i2c_status_reg_addr : begin - i2c_data_to_master <= {6'b000000,SYSEN,SYSGOOD_BUF}; + i2c_data_to_master <= {6'b000000, sysen, sysgood_buf}; end default : begin i2c_data_to_master <= 8'b00000000; @@ -100,24 +115,24 @@ module pwrseq( end // Power Sequencer state machine - always @(posedge CLK_IN) begin + always @(posedge clk_in) begin // Increase counter - T_COUNT <= T_COUNT + 1; + t_count <= t_count + 1; // Synchronize Asynchronous inputs to clock - PGOOD_S <= PGOOD_A; - PGOOD <= PGOOD_S; - SYSEN_S <= SYSEN_A; - SYSEN <= SYSEN_S; + 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 + if (err == 1'b1) begin state <= idleoff; end - else if (SYSEN == 1'b1) begin + else if (sysen == 1'b1) begin state <= shifton; end else begin state <= idleoff; @@ -125,24 +140,24 @@ module pwrseq( 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}}; + 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; + // 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; + err_msg[rail_size - 1:0] <= en_buf & pgood; state <= shiftoff; end - else if ((EN_BUF & PGOOD) == all_on) begin + 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}}; + else if (((en_buf & pgood) == en_buf)) begin + t_count <= {(((counter_size - 1))-((0))+1){1'b0}}; state <= waiten; end else begin state <= waitpgood; @@ -150,8 +165,8 @@ module pwrseq( 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}}; + if (t_count > t_delay) begin + t_count <= {(((counter_size - 1))-((0))+1){1'b0}}; state <= shifton; end else begin state <= waiten; @@ -159,14 +174,14 @@ module pwrseq( 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; + sysgood_buf <= 1'b1; + if ((!(pgood == all_on))) begin + err <= 1'b1; err_msg <= {16{1'b0}}; - err_msg[rail_size - 1:0] <= PGOOD; + err_msg[rail_size - 1:0] <= pgood; end - if (((SYSEN == 1'b0) || (ERR == 1'b1))) begin - SYSGOOD_BUF <= 1'b0; + if (((sysen == 1'b0) || (err == 1'b1))) begin + sysgood_buf <= 1'b0; state <= shiftoff; end else begin state <= idleon; @@ -174,22 +189,22 @@ module pwrseq( 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 + 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}}; + 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 + if (err == 1'b1) begin state <= shiftoff; //LED_BUF <= "10"; end - else if (T_COUNT > t_delay) begin + else if (t_count > t_delay) begin state <= shiftoff; //LED_BUF <= "10"; end else begin @@ -200,8 +215,8 @@ module pwrseq( end // Output enable buffer to pins - assign EN = ~(EN_BUF); + assign en = ~(en_buf); assign i2c_rst = 1'b0; - assign SYSGOOD = SYSGOOD_BUF; + assign sysgood = sysgood_buf; endmodule
\ No newline at end of file diff --git a/system_fpga.pcf b/system_fpga.pcf new file mode 100644 index 0000000..51ecc68 --- /dev/null +++ b/system_fpga.pcf @@ -0,0 +1,76 @@ +# This file is part of the Talos™ II system FPGA implementation +# +# © 2017 Raptor Engineering, LLC +# All Rights Reserved +# +# Licensed for exclusive use with Talos™ II systems from Raptor Computing Systems +# https://www.raptorcs.com/TALOSII + +# LPC clock +set_io lpc_clock 13 + +# General I/O +set_io sysen 15 +set_io sysgood 53 +set_io debug_in 25 + +# Workaround Control +set_io seq_cont 100 + +# Power Plane Enable +set_io vdda_en 72 +set_io vddb_en 79 +set_io vcsa_en 71 +set_io vcsb_en 78 +set_io vdna_en 68 +set_io vdnb_en 51 +set_io vioa_en 66 +set_io viob_en 69 +set_io vppab_en 52 +set_io vppcd_en 60 +set_io vddrab_en 65 +set_io vttab_en 62 +set_io vddrcd_en 64 +set_io vttcd_en 63 +set_io avdd_en 59 +set_io miscio_en 56 +set_io atx_en 57 + +# Power Good Sense +set_io vdda_pg 28 +set_io vddb_pg 26 +set_io vcsa_pg 29 +set_io vcsb_pg 27 +set_io vdna_pg 34 +set_io vdnb_pg 30 +set_io vioa_pg 36 +set_io viob_pg 33 +set_io vppab_pg 42 +set_io vppcd_pg 41 +set_io vddrab_pg 37 +set_io vddrcd_pg 40 +set_io avdd_pg 19 +set_io miscio_pg 24 +set_io atx_pg 20 +set_io bmc_vr_pg 18 + +# I2C +set_io i2c_scl 86 +set_io i2c_sda 85 + +# CPU B Presence Detect +set_io cpub_present_n 4 +set_io cpub_clk_oea 10 +set_io cpub_clk_oeb 9 + +# Resets +set_io lpc_rst 82 +set_io bmc_software_pg 8 +set_io bmc_rst 83 +set_io fan_rst 1 +set_io usbhub_rst 87 +set_io cpu_stby_rst 54 + +# Reserved +set_io dual_5v_ctrl 80 +set_io window_open_n 99
\ No newline at end of file @@ -1,536 +0,0 @@ -// Copyright © 2017 Raptor Engineering, LLC -// Copyright © 2017, International Business Machines Corp. -// All Rights Reserved -// -// See LICENSE file for licensing details - -module FPGA_TOP - ( - // General I/O - input wire SYSEN, - output wire SYSGOOD, - input wire DEBUG_IN, - - // DD1 temp fix for VCS overcurrent bug - input wire SEQ_CONT, - - // Enable outputs - output wire VDDA_EN, - output wire VDDB_EN, - output wire VCSA_EN, - output wire VCSB_EN, - output wire VDNA_EN, - output wire VDNB_EN, - output wire VIOA_EN, - output wire VIOB_EN, - output wire VPPAB_EN, - output wire VPPCD_EN, - output wire VDDRAB_EN, - output wire VTTAB_EN, - output wire VDDRCD_EN, - output wire VTTCD_EN, - output wire AVDD_EN, - output wire MISCIO_EN, - output wire ATX_EN, - - // Power Good inputs - input wire VDDA_PG, - input wire VDDB_PG, - input wire VCSA_PG, - input wire VCSB_PG, - input wire VDNA_PG, - input wire VDNB_PG, - input wire VIOA_PG, - input wire VIOB_PG, - input wire VPPAB_PG, - input wire VPPCD_PG, - input wire VDDRAB_PG, - input wire VDDRCD_PG, - input wire AVDD_PG, - input wire MISCIO_PG, - input wire ATX_PG, - input wire BMC_VR_PG, - - // I2C - inout wire SCL, - inout wire SDA, - - // Second CPU Present Detection - input wire CPUB_PRESENT_N, - output wire CPUB_CLK_OEA, - output wire CPUB_CLK_OEB, - - // Resets - output wire LPC_RST, - input wire BMC_SOFTWARE_PG, - output wire BMC_RST, - output wire FAN_RST, - output wire USBHUB_RST, - output wire CPU_STBY_RST, - - // Reserved for Future Use - output wire DUAL_5V_CTRL, - output wire WINDOW_OPEN_N - ); - - // FUTURE update version - parameter cpld_version = 8'b00000110; - parameter rail_size = 15; - wire [rail_size - 1:0] EN_BUF = 1'b0; - wire [rail_size - 1:0] PG_BUF; - wire SYSGOOD_BUF; - wire CLK_IN; - wire stdby_sed; - wire SYSEN_BUF; - parameter railarray_0 = 1'b0; - parameter railarray_1 = 1'b1; // synchronizing signals - reg [rail_size - 1:0] PG_S1 = 1'b0; - reg [rail_size - 1:0] PG_S2 = 1'b0; - reg SYSEN_S1 = 1'b0; - reg SYSEN_S2 = 1'b0; - reg SEQ_S1 = 1'b1; - reg SEQ_S2 = 1'b1; // Timer (Watchdog and Delay) signals - reg [rail_size - 1:0] DELAY_DONE = 1'b0; - reg [23:0] W_COUNT = 1'b0; - reg [16:0] D_COUNT = 1'b0; // at 4.16MHz, W_COUNT(23) being one means approximately 100ms have passed, good for checking watchdog between EN and PG - // D_COUNT(16) being one means approximately 15ms have passed, good enough for delay betwen One rail and the next - reg WAIT_ERR = 1'b0; - reg OPERATION_ERR = 1'b0; - reg ERR_FOUND = 1'b0; // signal FIRST_DELAY : STD_LOGIC := '1'; - wire CLEAR_ERR = 1'b0; //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_clr_err_addr = 8'b00000011; - parameter i2c_pg_reg_addr1 = 8'b00000101; - parameter i2c_pg_reg_addr2 = i2c_pg_reg_addr1 + 1; - parameter i2c_status_reg_addr = i2c_pg_reg_addr2 + 1; - parameter i2c_version_reg_addr = 8'b00000000; - reg [15:0] i2c_pg_reg = 1'b0; - reg i2c_clr_err = 1'b0; - - OSCH OSC1( - .STDBY(1'b0), - .OSC(CLK_IN), - .SEDSTDBY(stdby_sed) - ); - - //debug - //CLEAR_ERR <= DUAL_5V_CTRL; - //Divide input 33MHz clock down to 4.125MHz - // process (CLK_IN) - // begin - // if (rising_edge(CLK_IN)) then - // CLK_REG <= CLK_REG + 1; - // end if; - // end process; - // CLK_DIV <= STD_LOGIC(CLK_REG(2)); - // Power Sequencer Instance - // SEQ1: entity work.pwrseq - // generic map(rail_size) - // port map( - // EN => EN_BUF, - // PGOOD_A => PG_BUF, - // SYSEN_A => SYSEN_BUF, - // SYSGOOD => SYSGOOD_BUF, - // SCL => SCL, - // SDA => SDA, - // CLK_IN => CLK_DIV - // CLK_IN => CLK_IN - // ); - //I2C device - 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); - - assign i2c_rst = 1'b0; - //Handle I2C - //2 8-bit registers with PGOOD state on error - always @(posedge CLK_IN) begin - i2c_clr_err <= 1'b0; - - if (i2c_data_valid == 1'b1) begin - // data from master is register to be read - i2c_reg_cur <= i2c_data_from_master; - - //pulse clear err signal if i2c master reads register 0x03 - if (((i2c_data_from_master) == i2c_clr_err_addr)) begin - i2c_clr_err <= 1'b1; - end - end - else if (i2c_read_req == 1'b1) begin - i2c_reg_cur <= i2c_reg_cur + 1; - end - case(i2c_reg_cur) - i2c_clr_err_addr : begin - i2c_data_to_master <= 8'b11111111; - end - i2c_pg_reg_addr1 : begin - i2c_data_to_master <= i2c_pg_reg[15:8]; - end - i2c_pg_reg_addr2 : begin - i2c_data_to_master <= i2c_pg_reg[7:0]; - end - i2c_status_reg_addr : begin - //FUTURE add CPU1 Present detect - i2c_data_to_master <= {3'b000,WAIT_ERR,OPERATION_ERR,ERR_FOUND,SYSEN_BUF,SYSGOOD_BUF}; - end - i2c_version_reg_addr : begin - i2c_data_to_master <= cpld_version; - end - default : begin - i2c_data_to_master <= 8'b00000000; - end - endcase - end - - always @(posedge CLK_IN) begin - PG_S1 <= PG_BUF; - PG_S2 <= PG_S1; - SYSEN_S1 <= SYSEN_BUF; - SYSEN_S2 <= SYSEN_S1; - SEQ_S1 <= SEQ_CONT; - SEQ_S2 <= SEQ_S1; - if ((CLEAR_ERR == 1'b1)) begin - WAIT_ERR <= 1'b0; - OPERATION_ERR <= 1'b0; - ERR_FOUND <= 1'b0; - W_COUNT <= {24{1'b0}}; - D_COUNT <= {17{1'b0}}; - end - else if ((SYSEN_S2 == 1'b0 || ERR_FOUND == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= {17{1'b0}}; - DELAY_DONE <= {(((rail_size - 1))-((0))+1){1'b0}}; - end - else if ((PG_S2[0] == 1'b1 && EN_BUF[0] == 1'b1 && DELAY_DONE[0] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[0] <= 1'b1; - end - end - else if ((PG_S2[1] == 1'b1 && EN_BUF[1] == 1'b1 && DELAY_DONE[1] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[1] <= 1'b1; - end - end - else if ((PG_S2[2] == 1'b1 && EN_BUF[2] == 1'b1 && DELAY_DONE[2] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[2] <= 1'b1; - end - end - else if ((PG_S2[3] == 1'b1 && EN_BUF[3] == 1'b1 && DELAY_DONE[3] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[3] <= 1'b1; - end - end - else if ((PG_S2[4] == 1'b1 && EN_BUF[4] == 1'b1 && DELAY_DONE[4] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[4] <= 1'b1; - end - end - else if ((PG_S2[5] == 1'b1 && EN_BUF[5] == 1'b1 && DELAY_DONE[5] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[5] <= 1'b1; - end - end - else if ((PG_S2[6] == 1'b1 && EN_BUF[6] == 1'b1 && DELAY_DONE[6] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[6] <= 1'b1; - end - end - else if ((PG_S2[7] == 1'b1 && EN_BUF[7] == 1'b1 && DELAY_DONE[7] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[7] <= 1'b1; - end - end - else if ((PG_S2[8] == 1'b1 && EN_BUF[8] == 1'b1 && DELAY_DONE[8] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[8] <= 1'b1; - end - end - else if ((PG_S2[9] == 1'b1 && EN_BUF[9] == 1'b1 && DELAY_DONE[9] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[9] <= 1'b1; - end - end - else if ((PG_S2[10] == 1'b1 && EN_BUF[10] == 1'b1 && DELAY_DONE[10] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[10] <= 1'b1; - end - end - else if ((PG_S2[11] == 1'b1 && EN_BUF[11] == 1'b1 && DELAY_DONE[11] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[11] <= 1'b1; - end - end - else if ((PG_S2[12] == 1'b1 && EN_BUF[12] == 1'b1 && DELAY_DONE[12] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[12] <= 1'b1; - end - end - else if ((PG_S2[13] == 1'b1 && EN_BUF[13] == 1'b1 && DELAY_DONE[13] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[13] <= 1'b1; - end - end - else if ((PG_S2[14] == 1'b1 && EN_BUF[14] == 1'b1 && DELAY_DONE[14] == 1'b0)) begin - W_COUNT <= {24{1'b0}}; - D_COUNT <= D_COUNT + 1; - if ((D_COUNT[16] == 1'b1)) begin - D_COUNT <= {17{1'b0}}; - DELAY_DONE[14] <= 1'b1; - end - end - - // Error Checks - // Check time between Enables going high and PGOODs arriving. Error out after 100ms - else if ((PG_S2[0] == 1'b0 && EN_BUF[0] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[1] == 1'b0 && EN_BUF[1] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[2] == 1'b0 && EN_BUF[2] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[3] == 1'b0 && EN_BUF[3] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[4] == 1'b0 && EN_BUF[4] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[5] == 1'b0 && EN_BUF[5] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[6] == 1'b0 && EN_BUF[6] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[7] == 1'b0 && EN_BUF[7] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[8] == 1'b0 && EN_BUF[8] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[9] == 1'b0 && EN_BUF[9] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[10] == 1'b0 && EN_BUF[10] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[11] == 1'b0 && EN_BUF[11] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[12] == 1'b0 && EN_BUF[12] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[13] == 1'b0 && EN_BUF[13] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - else if ((PG_S2[14] == 1'b0 && EN_BUF[14] == 1'b1)) begin - W_COUNT <= W_COUNT + 1; - if ((W_COUNT[23] == 1'b1)) begin - W_COUNT <= {24{1'b0}}; - WAIT_ERR <= 1'b1; - end - end - if ((( ~(DELAY_DONE & ~PG_S2)) != railarray_1)) begin - OPERATION_ERR <= 1'b1; - end - if (((WAIT_ERR | OPERATION_ERR) == 1'b1 && CLEAR_ERR == 1'b0)) begin - ERR_FOUND <= 1'b1; - end else begin - i2c_pg_reg[14:0] <= PG_S2[14:0]; - end - end - - // Assign Ports to Enables - assign ATX_EN = ~EN_BUF[0]; - assign MISCIO_EN = EN_BUF[1]; - assign VDNA_EN = EN_BUF[2]; - assign VDNB_EN = EN_BUF[3] & ~CPUB_PRESENT_N; - assign AVDD_EN = EN_BUF[4]; - assign VIOA_EN = EN_BUF[5]; - assign VIOB_EN = EN_BUF[6] & ~CPUB_PRESENT_N; - assign VDDA_EN = EN_BUF[7]; - assign VDDB_EN = EN_BUF[8] & ~CPUB_PRESENT_N; - assign VCSA_EN = EN_BUF[9]; - assign VCSB_EN = EN_BUF[10] & ~CPUB_PRESENT_N; - assign VPPAB_EN = EN_BUF[11]; - assign VPPCD_EN = EN_BUF[12] & ~CPUB_PRESENT_N; - assign VDDRAB_EN = EN_BUF[13]; - assign VTTAB_EN = EN_BUF[13]; - assign VDDRCD_EN = EN_BUF[14] & ~CPUB_PRESENT_N; - assign VTTCD_EN = EN_BUF[14] & ~CPUB_PRESENT_N; - - // Assign Ports to PGood buffer - assign PG_BUF[0] = ATX_PG; - assign PG_BUF[1] = MISCIO_PG; - assign PG_BUF[2] = VDNA_PG; - assign PG_BUF[3] = VDNB_PG | (CPUB_PRESENT_N & EN_BUF[3]); - assign PG_BUF[4] = AVDD_PG; - assign PG_BUF[5] = VIOA_PG; - assign PG_BUF[6] = VIOB_PG | (CPUB_PRESENT_N & EN_BUF[6]); - assign PG_BUF[7] = VDDA_PG; - assign PG_BUF[8] = VDDB_PG | (CPUB_PRESENT_N & EN_BUF[8]); - assign PG_BUF[9] = VCSA_PG; - assign PG_BUF[10] = VCSB_PG | (CPUB_PRESENT_N & EN_BUF[10]); - assign PG_BUF[11] = VPPAB_PG; - assign PG_BUF[12] = VPPCD_PG | (CPUB_PRESENT_N & EN_BUF[12]); - assign PG_BUF[13] = VDDRAB_PG; - assign PG_BUF[14] = VDDRCD_PG | (CPUB_PRESENT_N & EN_BUF[14]); - - // Enable outputs - // Shut everything off if ann error has occurred - // Otherwise, if system enable is up, then enable short delay is done after previous rail - // Otherwise, disable after next rail goes down - assign EN_BUF[0] = (SYSEN_S2 | PG_S2[1]) & ~ERR_FOUND; - assign EN_BUF[1] = ((SYSEN_S2 & DELAY_DONE[0]) | PG_S2[2]) & ~ERR_FOUND; - assign EN_BUF[2] = ((SYSEN_S2 & DELAY_DONE[1]) | PG_S2[3]) & ~ERR_FOUND; - assign EN_BUF[3] = ((SYSEN_S2 & DELAY_DONE[2]) | PG_S2[4]) & ~ERR_FOUND; - assign EN_BUF[4] = ((SYSEN_S2 & DELAY_DONE[ + 1]) | PG_S2[ + 1]) & ~ERR_FOUND; - assign EN_BUF[5] = ((SYSEN_S2 & DELAY_DONE[4]) | PG_S2[6]) & ~ERR_FOUND; - assign EN_BUF[6] = ((SYSEN_S2 & DELAY_DONE[5]) | PG_S2[7]) & ~ERR_FOUND; - assign EN_BUF[7] = ((SYSEN_S2 & DELAY_DONE[6]) | PG_S2[8]) & ~ERR_FOUND; - assign EN_BUF[8] = ((SYSEN_S2 & DELAY_DONE[7]) | PG_S2[9]) & ~ERR_FOUND; - assign EN_BUF[9] = (( ~SEQ_S2 & SYSEN_S2 & DELAY_DONE[8]) | PG_S2[10]) & ~ERR_FOUND; - assign EN_BUF[10] = ((SYSEN_S2 & DELAY_DONE[9]) | PG_S2[11]) & ~ERR_FOUND; - assign EN_BUF[11] = ((SYSEN_S2 & DELAY_DONE[10]) | PG_S2[12]) & ~ERR_FOUND; - assign EN_BUF[12] = ((SYSEN_S2 & DELAY_DONE[11]) | PG_S2[13]) & ~ERR_FOUND; - assign EN_BUF[13] = ((SYSEN_S2 & DELAY_DONE[12]) | PG_S2[14]) & ~ERR_FOUND; - assign EN_BUF[14] = (SYSEN_S2 & DELAY_DONE[13]) & ~ERR_FOUND; - - //ERR state reset - assign CLEAR_ERR = i2c_clr_err; - - // CPUB clk enables - assign CPUB_CLK_OEA = ~CPUB_PRESENT_N; - assign CPUB_CLK_OEB = ~CPUB_PRESENT_N; - - // System PWRGOOD - assign SYSGOOD_BUF = DELAY_DONE[14]; - assign SYSGOOD = SYSGOOD_BUF & BMC_SOFTWARE_PG; - assign LPC_RST = SYSGOOD_BUF; - - // CPU Reset - assign CPU_STBY_RST = EN_BUF[0]; - - // BMC RESETs - assign BMC_RST = BMC_VR_PG; - assign USBHUB_RST = SYSGOOD_BUF & BMC_SOFTWARE_PG; - assign FAN_RST = ~BMC_VR_PG; - - // DEBUG_IN override allows non-BMC control of CPLD - assign SYSEN_BUF = SYSEN | ~DEBUG_IN; - // assign SYSEN_BUF = ~DEBUG_IN; - -endmodule
\ No newline at end of file |