📄 i2c.vhd
字号:
-- in s/f mode enabled only if hs-mode is not active ((mode = 's' OR mode = 'f') AND hs_mode = '0'), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_SCL_SDA, Violation => Tviol_SLC_SDA ); -- tSU;STA 4.7us, 0.6us, 160ns VitalSetupHoldCheck ( TestSignal => SCL, TestSignalName => "SCL", RefSignal => SDA, RefSignalName => "SDA", SetupHigh => tsetup_scl_sda_noedge_negedge, -- always enabled in HS mode CheckEnabled => mode = 'h' OR -- in s/f mode enabled only if hs-mode is not active ((mode = 's' OR mode = 'f') AND hs_mode = '0'), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_SCL_SDA_negedge, Violation => Tviol_SCL_SDA_negedge ); -- tHD;DAT 300ns, 300ns, -->20 ns (3mA current source and 400 pF load) --> 10 ns (load 10-100 pF) VitalSetupHoldCheck ( TestSignal => SDA, TestSignalName => "SDA", RefSignal => SCL, RefSignalName => "SCL", HoldHigh => thold_SDA_SCL, HoldLow => thold_SDA_SCL, CheckEnabled => TRUE,-- current_state = S_INIT OR cs = '1' RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_SDA_SCL_negedge, Violation => Tviol_SDA_SCL_negedge ); -- tSU;DAT 250ns, 100ns, 10ns VitalSetupHoldCheck ( TestSignal => SDA, TestSignalName => "SDA", RefSignal => SCL, RefSignalName => "SCL", SetupHigh => tsetup_SDA_SCL, SetupLow => tsetup_SDA_SCL, CheckEnabled => TRUE,-- current_state = S_INIT OR cs = '1' RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_SDA_SCL_posedge, Violation => Tviol_SDA_SCL_posedge ); -- tSU;STO 4.0us, 0.6us, 160ns VitalSetupHoldCheck ( TestSignal => SCL, TestSignalName => "SCL", RefSignal => SDA, RefSignalName => "SDA", SetupHigh => tsetup_scl_sda_noedge_posedge, CheckEnabled => TRUE,-- current_state = S_INIT OR cs = '1' RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_SCL_SDA_posedge, Violation => Tviol_SCL_SDA_posedge );-------------------------pulse width checkers------------------------ -- PulseWidth Check for REset VitalPeriodPulseCheck ( TestSignal => SCL, TestSignalName => "SCL", PulseWidthLow => tpw_SCL_negedge, PulseWidthHigh => tpw_SCL_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_SCL, Violation => Pviol_SCL ); Violation := Tviol_SLC_SDA OR Tviol_SCL_SDA_negedge OR Tviol_SDA_SCL_negedge OR Tviol_SDA_SCL_posedge OR Tviol_SCL_SDA_posedge OR Pviol_SCL; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; --------------------------------------------------------------------------- --Spike Protection: Inertial Delay does not propagate pulses < --------------------------------------------------------------------------- --gWE_n <= WENeg AFTER 5 ns; --------------------------------------------------------------------------- --Process that reports warning when changes on signals WE#, CE#, OE# are --discarded ----------------------------------------------------------------------------- PulseWatch : PROCESS (WENeg, CENeg, OENeg, gWE_n, gCE_n, gOE_n)-- BEGIN-- IF (WENeg'EVENT AND WENeg = gWE_n) THEN-- ASSERT false-- REPORT "Glitch detected on write control signals"-- SEVERITY warning;-- END IF;-- END PROCESS PulseWatch; Restore_slave_addr: PROCESS(hard_addr, soft_addr, load_addr) VARIABLE tmp : std_logic_vector(7 downto 0); BEGIN IF rising_edge(hard_addr) THEN slave_addr <= SLAVE_ADDR_gen; ELSIF rising_edge(soft_addr) THEN FOR i IN 0 TO 9 LOOP IF SLAVE_ADDR_gen(i) /= 'U' THEN slave_addr(i) <= SLAVE_ADDR_gen(i); ELSIF PPART_SLAVE_ADDR_gen(i) /= 'U' THEN slave_addr(i) <= PPART_SLAVE_ADDR_gen(i); END IF; END LOOP; -- if hardware master is intitialized through general call hard_mast_addressed <= '1'; -- writting dump address to hardware master ELSIF rising_edge(load_addr) THEN tmp := to_slv(slv_mem(0), 8); slave_addr(9 downto 0) <= "UUU" & tmp(7 downto 1); hard_mast_addressed <= '1'; END IF; END PROCESS; --------------------------------------------------------------------------- --Latch SDA on falling edge of SCL --------------------------------------------------------------------------- BusCycleDecode : PROCESS(SCL_in) BEGIN IF falling_edge(SCL_in) THEN SDA_tmp := SDA_in; END IF; END PROCESS BusCycleDecode; --------------------------------- -- detects START condition --------------------------------- start_proc: PROCESS(SDA_in, SCL_in) BEGIN IF falling_edge(SDA_in) AND SCL_in /= '0' THEN start <= '1', '0' AFTER 1 ns; --ELSIF falling_edge(SCL_in) THEN -- start <= '0'; END IF; END PROCESS start_proc; --------------------------------- -- detects STOP condition --------------------------------- stop_proc: PROCESS(SDA_in, SCL_in) BEGIN IF rising_edge(SDA_in) AND SCL_in /= '0' THEN stop <= '1' AFTER tdevice_tbuff, '0' AFTER tdevice_tbuff + 1 ns; --IF (start = '1') THEN -- Report("Void command is illegal"); --END IF; --ELSIF falling_edge(SCL_in) THEN --stop <= '0'; END IF; END PROCESS stop_proc; ---------------------------------------- -- if START is asserted by this device --------------------------------------- my_bus_proc: PROCESS(start, SDA_zd, stop, SDA_in, SCL_in, arb_lost) BEGIN IF start = '1' AND SDA_zd = '0' THEN my_bus <= '1'; -- stop condition detected ELSIF stop = '1' THEN my_bus <= '0'; --or lost arbitration ELSIF arb_lost = '1' THEN my_bus <= '0'; -- local stop, this device ends transfer ELSIF my_bus = '1' AND SCL_in /= '0' AND SDA_in = '0' AND rising_edge(SDA_zd) THEN my_bus <= '0'; END IF; END PROCESS my_bus_proc; --------------------------------- -- bus busy --------------------------------- bus_busy_proc: PROCESS(start, stop) BEGIN-- IF falling_edge(start) THEN-- -- stop and start are not genereted during same SCL high period-- IF (stop = '0') THEN-- busy <= '1';-- ELSE-- -- stop and start are genereted during same SCL high period-- IF SDA_in = '0' THEN-- -- restart condition is last-- busy <= '1';-- ELSE-- -- stop condition is last, this is illegal-- busy <= '0';-- END IF;-- END IF; IF start = '1' THEN busy <= '1'; ELSIF stop = '1' THEN busy <= '0'; END IF; END PROCESS bus_busy_proc; clk_cnt_proc: PROCESS(start, stop, SCL_in) BEGIN IF (start = '1' )--AND busy = '0')-- not restart OR stop = '1' THEN clk_cnt <= 0 AFTER 1 ns;-- ACK <= '0'; ELSIF falling_edge(SCL_in) THEN clk_cnt <= (clk_cnt + 1) MOD 9 AFTER 1 ns;-- IF clk_cnt = 8 THEN-- ACK <= '1';-- ELSE-- ACK <= '0';-- END IF; END IF; END PROCESS clk_cnt_proc;-- ACK_gen:PROCESS(clk_cnt)-- BEGIN-- IF clk_cnt = 0 THEN-- ACK <= '1';-- ELSE-- ACK <= '0';-- END IF;-- END PROCESS; clk_synchro: PROCESS(SCL_in, timeout_high, my_bus) VARIABLE t_new_timeout_high : TIME := 0 ns; BEGIN IF (rising_edge(my_bus)) THEN SCL_zd <= '0' AFTER 2 us, '1' AFTER T_LOW_gen + 2 us;--tsetup_scl_sda_negedge; ELSIF busy = '1' THEN IF (cs = '1' OR my_bus = '1') THEN t_new_timeout_high := -SCL_in'LAST_EVENT + T_HIGH_gen; IF falling_edge(SCL_in) THEN SCL_zd <= '0', '1' AFTER T_LOW_gen; ELSIF rising_edge(SCL_in) THEN timeout_high <= '1' AFTER T_HIGH_gen - 1 ns, '0' AFTER T_HIGH_gen; END IF; IF (falling_edge(timeout_high)) THEN IF (t_new_timeout_high <= 0 ns) THEN SCL_zd <= '0', '1' AFTER T_LOW_gen; ELSE timeout_high <= '1' AFTER t_new_timeout_high - 1 ns, '0' AFTER t_new_timeout_high; END IF; END IF; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- --rd_cnt: number of words to be read from slave --------------------------------------------------------------------------- rd_cnt_proc: PROCESS(load_rd_cnt, decr_rd_cnt) BEGIN IF load_rd_cnt = '1' THEN rd_cnt <= rd_value; ELSIF decr_rd_cnt = '1' THEN rd_cnt <= rd_cnt - 1; END IF; END PROCESS rd_cnt_proc; --------------------------------------------------------------------------- --FSM --------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- sequential process for reset control and FSM state transition ---------------------------------------------------------------------------- StateTransition_slave : PROCESS(SCL_in, stop) BEGIN IF stop = '1' THEN current_state_s <= IDLE; ELSIF rising_edge(SCL_in) THEN current_state_s <= next_state_s; END IF; END PROCESS StateTransition_slave; StateTransition_master : PROCESS(SCL_in, stop) BEGIN IF stop = '1' THEN current_state_m <= IDLE; ELSIF rising_edge(SCL_in) THEN current_state_m <= next_state_m; END IF; END PROCESS StateTransition_master; ---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -