From 5d8ea0866a80d3ccdeba6037ca87e7070d322c01 Mon Sep 17 00:00:00 2001 From: IBM Date: Fri, 29 Sep 2017 06:00:00 -0600 Subject: Initial import of Romulus support files --- I2C_slave.vhd | 270 ++++++++++++++++++++++++ PWRseq_Romulus.vhd | 196 +++++++++++++++++ Romulus_CPLD_TOP.vhd | 555 ++++++++++++++++++++++++++++++++++++++++++++++++ txt_util.vhd | 582 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1603 insertions(+) create mode 100644 I2C_slave.vhd create mode 100644 PWRseq_Romulus.vhd create mode 100644 Romulus_CPLD_TOP.vhd create mode 100644 txt_util.vhd 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 -- cgit v1.2.1