summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIBM <openpower-development-team@ibm.com>2017-09-29 06:00:00 -0600
committerRaptor Engineering Development Team <support@raptorengineering.com>2017-12-29 00:42:08 -0600
commit5d8ea0866a80d3ccdeba6037ca87e7070d322c01 (patch)
tree0c8f9a74050650447dd99f6f4acdf334742caceb
downloadtalos-system-fpga-5d8ea0866a80d3ccdeba6037ca87e7070d322c01.tar.gz
talos-system-fpga-5d8ea0866a80d3ccdeba6037ca87e7070d322c01.zip
Initial import of Romulus support files
-rw-r--r--I2C_slave.vhd270
-rw-r--r--PWRseq_Romulus.vhd196
-rw-r--r--Romulus_CPLD_TOP.vhd555
-rw-r--r--txt_util.vhd582
4 files changed, 1603 insertions, 0 deletions
diff --git a/I2C_slave.vhd b/I2C_slave.vhd
new file mode 100644
index 0000000..80871a6
--- /dev/null
+++ b/I2C_slave.vhd
@@ -0,0 +1,270 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.txt_util.all;
+------------------------------------------------------------
+entity I2C_slave is
+ generic (
+ SLAVE_ADDR : std_logic_vector(6 downto 0));
+ port (
+ scl : inout std_logic;
+ sda : inout std_logic;
+ clk : in std_logic;
+ rst : in std_logic;
+ -- User interface
+ read_req : out std_logic;
+ data_to_master : in std_logic_vector(7 downto 0);
+ data_valid : out std_logic;
+ data_from_master : out std_logic_vector(7 downto 0));
+end entity I2C_slave;
+------------------------------------------------------------
+architecture arch of I2C_slave is
+ type state_t is (i2c_idle, i2c_get_address_and_cmd,
+ i2c_answer_ack_start, i2c_write,
+ i2c_read, i2c_read_ack_start,
+ i2c_read_ack_got_rising, i2c_read_stop);
+ -- I2C state management
+ signal state_reg : state_t := i2c_idle;
+ signal cmd_reg : std_logic := '0';
+ signal bits_processed_reg : integer range 0 to 8 := 0;
+ signal continue_reg : std_logic := '0';
+
+ -- Helpers to figure out next state
+ signal start_reg : std_logic := '0';
+ signal stop_reg : std_logic := '0';
+ signal scl_rising_reg : std_logic := '0';
+ signal scl_falling_reg : std_logic := '0';
+
+ -- Address and data received from master
+ signal addr_reg : std_logic_vector(6 downto 0) := (others => '0');
+ signal data_reg : std_logic_vector(7 downto 0) := (others => '0');
+
+ -- Delayed SCL (by 1 clock cycle, and by 2 clock cycles)
+ signal scl_reg : std_logic := '1';
+ signal scl_prev_reg : std_logic := '1';
+ -- Slave writes on scl
+ signal scl_wen_reg : std_logic := '0';
+ signal scl_o_reg : std_logic := '0';
+ -- Delayed SDA (1 clock cycle, and 2 clock cycles)
+ signal sda_reg : std_logic := '1';
+ signal sda_prev_reg : std_logic := '1';
+ -- Slave writes on sda
+ signal sda_wen_reg : std_logic := '0';
+ signal sda_o_reg : std_logic := '0';
+
+ -- User interface
+ signal data_valid_reg : std_logic := '0';
+ signal read_req_reg : std_logic := '0';
+ signal data_to_master_reg : std_logic_vector(7 downto 0) := (others => '0');
+begin
+ process (clk) is
+ begin
+ if rising_edge(clk) then
+ -- Delay SCL by 1 and 2 clock cycles
+ scl_reg <= scl;
+ scl_prev_reg <= scl_reg;
+ -- Delay SDA by 1 and 2 clock cycles
+ sda_reg <= sda;
+ sda_prev_reg <= sda_reg;
+ -- Detect rising and falling SCL
+ scl_rising_reg <= '0';
+ if scl_prev_reg = '0' and scl_reg = '1' then
+ scl_rising_reg <= '1';
+ end if;
+ scl_falling_reg <= '0';
+ if scl_prev_reg = '1' and scl_reg = '0' then
+ scl_falling_reg <= '1';
+ end if;
+
+ -- Detect I2C START condition
+ start_reg <= '0';
+ stop_reg <= '0';
+ if scl_reg = '1' and scl_prev_reg = '1' and
+ sda_prev_reg = '1' and sda_reg = '0' then
+ start_reg <= '1';
+ stop_reg <= '0';
+ end if;
+
+ -- Detect I2C STOP condition
+ if scl_prev_reg = '1' and scl_reg = '1' and
+ sda_prev_reg = '0' and sda_reg = '1' then
+ start_reg <= '0';
+ stop_reg <= '1';
+ end if;
+
+ end if;
+ end process;
+
+ ----------------------------------------------------------
+ -- I2C state machine
+ ----------------------------------------------------------
+ process (clk) is
+ begin
+ if rising_edge(clk) then
+ -- Default assignments
+ sda_o_reg <= '0';
+ sda_wen_reg <= '0';
+ -- User interface
+ data_valid_reg <= '0';
+ read_req_reg <= '0';
+
+ case state_reg is
+
+ when i2c_idle =>
+ if start_reg = '1' then
+ state_reg <= i2c_get_address_and_cmd;
+ bits_processed_reg <= 0;
+ end if;
+
+ when i2c_get_address_and_cmd =>
+ if scl_rising_reg = '1' then
+ if bits_processed_reg < 7 then
+ bits_processed_reg <= bits_processed_reg + 1;
+ addr_reg(6-bits_processed_reg) <= sda_reg;
+ elsif bits_processed_reg = 7 then
+ bits_processed_reg <= bits_processed_reg + 1;
+ cmd_reg <= sda_reg;
+ end if;
+ end if;
+
+ if bits_processed_reg = 8 and scl_falling_reg = '1' then
+ bits_processed_reg <= 0;
+ if addr_reg = SLAVE_ADDR then -- check req address
+ state_reg <= i2c_answer_ack_start;
+ if cmd_reg = '1' then -- issue read request
+ read_req_reg <= '1';
+ data_to_master_reg <= data_to_master;
+ end if;
+ else
+ assert false
+ report ("I2C: slave address: " & str(SLAVE_ADDR) &
+ ", requested address: " & str(addr_reg))
+ severity note;
+ state_reg <= i2c_idle;
+ end if;
+ end if;
+
+ ----------------------------------------------------
+ -- I2C acknowledge to master
+ ----------------------------------------------------
+ when i2c_answer_ack_start =>
+ sda_wen_reg <= '1';
+ sda_o_reg <= '0';
+ if scl_falling_reg = '1' then
+ if cmd_reg = '0' then
+ state_reg <= i2c_write;
+ else
+ state_reg <= i2c_read;
+ end if;
+ end if;
+
+ ----------------------------------------------------
+ -- WRITE
+ ----------------------------------------------------
+ when i2c_write =>
+ if scl_rising_reg = '1' then
+ if bits_processed_reg <= 7 then
+ data_reg(7-bits_processed_reg) <= sda_reg;
+ bits_processed_reg <= bits_processed_reg + 1;
+ end if;
+ if bits_processed_reg = 7 then
+ data_valid_reg <= '1';
+ end if;
+ end if;
+
+ if scl_falling_reg = '1' and bits_processed_reg = 8 then
+ state_reg <= i2c_answer_ack_start;
+ bits_processed_reg <= 0;
+ end if;
+
+ ----------------------------------------------------
+ -- READ: send data to master
+ ----------------------------------------------------
+ when i2c_read =>
+ sda_wen_reg <= '1';
+ sda_o_reg <= data_to_master_reg(7-bits_processed_reg);
+ if scl_falling_reg = '1' then
+ if bits_processed_reg < 7 then
+ bits_processed_reg <= bits_processed_reg + 1;
+ elsif bits_processed_reg = 7 then
+ state_reg <= i2c_read_ack_start;
+ bits_processed_reg <= 0;
+ end if;
+ end if;
+
+ ----------------------------------------------------
+ -- I2C read master acknowledge
+ ----------------------------------------------------
+ when i2c_read_ack_start =>
+ if scl_rising_reg = '1' then
+ state_reg <= i2c_read_ack_got_rising;
+ if sda_reg = '1' then -- nack = stop read
+ continue_reg <= '0';
+ else -- ack = continue read
+ continue_reg <= '1';
+ read_req_reg <= '1'; -- request reg byte
+ data_to_master_reg <= data_to_master;
+ end if;
+ end if;
+
+ when i2c_read_ack_got_rising =>
+ if scl_falling_reg = '1' then
+ if continue_reg = '1' then
+ if cmd_reg = '0' then
+ state_reg <= i2c_write;
+ else
+ state_reg <= i2c_read;
+ end if;
+ else
+ state_reg <= i2c_read_stop;
+ end if;
+ end if;
+
+ -- Wait for START or STOP to get out of this state
+ when i2c_read_stop =>
+ null;
+
+ -- Wait for START or STOP to get out of this state
+ when others =>
+ assert false
+ report ("I2C: slave address: " & str(SLAVE_ADDR) &
+ "ended up in an impossible state.")
+ severity note;
+ null;
+ end case;
+
+ --------------------------------------------------------
+ -- Reset counter and state on start/stop
+ --------------------------------------------------------
+ if start_reg = '1' then
+ state_reg <= i2c_get_address_and_cmd;
+ bits_processed_reg <= 0;
+ end if;
+
+ if stop_reg = '1' then
+ state_reg <= i2c_idle;
+ bits_processed_reg <= 0;
+ end if;
+
+ if rst = '1' then
+ state_reg <= i2c_idle;
+ end if;
+ end if;
+ end process;
+
+ ----------------------------------------------------------
+ -- I2C interface
+ ----------------------------------------------------------
+ sda <= sda_o_reg when sda_wen_reg = '1' else
+ 'Z';
+ scl <= scl_o_reg when scl_wen_reg = '1' else
+ 'Z';
+ ----------------------------------------------------------
+ -- User interface
+ ----------------------------------------------------------
+ -- Master writes
+ data_valid <= data_valid_reg;
+ data_from_master <= data_reg;
+ -- Master reads
+ read_req <= read_req_reg;
+end architecture arch; \ No newline at end of file
diff --git a/PWRseq_Romulus.vhd b/PWRseq_Romulus.vhd
new file mode 100644
index 0000000..a718bfd
--- /dev/null
+++ b/PWRseq_Romulus.vhd
@@ -0,0 +1,196 @@
+library IEEE;
+use IEEE.numeric_std.ALL;
+use IEEE.STD_LOGIC_1164.ALL;
+
+entity PWRseq_Romulus is
+ generic (rail_size : integer);
+ Port (EN : out STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others=>'0');
+ PGOOD_A : in STD_LOGIC_VECTOR (rail_size-1 downto 0);
+ SYSEN_A : in STD_LOGIC;
+ SYSGOOD: out STD_LOGIC := '0';
+ SCL: inout STD_LOGIC;
+ SDA: inout STD_LOGIC;
+ CLK_IN: in STD_LOGIC);
+end PWRseq_Romulus;
+
+architecture Behavioral of PWRseq_Romulus is
+ --Input output buffers and synchronizers
+ --constant rail_size : integer := EN'LENGTH;
+ signal EN_BUF : STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others => '0');
+ signal PGOOD : STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others => '0');
+ signal PGOOD_S : STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others => '0');
+ signal SYSEN : STD_LOGIC := '0';
+ signal SYSEN_S : STD_LOGIC := '0';
+ signal SYSGOOD_BUF : STD_LOGIC := '0';
+
+ --Sequencer State Machine
+ type state_type is (idleon,shifton,waitpgood,waiten,idleoff,shiftoff,waitoff);
+ signal state : state_type := idleoff;
+ signal ERR : STD_LOGIC := '0';
+ signal err_msg : STD_LOGIC_VECTOR (15 downto 0) := (others => '1');
+ constant all_on : STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others=>'1');
+ constant all_off : STD_LOGIC_VECTOR (rail_size-1 downto 0) := (others =>'0');
+
+ --Clocks and timers
+ constant counter_size : integer := 20;
+ signal T_COUNT : UNSIGNED (counter_size-1 downto 0);
+ --t_max_wait is max delay from Enable assert to Pgood assert (200 ms assumption 4.125MHz clk)
+ constant t_max_wait : UNSIGNED (counter_size-1 downto 0) := TO_UNSIGNED(825000,counter_size);
+ --t_delay is delay from Pgood assert to next Enable assert (1ms assumption 4.125MHz clk)
+ constant t_delay : UNSIGNED (counter_size-1 downto 0) := TO_UNSIGNED(4125,counter_size);
+
+ --i2c signals
+ signal i2c_read_req : STD_LOGIC;
+ signal i2c_data_to_master : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
+ signal i2c_data_from_master : STD_LOGIC_VECTOR(7 downto 0);
+ signal i2c_data_valid : STD_LOGIC;
+ signal i2c_rst : STD_LOGIC := '0';
+ signal i2c_reg_cur : UNSIGNED(7 downto 0) := "00000000";
+ constant i2c_addr : STD_LOGIC_VECTOR (6 downto 0) := "0110001";
+ constant i2c_pg_reg_addr1 : UNSIGNED (7 downto 0) := "00000001";
+ constant i2c_pg_reg_addr2 : UNSIGNED (7 downto 0) := i2c_pg_reg_addr1 + 1;
+ constant i2c_status_reg_addr : UNSIGNED (7 downto 0) := i2c_pg_reg_addr2 + 1;
+
+
+begin
+
+
+--I2C device
+I2C_SLAVE: entity work.I2C_slave generic map(i2c_addr) port map(
+ 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
+ process (CLK_IN)
+ begin
+ if (rising_edge(CLK_IN)) then
+ --return high byte with any memory address, loop on any consecutive reads
+ if i2c_data_valid = '1' then
+ i2c_reg_cur <= unsigned(i2c_data_from_master);
+ elsif i2c_read_req = '1' then
+ i2c_reg_cur <= i2c_reg_cur + 1;
+ end if;
+
+ case i2c_reg_cur is
+ when i2c_pg_reg_addr1 =>
+ i2c_data_to_master <= err_msg(15 downto 8);
+ when i2c_pg_reg_addr2 =>
+ i2c_data_to_master <= err_msg(7 downto 0);
+ when i2c_status_reg_addr =>
+ i2c_data_to_master <= "000000" & SYSEN & SYSGOOD_BUF;
+ when others =>
+ i2c_data_to_master <= "00000000";
+ end case;
+ end if;
+ end process;
+
+-- Power Sequencer state machine
+ process (CLK_IN)
+ begin
+ if rising_edge(CLK_IN) then
+
+
+ -- 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 is
+ when idleoff=>
+ --Only leave idle off if system enable active and no error
+ if ERR = '1' then
+ state <= idleoff;
+ elsif SYSEN = '1' then
+ state <= shifton;
+ else
+ state <= idleoff;
+ end if;
+ when shifton=>
+ -- enable next power rail, reset counter, wait for pgood
+ EN_BUF(rail_size-1 downto 1) <= EN_BUF(rail_size-2 downto 0);
+ EN_BUF(0) <= '1';
+ T_COUNT <= (others=>'0');
+ state <= waitpgood;
+ when waitpgood=>
+ -- Wait for enabled power rail's PGOOD, after time with no pgood, error
+ if T_COUNT > t_max_wait then
+ ERR <= '1';
+ err_msg <= (others =>'0');
+ err_msg(rail_size-1 downto 0) <= EN_BUF and PGOOD;
+ state <= shiftoff;
+
+ elsif (EN_BUF and PGOOD) = all_on then
+ state <=idleon;
+
+ elsif ((EN_BUF and PGOOD) = EN_BUF) then
+ T_COUNT <= (others => '0');
+ state <= waiten;
+ else
+ state <= waitpgood;
+ end if;
+ -- delay between last pgood and next enable
+ when waiten=>
+ if T_COUNT > t_delay then
+ T_COUNT <= (others => '0');
+ state <= shifton;
+
+ else
+ state <= waiten;
+ end if;
+
+ -- stay in idle on unless power rail goes down (error) or system enable removed
+ when idleon=>
+ SYSGOOD_BUF <= '1';
+ if (not(PGOOD = all_on)) then
+ ERR <= '1';
+ err_msg <= (others =>'0');
+ err_msg(rail_size-1 downto 0) <= PGOOD;
+ end if;
+ if ((SYSEN = '0') or (ERR = '1')) then
+ SYSGOOD_BUF <= '0';
+ state <= shiftoff;
+
+ else
+ state <= idleon;
+ end if;
+ -- Turn off enable for next power rail
+ when shiftoff=>
+ EN_BUF(rail_size-2 downto 0) <= EN_BUF(rail_size-1 downto 1);
+ EN_BUF(rail_size-1) <= '0';
+ if(EN_BUF=all_off) then
+ state <= idleoff;
+
+ else
+ T_COUNT <= (others => '0');
+ state <= waitoff;
+ end if;
+ -- in controlled shutdown, delay between disabling power rails
+ when waitoff=>
+ if ERR = '1' then
+ state <= shiftoff;
+ --LED_BUF <= "10";
+ elsif T_COUNT > t_delay then
+ state <= shiftoff;
+ --LED_BUF <= "10";
+ else
+ state <= waitoff;
+ end if;
+ end case;
+ end if;
+ end process;
+
+
+-- Output enable buffer to pins
+ EN <= not(EN_BUF);
+ i2c_rst <= '0';
+ SYSGOOD <=SYSGOOD_BUF;
+
+
+end Behavioral;
+
diff --git a/Romulus_CPLD_TOP.vhd b/Romulus_CPLD_TOP.vhd
new file mode 100644
index 0000000..f797f9e
--- /dev/null
+++ b/Romulus_CPLD_TOP.vhd
@@ -0,0 +1,555 @@
+library IEEE;
+use IEEE.numeric_std.ALL;
+use IEEE.STD_LOGIC_1164.ALL;
+library machxo2;
+use machxo2.all;
+
+entity Romulus_CPLD_TOP is
+ Port ( SYSEN : in STD_LOGIC;
+ SYSGOOD: out STD_LOGIC := '0';
+ DEBUG_IN: in STD_LOGIC;
+
+ --DD1 temp fix for VCS overcurrent bug
+ SEQ_CONT: in STD_LOGIC;
+
+
+ --Enable outputs
+ VDDA_EN: out STD_LOGIC := '0';
+ VDDB_EN: out STD_LOGIC := '0';
+ VCSA_EN: out STD_LOGIC := '0';
+ VCSB_EN: out STD_LOGIC := '0';
+ VDNA_EN: out STD_LOGIC := '0';
+ VDNB_EN: out STD_LOGIC := '0';
+ VIOA_EN: out STD_LOGIC := '0';
+ VIOB_EN: out STD_LOGIC := '0';
+ VPPAB_EN: out STD_LOGIC := '0';
+ VPPCD_EN: out STD_LOGIC := '0';
+ VDDRAB_EN: out STD_LOGIC := '0';
+ VTTAB_EN: out STD_LOGIC := '0';
+ VDDRCD_EN: out STD_LOGIC := '0';
+ VTTCD_EN: out STD_LOGIC := '0';
+ AVDD_EN: out STD_LOGIC := '0';
+ MISCIO_EN: out STD_LOGIC := '0';
+ ATX_EN: out STD_LOGIC := '1';
+
+ --Power Good inputs
+ VDDA_PG: in STD_LOGIC;
+ VDDB_PG: in STD_LOGIC;
+ VCSA_PG: in STD_LOGIC;
+ VCSB_PG: in STD_LOGIC;
+ VDNA_PG: in STD_LOGIC;
+ VDNB_PG: in STD_LOGIC;
+ VIOA_PG: in STD_LOGIC;
+ VIOB_PG: in STD_LOGIC;
+ VPPAB_PG: in STD_LOGIC;
+ VPPCD_PG: in STD_LOGIC;
+ VDDRAB_PG: in STD_LOGIC;
+ VDDRCD_PG: in STD_LOGIC;
+ AVDD_PG: in STD_LOGIC;
+ MISCIO_PG: in STD_LOGIC;
+ ATX_PG: in STD_LOGIC;
+ BMC_VR_PG: in STD_LOGIC;
+
+ --i2c
+ SCL: inout STD_LOGIC;
+ SDA: inout STD_LOGIC;
+
+ --CLK_IN: in STD_LOGIC;
+
+ --Second CPU Present Detection
+ CPUB_PRESENT_N: in STD_LOGIC;
+ CPUB_CLK_OEA: out STD_LOGIC;
+ CPUB_CLK_OEB: out STD_LOGIC;
+
+ -- Resets
+ LPC_RST: out STD_LOGIC := '0';
+ BMC_SOFTWARE_PG: in STD_LOGIC;
+ BMC_RST: out STD_LOGIC := '0';
+ FAN_RST: out STD_LOGIC := '0';
+ USBHUB_RST: out STD_LOGIC := '0';
+ CPU_STBY_RST: out STD_LOGIC := '0';
+
+ -- Reserved for Future Use
+ DUAL_5V_CTRL: out STD_LOGIC := '0';
+ --DUAL_5V_CTRL: in STD_LOGIC;
+ WINDOW_OPEN_N: out STD_LOGIC := '0'
+ );
+
+
+end Romulus_CPLD_TOP;
+
+architecture Behavioral of Romulus_CPLD_TOP is
+ --FUTURE update version
+ constant cpld_version : STD_LOGIC_VECTOR (7 downto 0) := "00000101";
+ constant rail_size : integer := 15;
+ signal EN_BUF : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others => '0');
+ signal PG_BUF : STD_LOGIC_VECTOR(rail_size-1 downto 0);
+ signal SYSGOOD_BUF : STD_LOGIC;
+-- signal CLK_DIV : STD_LOGIC;
+-- signal CLK_REG : UNSIGNED(2 downto 0) := "000";
+ signal CLK_IN: STD_LOGIC;
+ signal stdby_sed: STD_LOGIC;
+ signal SYSEN_BUF: STD_LOGIC;
+-- signal DEBUG_BUF: STD_LOGIC;
+ constant railarray_0 : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others =>'0');
+ constant railarray_1 : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others =>'1');
+
+ -- synchronizing signals
+ signal PG_S1 : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others => '0');
+ signal PG_S2 : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others => '0');
+ signal SYSEN_S1: STD_LOGIC := '0';
+ signal SYSEN_S2: STD_LOGIC := '0';
+ signal SEQ_S1: STD_LOGIC := '1';
+ signal SEQ_S2: STD_LOGIC := '1';
+
+ -- Timer (Watchdog and Delay) signals
+ signal DELAY_DONE : STD_LOGIC_VECTOR(rail_size-1 downto 0) := (others => '0');
+ signal W_COUNT : UNSIGNED(23 downto 0) := (others=> '0');
+ signal D_COUNT : UNSIGNED(16 downto 0) := (others=> '0');
+ -- 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
+ signal WAIT_ERR : STD_LOGIC := '0';
+ signal OPERATION_ERR : STD_LOGIC := '0';
+ signal ERR_FOUND :STD_LOGIC := '0';
+-- signal FIRST_DELAY : STD_LOGIC := '1';
+ signal CLEAR_ERR : STD_LOGIC := '0';
+
+ --i2c signals
+ signal i2c_read_req : STD_LOGIC;
+ signal i2c_data_to_master : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
+ signal i2c_data_from_master : STD_LOGIC_VECTOR(7 downto 0);
+ signal i2c_data_valid : STD_LOGIC;
+ signal i2c_rst : STD_LOGIC := '0';
+ signal i2c_reg_cur : UNSIGNED(7 downto 0) := "00000000";
+ constant i2c_addr : STD_LOGIC_VECTOR (6 downto 0) := "0110001";
+ constant i2c_clr_err_addr : UNSIGNED (7 downto 0) := "00000011";
+ constant i2c_pg_reg_addr1 : UNSIGNED (7 downto 0) := "00000101";
+ constant i2c_pg_reg_addr2 : UNSIGNED (7 downto 0) := i2c_pg_reg_addr1 + 1;
+ constant i2c_status_reg_addr : UNSIGNED (7 downto 0) := i2c_pg_reg_addr2 + 1;
+ constant i2c_version_reg_addr: UNSIGNED (7 downto 0) := "00000000";
+ signal i2c_pg_reg : STD_LOGIC_VECTOR(15 downto 0) := (others=>'0');
+ signal i2c_clr_err : STD_LOGIC := '0';
+
+ component OSCH
+ -- synthesis translate_off
+ generic (NOM_FREQ: string := "4.16");
+ -- synthesis translate_on
+ PORT ( STDBY : in STD_LOGIC;
+ OSC: out STD_LOGIC;
+ SEDSTDBY: out STD_LOGIC);
+ end component;
+ attribute NOM_FREQ : string;
+ attribute NOM_FREQ of OSC1 : label is "4.16";
+
+
+
+begin
+ OSC1: OSCH
+ -- synthesis translate_off
+ generic map( NOM_FREQ => "4.16")
+ -- synthesis translate_on
+ port map ( STDBY => '0', 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_Romulus
+ -- 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: entity work.I2C_slave generic map(i2c_addr) port map(
+ SCL, SDA, CLK_IN, i2c_rst,
+ i2c_read_req,i2c_data_to_master,
+ i2c_data_valid,i2c_data_from_master);
+
+ i2c_rst <= '0';
+
+--Handle I2C
+ --2 8-bit registers with PGOOD state on error
+ process (CLK_IN)
+ begin
+ if (rising_edge(CLK_IN)) then
+ i2c_clr_err <= '0';
+ if i2c_data_valid = '1' then
+ -- data from master is register to be read
+ i2c_reg_cur <= unsigned(i2c_data_from_master);
+
+ --pulse clear err signal if i2c master reads register 0x03
+ if(unsigned(i2c_data_from_master) = i2c_clr_err_addr) then
+ i2c_clr_err <= '1';
+ end if;
+ elsif i2c_read_req = '1' then
+ i2c_reg_cur <= i2c_reg_cur + 1;
+ end if;
+
+ case i2c_reg_cur is
+ when i2c_clr_err_addr =>
+ i2c_data_to_master <= "11111111";
+ when i2c_pg_reg_addr1 =>
+ i2c_data_to_master <= i2c_pg_reg(15 downto 8);
+ when i2c_pg_reg_addr2 =>
+ i2c_data_to_master <= i2c_pg_reg(7 downto 0);
+ when i2c_status_reg_addr =>
+ --FUTURE add CPU1 Present detect
+ i2c_data_to_master <= "000" & WAIT_ERR & OPERATION_ERR & ERR_FOUND & SYSEN_BUF & SYSGOOD_BUF;
+ when i2c_version_reg_addr =>
+ i2c_data_to_master <= cpld_version;
+ when others =>
+ i2c_data_to_master <= "00000000";
+ end case;
+ end if;
+ end process;
+
+ process (CLK_IN)
+ begin
+ if (rising_edge(CLK_IN)) then
+ 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') then
+ WAIT_ERR <= '0';
+ OPERATION_ERR <= '0';
+ ERR_FOUND <= '0';
+ W_COUNT <= (others => '0');
+ D_COUNT <= (others => '0');
+ elsif(SYSEN_S2 = '0' or ERR_FOUND = '1') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= (others => '0');
+ DELAY_DONE <= (others => '0');
+ elsif (PG_S2(0) = '1' and EN_BUF(0) = '1' and DELAY_DONE(0) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(0) <= '1';
+ end if;
+ elsif (PG_S2(1) = '1' and EN_BUF(1) = '1' and DELAY_DONE(1) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(1) <= '1';
+ end if;
+ elsif (PG_S2(2) = '1' and EN_BUF(2) = '1' and DELAY_DONE(2) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(2) <= '1';
+ end if;
+ elsif (PG_S2(3) = '1' and EN_BUF(3) = '1' and DELAY_DONE(3) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(3) <= '1';
+ end if;
+ elsif (PG_S2(4) = '1' and EN_BUF(4) = '1' and DELAY_DONE(4) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(4) <= '1';
+ end if;
+ elsif (PG_S2(5) = '1' and EN_BUF(5) = '1' and DELAY_DONE(5) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(5) <= '1';
+ end if;
+ elsif (PG_S2(6) = '1' and EN_BUF(6) = '1' and DELAY_DONE(6) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(6) <= '1';
+ end if;
+ elsif (PG_S2(7) = '1' and EN_BUF(7) = '1' and DELAY_DONE(7) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(7) <= '1';
+ end if;
+ elsif (PG_S2(8) = '1' and EN_BUF(8) = '1' and DELAY_DONE(8) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(8) <= '1';
+ end if;
+ elsif (PG_S2(9) = '1' and EN_BUF(9) = '1' and DELAY_DONE(9) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(9) <= '1';
+ end if;
+ elsif (PG_S2(10) = '1' and EN_BUF(10) = '1' and DELAY_DONE(10) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(10) <= '1';
+ end if;
+ elsif (PG_S2(11) = '1' and EN_BUF(11) = '1' and DELAY_DONE(11) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(11) <= '1';
+ end if;
+ elsif (PG_S2(12) = '1' and EN_BUF(12) = '1' and DELAY_DONE(12) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(12) <= '1';
+ end if;
+ elsif (PG_S2(13) = '1' and EN_BUF(13) = '1' and DELAY_DONE(13) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(13) <= '1';
+ end if;
+ elsif (PG_S2(14) = '1' and EN_BUF(14) = '1' and DELAY_DONE(14) = '0') then
+ W_COUNT <= (others => '0');
+ D_COUNT <= D_COUNT+1;
+ if (D_COUNT(16) = '1') then
+ D_COUNT <= (others => '0');
+ DELAY_DONE(14) <= '1';
+ end if;
+
+ -- Error Checks
+ -- Check time between Enables going high and PGOODs arriving. Error out after 100ms
+ elsif (PG_S2(0) = '0' and EN_BUF(0) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if (W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(1) = '0' and EN_BUF(1) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if (W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(2) = '0' and EN_BUF(2) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(3) = '0' and EN_BUF(3) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(4) = '0' and EN_BUF(4) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(5) = '0' and EN_BUF(5) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(6) = '0' and EN_BUF(6) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(7) = '0' and EN_BUF(7) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(8) = '0' and EN_BUF(8) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(9) = '0' and EN_BUF(9) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(10) = '0' and EN_BUF(10) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(11) = '0' and EN_BUF(11) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(12) = '0' and EN_BUF(12) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(13) = '0' and EN_BUF(13) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ elsif (PG_S2(14) = '0' and EN_BUF(14) = '1') then
+
+ W_COUNT <= W_COUNT+1;
+ if ( W_COUNT(23) = '1') then
+ W_COUNT <= (others => '0');
+ WAIT_ERR <= '1';
+ end if;
+ end if;
+
+ if(not (DELAY_DONE and not PG_S2) /= railarray_1) then
+ OPERATION_ERR <= '1';
+ end if;
+
+ if ((WAIT_ERR or OPERATION_ERR) = '1' and CLEAR_ERR = '0') then
+ ERR_FOUND <= '1';
+ else
+ i2c_pg_reg(14 downto 0) <= PG_S2(14 downto 0);
+ end if;
+ end if;
+ end process;
+
+
+ --Assign Ports to Enables
+ ATX_EN <= not EN_BUF(0);
+ MISCIO_EN <= EN_BUF(1);
+ VDNA_EN <= EN_BUF(2);
+ VDNB_EN <= EN_BUF(3) and not CPUB_PRESENT_N;
+ AVDD_EN <= EN_BUF(4);
+ VIOA_EN <= EN_BUF(5);
+ VIOB_EN <= EN_BUF(6) and not CPUB_PRESENT_N;
+ VDDA_EN <= EN_BUF(7);
+ VDDB_EN <= EN_BUF(8) and not CPUB_PRESENT_N;
+ VCSA_EN <= EN_BUF(9);
+ VCSB_EN <= EN_BUF(10) and not CPUB_PRESENT_N;
+ VPPAB_EN <= EN_BUF(11);
+ VPPCD_EN <= EN_BUF(12) and not CPUB_PRESENT_N;
+ VDDRAB_EN <= EN_BUF(13);
+ VTTAB_EN <= EN_BUF(13);
+ VDDRCD_EN <= EN_BUF(14) and not CPUB_PRESENT_N;
+ VTTCD_EN <= EN_BUF(14) and not CPUB_PRESENT_N;
+
+ -- Assign Ports to PGood buffer
+ PG_BUF(0) <= ATX_PG;
+ PG_BUF(1) <= MISCIO_PG;
+ PG_BUF(2) <= VDNA_PG;
+ PG_BUF(3) <= VDNB_PG or (CPUB_PRESENT_N and EN_BUF(3));
+ PG_BUF(4) <= AVDD_PG;
+ PG_BUF(5) <= VIOA_PG;
+ PG_BUF(6) <= VIOB_PG or (CPUB_PRESENT_N and EN_BUF(6));
+ PG_BUF(7) <= VDDA_PG;
+ PG_BUF(8) <= VDDB_PG or (CPUB_PRESENT_N and EN_BUF(8));
+ PG_BUF(9) <= VCSA_PG;
+ PG_BUF(10) <= VCSB_PG or (CPUB_PRESENT_N and EN_BUF(10));
+ PG_BUF(11) <= VPPAB_PG;
+ PG_BUF(12) <= VPPCD_PG or (CPUB_PRESENT_N and EN_BUF(12));
+ PG_BUF(13) <= VDDRAB_PG;
+ PG_BUF(14) <= VDDRCD_PG or (CPUB_PRESENT_N and 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
+ EN_BUF(0) <= (SYSEN_S2 or PG_S2(1)) and not ERR_FOUND;
+ EN_BUF(1) <= ((SYSEN_S2 and DELAY_DONE(0)) or PG_S2(2)) and not ERR_FOUND;
+ EN_BUF(2) <= ((SYSEN_S2 and DELAY_DONE(1)) or PG_S2(3)) and not ERR_FOUND;
+ EN_BUF(3) <= ((SYSEN_S2 and DELAY_DONE(2)) or PG_S2(4)) and not ERR_FOUND;
+ EN_BUF(4) <= ((SYSEN_S2 and DELAY_DONE(3)) or PG_S2(5)) and not ERR_FOUND;
+ EN_BUF(5) <= ((SYSEN_S2 and DELAY_DONE(4)) or PG_S2(6)) and not ERR_FOUND;
+ EN_BUF(6) <= ((SYSEN_S2 and DELAY_DONE(5)) or PG_S2(7)) and not ERR_FOUND;
+ EN_BUF(7) <= ((SYSEN_S2 and DELAY_DONE(6)) or PG_S2(8)) and not ERR_FOUND;
+ EN_BUF(8) <= ((SYSEN_S2 and DELAY_DONE(7)) or PG_S2(9)) and not ERR_FOUND;
+ EN_BUF(9) <= ((not SEQ_S2 and SYSEN_S2 and DELAY_DONE(8)) or PG_S2(10)) and not ERR_FOUND;
+ EN_BUF(10) <= ((SYSEN_S2 and DELAY_DONE(9)) or PG_S2(11)) and not ERR_FOUND;
+ EN_BUF(11) <= ((SYSEN_S2 and DELAY_DONE(10)) or PG_S2(12)) and not ERR_FOUND;
+ EN_BUF(12) <= ((SYSEN_S2 and DELAY_DONE(11)) or PG_S2(13)) and not ERR_FOUND;
+ EN_BUF(13) <= ((SYSEN_S2 and DELAY_DONE(12)) or PG_S2(14)) and not ERR_FOUND;
+ EN_BUF(14) <= (SYSEN_S2 and DELAY_DONE(13)) and not ERR_FOUND;
+
+ --ERR state reset
+ CLEAR_ERR <= i2c_clr_err;
+
+
+ -- CPUB clk enables
+ CPUB_CLK_OEA <= not CPUB_PRESENT_N;
+ CPUB_CLK_OEB <= not CPUB_PRESENT_N;
+
+ -- System PWRGOOD
+ SYSGOOD_BUF <= DELAY_DONE(14);
+ SYSGOOD <= SYSGOOD_BUF and BMC_SOFTWARE_PG;
+ LPC_RST <= SYSGOOD_BUF;
+
+ -- CPU Reset
+ CPU_STBY_RST <= EN_BUF(0);
+
+ -- BMC RESETs
+ BMC_RST <= BMC_VR_PG;
+ USBHUB_RST <= SYSGOOD_BUF and BMC_SOFTWARE_PG;
+ FAN_RST <= not BMC_VR_PG;
+
+ -- DEBUG_IN override allows non-BMC control of CPLD
+ SYSEN_BUF <= SYSEN or not DEBUG_IN;
+ --SYSEN_BUF <= not DEBUG_IN;
+
+
+
+
+end Behavioral;
+
diff --git a/txt_util.vhd b/txt_util.vhd
new file mode 100644
index 0000000..a4c9ee5
--- /dev/null
+++ b/txt_util.vhd
@@ -0,0 +1,582 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use std.textio.all;
+
+
+package txt_util is
+
+ -- prints a message to the screen
+ procedure print(text: string);
+
+ -- prints the message when active
+ -- useful for debug switches
+ procedure print(active: boolean; text: string);
+
+ -- converts std_logic into a character
+ function chr(sl: std_logic) return character;
+
+ -- converts std_logic into a string (1 to 1)
+ function str(sl: std_logic) return string;
+
+ -- converts std_logic_vector into a string (binary base)
+ function str(slv: std_logic_vector) return string;
+
+ -- converts boolean into a string
+ function str(b: boolean) return string;
+
+ -- converts an integer into a single character
+ -- (can also be used for hex conversion and other bases)
+ function chr(int: integer) return character;
+
+ -- converts integer into string using specified base
+ function str(int: integer; base: integer) return string;
+
+ -- converts integer to string, using base 10
+ function str(int: integer) return string;
+
+ -- convert std_logic_vector into a string in hex format
+ function hstr(slv: std_logic_vector) return string;
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+ -- convert a character to upper case
+ function to_upper(c: character) return character;
+
+ -- convert a character to lower case
+ function to_lower(c: character) return character;
+
+ -- convert a string to upper case
+ function to_upper(s: string) return string;
+
+ -- convert a string to lower case
+ function to_lower(s: string) return string;
+
+
+
+ -- functions to convert strings into other formats
+ --------------------------------------------------
+
+ -- converts a character into std_logic
+ function to_std_logic(c: character) return std_logic;
+
+ -- converts a string into std_logic_vector
+ function to_std_logic_vector(s: string) return std_logic_vector;
+
+
+
+ -- file I/O
+ -----------
+
+ -- read variable length string from input file
+ procedure str_read(file in_file: TEXT;
+ res_string: out string);
+
+ -- print string to a file and start new line
+ procedure print(file out_file: TEXT;
+ new_string: in string);
+
+ -- print character to a file and start new line
+ procedure print(file out_file: TEXT;
+ char: in character);
+
+end txt_util;
+
+
+
+
+package body txt_util is
+
+
+
+
+ -- prints text to the screen
+
+ procedure print(text: string) is
+ variable msg_line: line;
+ begin
+ write(msg_line, text);
+ writeline(output, msg_line);
+ end print;
+
+
+
+
+ -- prints text to the screen when active
+
+ procedure print(active: boolean; text: string) is
+ begin
+ if active then
+ print(text);
+ end if;
+ end print;
+
+
+ -- converts std_logic into a character
+
+ function chr(sl: std_logic) return character is
+ variable c: character;
+ begin
+ case sl is
+ when 'U' => c:= 'U';
+ when 'X' => c:= 'X';
+ when '0' => c:= '0';
+ when '1' => c:= '1';
+ when 'Z' => c:= 'Z';
+ when 'W' => c:= 'W';
+ when 'L' => c:= 'L';
+ when 'H' => c:= 'H';
+ when '-' => c:= '-';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- converts std_logic into a string (1 to 1)
+
+ function str(sl: std_logic) return string is
+ variable s: string(1 to 1);
+ begin
+ s(1) := chr(sl);
+ return s;
+ end str;
+
+
+
+ -- converts std_logic_vector into a string (binary base)
+ -- (this also takes care of the fact that the range of
+ -- a string is natural while a std_logic_vector may
+ -- have an integer range)
+
+ function str(slv: std_logic_vector) return string is
+ variable result : string (1 to slv'length);
+ variable r : integer;
+ begin
+ r := 1;
+ for i in slv'range loop
+ result(r) := chr(slv(i));
+ r := r + 1;
+ end loop;
+ return result;
+ end str;
+
+
+ function str(b: boolean) return string is
+
+ begin
+ if b then
+ return "true";
+ else
+ return "false";
+ end if;
+ end str;
+
+
+ -- converts an integer into a character
+ -- for 0 to 9 the obvious mapping is used, higher
+ -- values are mapped to the characters A-Z
+ -- (this is usefull for systems with base > 10)
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function chr(int: integer) return character is
+ variable c: character;
+ begin
+ case int is
+ when 0 => c := '0';
+ when 1 => c := '1';
+ when 2 => c := '2';
+ when 3 => c := '3';
+ when 4 => c := '4';
+ when 5 => c := '5';
+ when 6 => c := '6';
+ when 7 => c := '7';
+ when 8 => c := '8';
+ when 9 => c := '9';
+ when 10 => c := 'A';
+ when 11 => c := 'B';
+ when 12 => c := 'C';
+ when 13 => c := 'D';
+ when 14 => c := 'E';
+ when 15 => c := 'F';
+ when 16 => c := 'G';
+ when 17 => c := 'H';
+ when 18 => c := 'I';
+ when 19 => c := 'J';
+ when 20 => c := 'K';
+ when 21 => c := 'L';
+ when 22 => c := 'M';
+ when 23 => c := 'N';
+ when 24 => c := 'O';
+ when 25 => c := 'P';
+ when 26 => c := 'Q';
+ when 27 => c := 'R';
+ when 28 => c := 'S';
+ when 29 => c := 'T';
+ when 30 => c := 'U';
+ when 31 => c := 'V';
+ when 32 => c := 'W';
+ when 33 => c := 'X';
+ when 34 => c := 'Y';
+ when 35 => c := 'Z';
+ when others => c := '?';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- convert integer to string using specified base
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function str(int: integer; base: integer) return string is
+
+ variable temp: string(1 to 10);
+ variable num: integer;
+ variable abs_int: integer;
+ variable len: integer := 1;
+ variable power: integer := 1;
+
+ begin
+
+ -- bug fix for negative numbers
+ abs_int := abs(int);
+
+ num := abs_int;
+
+ while num >= base loop -- Determine how many
+ len := len + 1; -- characters required
+ num := num / base; -- to represent the
+ end loop ; -- number.
+
+ for i in len downto 1 loop -- Convert the number to
+ temp(i) := chr(abs_int/power mod base); -- a string starting
+ power := power * base; -- with the right hand
+ end loop ; -- side.
+
+ -- return result and add sign if required
+ if int < 0 then
+ return '-'& temp(1 to len);
+ else
+ return temp(1 to len);
+ end if;
+
+ end str;
+
+
+ -- convert integer to string, using base 10
+ function str(int: integer) return string is
+
+ begin
+
+ return str(int, 10) ;
+
+ end str;
+
+
+
+ -- converts a std_logic_vector into a hex string.
+ function hstr(slv: std_logic_vector) return string is
+ variable hexlen: integer;
+ variable longslv : std_logic_vector(67 downto 0) := (others => '0');
+ variable hex : string(1 to 16);
+ variable fourbit : std_logic_vector(3 downto 0);
+ begin
+ hexlen := (slv'left+1)/4;
+ if (slv'left+1) mod 4 /= 0 then
+ hexlen := hexlen + 1;
+ end if;
+ longslv(slv'left downto 0) := slv;
+ for i in (hexlen -1) downto 0 loop
+ fourbit := longslv(((i*4)+3) downto (i*4));
+ case fourbit is
+ when "0000" => hex(hexlen -I) := '0';
+ when "0001" => hex(hexlen -I) := '1';
+ when "0010" => hex(hexlen -I) := '2';
+ when "0011" => hex(hexlen -I) := '3';
+ when "0100" => hex(hexlen -I) := '4';
+ when "0101" => hex(hexlen -I) := '5';
+ when "0110" => hex(hexlen -I) := '6';
+ when "0111" => hex(hexlen -I) := '7';
+ when "1000" => hex(hexlen -I) := '8';
+ when "1001" => hex(hexlen -I) := '9';
+ when "1010" => hex(hexlen -I) := 'A';
+ when "1011" => hex(hexlen -I) := 'B';
+ when "1100" => hex(hexlen -I) := 'C';
+ when "1101" => hex(hexlen -I) := 'D';
+ when "1110" => hex(hexlen -I) := 'E';
+ when "1111" => hex(hexlen -I) := 'F';
+ when "ZZZZ" => hex(hexlen -I) := 'z';
+ when "UUUU" => hex(hexlen -I) := 'u';
+ when "XXXX" => hex(hexlen -I) := 'x';
+ when others => hex(hexlen -I) := '?';
+ end case;
+ end loop;
+ return hex(1 to hexlen);
+ end hstr;
+
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+
+ -- convert a character to upper case
+
+ function to_upper(c: character) return character is
+
+ variable u: character;
+
+ begin
+
+ case c is
+ when 'a' => u := 'A';
+ when 'b' => u := 'B';
+ when 'c' => u := 'C';
+ when 'd' => u := 'D';
+ when 'e' => u := 'E';
+ when 'f' => u := 'F';
+ when 'g' => u := 'G';
+ when 'h' => u := 'H';
+ when 'i' => u := 'I';
+ when 'j' => u := 'J';
+ when 'k' => u := 'K';
+ when 'l' => u := 'L';
+ when 'm' => u := 'M';
+ when 'n' => u := 'N';
+ when 'o' => u := 'O';
+ when 'p' => u := 'P';
+ when 'q' => u := 'Q';
+ when 'r' => u := 'R';
+ when 's' => u := 'S';
+ when 't' => u := 'T';
+ when 'u' => u := 'U';
+ when 'v' => u := 'V';
+ when 'w' => u := 'W';
+ when 'x' => u := 'X';
+ when 'y' => u := 'Y';
+ when 'z' => u := 'Z';
+ when others => u := c;
+ end case;
+
+ return u;
+
+ end to_upper;
+
+
+ -- convert a character to lower case
+
+ function to_lower(c: character) return character is
+
+ variable l: character;
+
+ begin
+
+ case c is
+ when 'A' => l := 'a';
+ when 'B' => l := 'b';
+ when 'C' => l := 'c';
+ when 'D' => l := 'd';
+ when 'E' => l := 'e';
+ when 'F' => l := 'f';
+ when 'G' => l := 'g';
+ when 'H' => l := 'h';
+ when 'I' => l := 'i';
+ when 'J' => l := 'j';
+ when 'K' => l := 'k';
+ when 'L' => l := 'l';
+ when 'M' => l := 'm';
+ when 'N' => l := 'n';
+ when 'O' => l := 'o';
+ when 'P' => l := 'p';
+ when 'Q' => l := 'q';
+ when 'R' => l := 'r';
+ when 'S' => l := 's';
+ when 'T' => l := 't';
+ when 'U' => l := 'u';
+ when 'V' => l := 'v';
+ when 'W' => l := 'w';
+ when 'X' => l := 'x';
+ when 'Y' => l := 'y';
+ when 'Z' => l := 'z';
+ when others => l := c;
+ end case;
+
+ return l;
+
+ end to_lower;
+
+
+
+ -- convert a string to upper case
+
+ function to_upper(s: string) return string is
+
+ variable uppercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ uppercase(i):= to_upper(s(i));
+ end loop;
+ return uppercase;
+
+ end to_upper;
+
+
+
+ -- convert a string to lower case
+
+ function to_lower(s: string) return string is
+
+ variable lowercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ lowercase(i):= to_lower(s(i));
+ end loop;
+ return lowercase;
+
+ end to_lower;
+
+
+
+-- functions to convert strings into other types
+
+
+-- converts a character into a std_logic
+
+function to_std_logic(c: character) return std_logic is
+ variable sl: std_logic;
+ begin
+ case c is
+ when 'U' =>
+ sl := 'U';
+ when 'X' =>
+ sl := 'X';
+ when '0' =>
+ sl := '0';
+ when '1' =>
+ sl := '1';
+ when 'Z' =>
+ sl := 'Z';
+ when 'W' =>
+ sl := 'W';
+ when 'L' =>
+ sl := 'L';
+ when 'H' =>
+ sl := 'H';
+ when '-' =>
+ sl := '-';
+ when others =>
+ sl := 'X';
+ end case;
+ return sl;
+ end to_std_logic;
+
+
+-- converts a string into std_logic_vector
+
+function to_std_logic_vector(s: string) return std_logic_vector is
+ variable slv: std_logic_vector(s'high-s'low downto 0);
+ variable k: integer;
+begin
+ k := s'high-s'low;
+ for i in s'range loop
+ slv(k) := to_std_logic(s(i));
+ k := k - 1;
+ end loop;
+ return slv;
+end to_std_logic_vector;
+
+
+
+
+
+
+----------------
+-- file I/O --
+----------------
+
+
+
+-- read variable length string from input file
+
+procedure str_read(file in_file: TEXT;
+ res_string: out string) is
+
+ variable l: line;
+ variable c: character;
+ variable is_string: boolean;
+
+ begin
+
+ readline(in_file, l);
+ -- clear the contents of the result string
+ for i in res_string'range loop
+ res_string(i) := ' ';
+ end loop;
+ -- read all characters of the line, up to the length
+ -- of the results string
+ for i in res_string'range loop
+ read(l, c, is_string);
+ res_string(i) := c;
+ if not is_string then -- found end of line
+ exit;
+ end if;
+ end loop;
+
+end str_read;
+
+
+-- print string to a file
+procedure print(file out_file: TEXT;
+ new_string: in string) is
+
+ variable l: line;
+
+ begin
+
+ write(l, new_string);
+ writeline(out_file, l);
+
+end print;
+
+
+-- print character to a file and start new line
+procedure print(file out_file: TEXT;
+ char: in character) is
+
+ variable l: line;
+
+ begin
+
+ write(l, char);
+ writeline(out_file, l);
+
+end print;
+
+
+
+-- appends contents of a string to a file until line feed occurs
+-- (LF is considered to be the end of the string)
+
+procedure str_write(file out_file: TEXT;
+ new_string: in string) is
+ begin
+
+ for i in new_string'range loop
+ print(out_file, new_string(i));
+ if new_string(i) = LF then -- end of string
+ exit;
+ end if;
+ end loop;
+
+end str_write;
+
+
+
+
+end txt_util; \ No newline at end of file
OpenPOWER on IntegriCloud