📄 i2c.vhd
字号:
SHARED VARIABLE mast_mem : MemArray := (OTHERS=> 0); -- write pointer SHARED VARIABLE s_p : INTEGER RANGE 0 TO MemSize := 0; -- read pointer SHARED VARIABLE s_p_rd : INTEGER RANGE 0 TO MemSize := 0; SHARED VARIABLE m_p : INTEGER RANGE 0 TO MemSize := 0;----------------------------------------------------------------------------------------------------------------------------------------------------------------FUNCTIONS AND PROCEDURES------------------------------------------------------------------------------- PROCEDURE Drive( SIGNAL SDA_zd : INOUT std_logic; VARIABLE num : INOUT NATURAL ) IS BEGIN SDA_zd <= buff(num); --i := ((i-1)+8) MOD 8; num := (num+7) MOD 8; END Drive; PROCEDURE Drive_slave_addr( SIGNAL SDA_zd : INOUT std_logic; SIGNAL slave_addr : IN std_logic_vector(9 downto 0); VARIABLE num : INOUT NATURAL ) IS VARIABLE num_local : INTEGER := 0; BEGIN num_local := num - 1; -- only slave_addr(7 downto 0) are output IF num_local < 0 THEN -- B bit SDA_zd <= '1'; ELSE SDA_zd <= slave_addr(num_local); END IF; num := (num+7) MOD 8; END Drive_slave_addr; PROCEDURE Drive_slave( SIGNAL SDA_zd : INOUT std_logic; VARIABLE num : INOUT NATURAL ) IS VARIABLE tmp_buff : std_logic_vector(7 downto 0); BEGIN tmp_buff := to_slv(slv_mem(s_p_rd), 8); out_num := num; out_buff := tmp_buff; SDA_zd <= tmp_buff(num); --i := ((i-1)+8) MOD 8; IF num = 0 THEN s_p_rd := (s_p_rd +1) MOD (MemSize+1); END IF; num := (num+7) MOD 8; END Drive_slave; PROCEDURE Drive_rdy( SIGNAL rdy : INOUT std_logic; SIGNAL clk_cnt : IN INTEGER ) IS BEGIN IF clk_cnt = 8 THEN rdy <= '1'; ELSE rdy <= '0'; END IF; END Drive_rdy; PROCEDURE Store( VARIABLE Load_buf : INOUT std_logic_vector(7 downto 0); CONSTANT master : BOOLEAN-- SIGNAL load_addr_l : INOUT std_logic ) IS BEGIN IF master = TRUE THEN mast_mem(m_p) := to_nat(Load_buf); m_p := (m_p+1) MOD (MemSize+1); ELSE slv_mem(s_p) := to_nat(Load_buf); s_p := (s_p+1) MOD (MemSize+1); END IF; END Store; PROCEDURE SetSDA( SIGNAL SDA_zd : INOUT std_logic ) IS BEGIN IF next_req = '1' THEN -- prepare for RESTART SDA_zd <= '1'; ELSE -- prepare for STOP SDA_zd <= '0'; END IF; END SetSDA; -------------------------------------------------------------------------- -- PROCEDURE to select TC -------------------------------------------------------------------------- PROCEDURE Pick_TC ( VARIABLE ts_cnt : INOUT NATURAL RANGE 1 TO 30; VARIABLE tc_cnt : INOUT NATURAL RANGE 0 TO 30 ) IS BEGIN IF TC_cnt < tc(TS_cnt) THEN TC_cnt := TC_cnt+1; ELSE TC_cnt:=1; IF TS_cnt < 30 THEN TS_cnt := TS_cnt+1; ELSE -- end test WAIT; END IF; END IF; END PROCEDURE Pick_TC; --------------------------------------------------------------------------- --procedure to decode commands into specific MASTER/SLAVE command sequence --------------------------------------------------------------------------- PROCEDURE command_decode ( command : IN cmd_rec; VARIABLE current_time : IN TIME; SIGNAL buff : INOUT std_logic_vector(7 downto 0); SIGNAL end_of_write : INOUT std_logic; SIGNAL next_req : INOUT std_logic; SIGNAL load_rd_cnt : INOUT std_logic; SIGNAL rd_value : INOUT NATURAL; SIGNAL delay_value : INOUT time; SIGNAL en_sl_resp : INOUT std_logic; SIGNAL address_some_slave : INOUT BOOLEAN ) IS VARIABLE tmp :std_logic_vector(7 downto 0) := (OTHERS => '0'); VARIABLE tmp_time : TIME; VARIABLE i : NATURAL := 0; BEGIN IF command.cmd = idle AND (command.device_id(7 downto 1) = "all_dev" OR command.device_id = Device_id) THEN --IF my_bus = '1' THEN -- WAIT UNTIL rdy = '1' OR my_bus = '0';--AND rdy'EVENT; --END IF; tmp_time := NOW; next_req <= '0'; end_of_write <= '1'; en_sl_resp <= '1'; WAIT FOR (command.wtime - tmp_time);--current_time); END IF; IF command.device_id = Device_id THEN rd_value <= 1; delay_value <= 0 ns; next_req <= '0'; CASE command.cmd IS WHEN none => IF my_bus = '1' THEN WAIT UNTIL rdy = '1' OR my_bus = '0';--AND rdy'EVENT; END IF; next_req <= '1'; end_of_write <= '1'; IF my_bus = '1' THEN WAIT UNTIL rdy = '1' OR my_bus = '0';--AND rdy'EVENT; END IF; WHEN req_bus => IF my_bus = '1' OR busy = '0' THEN --IF my_bus = '1' THEN -- WAIT UNTIL rdy = '1' OR my_bus = '0';--AND rdy'EVENT; --END IF; tmp := to_slv(command.wr_byte,8); -- not HS mode request IF (tmp(7 downto 3) /= HS_MODE_C) THEN address_some_slave <= ( (tmp(7 downto 4)) /= "0000" AND (tmp(7 downto 4)) /= "1111" ); next_req <= '1'; IF HARD_MASTER_gen = TRUE THEN -- general call procedure buff <= "00000000"; ELSE buff <= to_slv(command.wr_byte,8); END IF; end_of_write <= '1'; load_rd_cnt <= '1', '0' AFTER 1 ns; rd_value <= 1;--command.rd_byte_num; -- HS mode request ELSIF HS_MODE_gen = TRUE THEN address_some_slave <= NOT( (buff(7 downto 4)) = "0000" OR (buff(7 downto 4)) = "1111" ); next_req <= '1'; buff <= MASTER_CODE_gen; end_of_write <= '0'; END IF; wait for command.wtime; WAIT UNTIL ((rdy = '1' AND rdy'EVENT) OR my_bus = '0'); IF command.rd_byte_num = 1 THEN WAIT UNTIL ((rdy = '1' AND rdy'EVENT) OR my_bus = '0'); END IF; END IF; WHEN write => IF my_bus = '1' OR busy = '0' THEN IF ( (buff(7 downto 4)) = "0000" OR (buff(7 downto 4)) = "1111" ) THEN address_some_slave <= FALSE; ELSE address_some_slave <= TRUE; END IF; buff <= to_slv(command.wr_byte,8); next_req <= '0'; end_of_write <= '0'; WAIT UNTIL ((rdy = '1' AND rdy'EVENT) OR my_bus = '0'); END IF; WHEN read => IF my_bus = '1' OR busy = '0' THEN --buff <= to_slv(command.wr_byte,8); next_req <= '0'; load_rd_cnt <= '1', '0' AFTER 1 ns; rd_value <= command.rd_byte_num; end_of_write <= '1'; FOR i IN 0 TO command.rd_byte_num-1 LOOP --WHILE i < (command.rd_byte_num) LOOP WAIT UNTIL ((rdy = '1' AND rdy'EVENT) OR my_bus = '0'); -- i := i+1; END LOOP; END IF; WHEN delay_clk => --buff <= to_slv(command.wr_byte,8); next_req <= '0'; load_rd_cnt <= '1', '0' AFTER 1 ns; rd_value <= command.rd_byte_num; delay_value <= command.wtime; end_of_write <= '1'; WHEN dis_sl_resp => tmp := to_slv(command.wr_byte, 8); --tmp_time := NOW; --WAIT FOR (command.wtime - tmp_time);--current_time); en_sl_resp <= tmp(0); end_of_write <= '1'; WAIT FOR command.wtime; WHEN OTHERS => null; END CASE; END IF; END PROCEDURE command_decode; BEGIN hard_addr <= '1', '0' AFTER 1 ns;--WHEN GENERAL_CALL_gen = FALSE ELSE --'0'; hs_mode <= hs_mode_m OR hs_mode_s; mode <= 's' WHEN (T_LOW_gen >= 4.7 us AND T_HIGH_gen >= 4.0 us) ELSE 'f' WHEN (T_LOW_gen >= 1.3 us AND T_HIGH_gen >= 0.6 us) ELSE --Cp = 100 pF 'h';-- WHEN (T_LOW_gen >= 160 ns AND T_HIGH_gen >= 60 ns) SDA_in <= '1' AFTER tdevice_tgsp WHEN SDA /= '0' ELSE '0' AFTER tdevice_tgsp; SCL_in <= '1' AFTER tdevice_tgsp WHEN SCL /= '0' ELSE '0' AFTER tdevice_tgsp; ---------------------------------------------------------------------------- --Power Up time 100 ns; ----------------------------------------------------------------------------- PoweredUp <= '1' AFTER 100 ns;-- RST <= RESETNeg AFTER 500 ns; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(SDA, SCL) -- Timing Check Variables VARIABLE TD_SCL_SDA : VitalTimingDataType; VARIABLE Tviol_SLC_SDA : X01 := '0'; VARIABLE TD_SCL_SDA_negedge : VitalTimingDataType; VARIABLE Tviol_SCL_SDA_negedge : X01 := '0'; VARIABLE TD_SDA_SCL_negedge : VitalTimingDataType; VARIABLE Tviol_SDA_SCL_negedge : X01 := '0'; VARIABLE TD_SDA_SCL_posedge : VitalTimingDataType; VARIABLE Tviol_SDA_SCL_posedge : X01 := '0'; VARIABLE TD_SCL_SDA_posedge : VitalTimingDataType; VARIABLE Tviol_SCL_SDA_posedge : X01 := '0'; VARIABLE PD_SCL : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCL : X01 := '0'; VARIABLE Violation : X01 := '0'; BEGIN ---------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- tHD;STA 4us, 0.6us, 160ns VitalSetupHoldCheck ( TestSignal => SCL, TestSignalName => "SCL", RefSignal => SDA, RefSignalName => "SDA", HoldHigh => thold_SCL_SDA, -- always enabled in HS mode CheckEnabled => mode = 'h' OR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -