Chào các bạn !
Mình đang phải đọc nhiệt độ từ con cảm biến nhiệt số TEMP275. Hiện là code VHDL đã viết xong, mo phỏng bằng Modelsim thì thấy là được. Nhưng cho vào mạch thật , sử dụng Kit Alter DE2-115 để test và mo phỏng bằng SIGNALTAB thì chưa đọc được nhiệt độ.
Rất mong nhận được sự giúp đỡ của các bạn trên diễn đàn này !!!
Mình đang phải đọc nhiệt độ từ con cảm biến nhiệt số TEMP275. Hiện là code VHDL đã viết xong, mo phỏng bằng Modelsim thì thấy là được. Nhưng cho vào mạch thật , sử dụng Kit Alter DE2-115 để test và mo phỏng bằng SIGNALTAB thì chưa đọc được nhiệt độ.
Rất mong nhận được sự giúp đỡ của các bạn trên diễn đàn này !!!
-- doc 1byte nhiet do tu TEMP275
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity TEMP275 is
generic( input_clk: integer := 50_000_000;
bus_clk: integer:= 400_000
);
port ( clk: in std_logic;
clk1: out std_logic; -- xung clock = 1200_000 Hz de soi tren signaltab
SCL: out std_logic;
SDA: inout std_logic;
data_out: out std_logic_vector(7 downto 0)
);
end TEMP275;
architecture arch of TEMP275 is
signal ena: std_logic := '0'; -- cho phep qua trinh lam viec bat dau
signal addr: std_logic_vector(6 downto 0):= "1001000";
signal rw: std_logic; -- viet khi rw =0, doc khi rw =1
signal data_rd: std_logic_vector(7 downto 0):= "00000000"; -- thanh ghi doc du lieu tu TEMP275
constant divider : integer := (input_clk/bus_clk)/4; -- number of clocks in 1/4 cycle of SCL
constant divider1 : integer := divider*4/8;
TYPE machine is (ready, start, command, slv_ack1, wr1, slv_ack2, wr2, slv_ack3,stop, ready1, start1, command1, slv_ack4, rd, mstr_ack, stop1, ready2, start2, command2, slv_ack5); -- mo ta trang thai
signal state : machine := ready; -- state machine
signal data_clk : std_logic; -- xung clock cho SDA
SIGNAL scl_clk : STD_LOGIC; --constantly running internal scl
SIGNAL scl_ena : STD_LOGIC := '0'; --enables internal scl to output
SIGNAL sda_out : STD_LOGIC := '1'; --internal sda
--signal sda_int : std_logic:= '1';
SIGNAL sda_ena_n : STD_LOGIC; --enables internal sda
SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave
SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave
SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction
SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write
begin
--generate the timing for the bus clock (scl_clk) and the data clock (data_clk)
PROCESS(clk)
VARIABLE count : INTEGER RANGE 0 TO divider*4 := 0; --timing for clock generation
BEGIN
IF(clk'EVENT AND clk = '1') THEN
count := count + 1;
IF(count = divider*4-1) THEN --end of timing cycle
count := 0; --reset timer
END IF;
CASE count IS
WHEN 0 TO divider-1 => --first 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '0';
WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '1';
WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking
scl_clk <= '1'; --release scl
data_clk <= '1';
WHEN OTHERS => --last 1/4 cycle of clocking
scl_clk <= '1';
data_clk <= '0';
END CASE;
END IF;
END PROCESS;
-- bo chia tan 800KHz dung de soi tren signalTAB --50*10^6/800*10^3
process(clk)
VARIABLE cnt_div : INTEGER range 0 to divider1:= 0;
variable f : std_logic;
begin
if rising_edge(clk) then
cnt_div := cnt_div + 1;
if(cnt_div = divider1) then
cnt_div := 0;
f := not f;
end if;
end if;
clk1 <= f;
end process;
--state machine and writing to sda during scl low (data_clk rising edge)
PROCESS(data_clk)
BEGIN
IF(data_clk'EVENT AND data_clk = '1') THEN
CASE state IS
-- Init TEMP275
WHEN ready => -- trang thai nghi, chuan bi cho truyen du lieu
sda_out <= '1';
ena <= '1'; -- cho phep viet lenh
addr_rw <= "10010000";
data_tx <= "00000001";
state <= start;
WHEN start => -- bit start
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command;
WHEN command => -- dia chi TEMP275
IF(bit_cnt = 0) THEN
sda_out <= 'Z'; -- cho bit ACK tu slave
bit_cnt <= 7;
state <= slv_ack1;
ELSE
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt-1);
state <= command;
END IF;
WHEN slv_ack1 => -- nhan bit ack tu TEMP275
rw <= '0';
sda_out <= data_tx(bit_cnt);
state <= wr1;
when wr1 => -- SELECT RES CONFIG
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
data_tx <= "00000000";
state <= slv_ack2;
else
bit_cnt <= bit_cnt - 1;
sda_out <= data_tx(bit_cnt - 1);
state <= wr1;
end if;
when slv_ack2 =>
rw <= '0';
sda_out <= data_tx(bit_cnt);
state <= wr2;
when wr2 =>
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
state <= slv_ack3;
else
bit_cnt <= bit_cnt - 1;
sda_out <= data_tx(bit_cnt - 1);
state <= wr2;
end if;
when slv_ack3 =>
sda_out <= '1';
ena <= '0';
scl_ena <= '0';
state <= stop;
when stop =>
state <= ready1;
-- Qua trinh doc du lieu tu TEMP275
when ready1 =>
ena <= '1';
addr_rw <= "10010000";
data_tx <= "00000000";
state <= start1;
when start1 =>
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command1;
when command1 =>
IF(bit_cnt = 0) THEN
sda_out <= 'Z'; -- cho bit ACK tu slave
bit_cnt <= 7;
state <= slv_ack4;
ELSE
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt-1);
state <= command1;
END IF;
when slv_ack4 =>
ena <= '0' ;
sda_out <= '1';
scl_ena <= '0';
state <= ready2;
when ready2 =>
ena <= '1';
addr_rw <= "10010001";
state <= start2;
when start2 =>
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command2;
when command2 =>
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
state <= slv_ack5;
else
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt - 1);
state <= command2;
end if;
when slv_ack5 =>
rw <= '1';
sda_out <= '1';
state <= rd;
when rd =>
if (bit_cnt = 0) then
sda_out <= '0';
bit_cnt <= 7;
data_rd <= data_rx;
state <= mstr_ack;
else
bit_cnt <= bit_cnt - 1;
state <= rd;
end if;
when mstr_ack =>
ena <= '0';
scl_ena <= '0';
state <= stop1;
when stop1 => -- bit STOP
sda_out <= '1';
state <= ready2;
END CASE;
END IF;
if (data_clk'event and data_clk ='0') then
case state is
when rd =>
data_rx(bit_cnt) <= sda;
when others => Null;
end case;
end if;
END PROCESS;
--set sda output
WITH state SELECT
sda_ena_n <= data_clk WHEN start, --generate start condition
data_clk when start1,
data_clk when start2,
not data_clk when stop1,
not data_clk WHEN stop, --generate stop condition
'Z' when rd,
sda_out WHEN OTHERS; --set to internal sda signal
--set scl and sda outputs
SCL <= scl_clk when scl_ena = '1' else '1';
sda <= sda_ena_n;
end arch;
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity TEMP275 is
generic( input_clk: integer := 50_000_000;
bus_clk: integer:= 400_000
);
port ( clk: in std_logic;
clk1: out std_logic; -- xung clock = 1200_000 Hz de soi tren signaltab
SCL: out std_logic;
SDA: inout std_logic;
data_out: out std_logic_vector(7 downto 0)
);
end TEMP275;
architecture arch of TEMP275 is
signal ena: std_logic := '0'; -- cho phep qua trinh lam viec bat dau
signal addr: std_logic_vector(6 downto 0):= "1001000";
signal rw: std_logic; -- viet khi rw =0, doc khi rw =1
signal data_rd: std_logic_vector(7 downto 0):= "00000000"; -- thanh ghi doc du lieu tu TEMP275
constant divider : integer := (input_clk/bus_clk)/4; -- number of clocks in 1/4 cycle of SCL
constant divider1 : integer := divider*4/8;
TYPE machine is (ready, start, command, slv_ack1, wr1, slv_ack2, wr2, slv_ack3,stop, ready1, start1, command1, slv_ack4, rd, mstr_ack, stop1, ready2, start2, command2, slv_ack5); -- mo ta trang thai
signal state : machine := ready; -- state machine
signal data_clk : std_logic; -- xung clock cho SDA
SIGNAL scl_clk : STD_LOGIC; --constantly running internal scl
SIGNAL scl_ena : STD_LOGIC := '0'; --enables internal scl to output
SIGNAL sda_out : STD_LOGIC := '1'; --internal sda
--signal sda_int : std_logic:= '1';
SIGNAL sda_ena_n : STD_LOGIC; --enables internal sda
SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave
SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave
SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction
SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write
begin
--generate the timing for the bus clock (scl_clk) and the data clock (data_clk)
PROCESS(clk)
VARIABLE count : INTEGER RANGE 0 TO divider*4 := 0; --timing for clock generation
BEGIN
IF(clk'EVENT AND clk = '1') THEN
count := count + 1;
IF(count = divider*4-1) THEN --end of timing cycle
count := 0; --reset timer
END IF;
CASE count IS
WHEN 0 TO divider-1 => --first 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '0';
WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '1';
WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking
scl_clk <= '1'; --release scl
data_clk <= '1';
WHEN OTHERS => --last 1/4 cycle of clocking
scl_clk <= '1';
data_clk <= '0';
END CASE;
END IF;
END PROCESS;
-- bo chia tan 800KHz dung de soi tren signalTAB --50*10^6/800*10^3
process(clk)
VARIABLE cnt_div : INTEGER range 0 to divider1:= 0;
variable f : std_logic;
begin
if rising_edge(clk) then
cnt_div := cnt_div + 1;
if(cnt_div = divider1) then
cnt_div := 0;
f := not f;
end if;
end if;
clk1 <= f;
end process;
--state machine and writing to sda during scl low (data_clk rising edge)
PROCESS(data_clk)
BEGIN
IF(data_clk'EVENT AND data_clk = '1') THEN
CASE state IS
-- Init TEMP275
WHEN ready => -- trang thai nghi, chuan bi cho truyen du lieu
sda_out <= '1';
ena <= '1'; -- cho phep viet lenh
addr_rw <= "10010000";
data_tx <= "00000001";
state <= start;
WHEN start => -- bit start
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command;
WHEN command => -- dia chi TEMP275
IF(bit_cnt = 0) THEN
sda_out <= 'Z'; -- cho bit ACK tu slave
bit_cnt <= 7;
state <= slv_ack1;
ELSE
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt-1);
state <= command;
END IF;
WHEN slv_ack1 => -- nhan bit ack tu TEMP275
rw <= '0';
sda_out <= data_tx(bit_cnt);
state <= wr1;
when wr1 => -- SELECT RES CONFIG
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
data_tx <= "00000000";
state <= slv_ack2;
else
bit_cnt <= bit_cnt - 1;
sda_out <= data_tx(bit_cnt - 1);
state <= wr1;
end if;
when slv_ack2 =>
rw <= '0';
sda_out <= data_tx(bit_cnt);
state <= wr2;
when wr2 =>
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
state <= slv_ack3;
else
bit_cnt <= bit_cnt - 1;
sda_out <= data_tx(bit_cnt - 1);
state <= wr2;
end if;
when slv_ack3 =>
sda_out <= '1';
ena <= '0';
scl_ena <= '0';
state <= stop;
when stop =>
state <= ready1;
-- Qua trinh doc du lieu tu TEMP275
when ready1 =>
ena <= '1';
addr_rw <= "10010000";
data_tx <= "00000000";
state <= start1;
when start1 =>
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command1;
when command1 =>
IF(bit_cnt = 0) THEN
sda_out <= 'Z'; -- cho bit ACK tu slave
bit_cnt <= 7;
state <= slv_ack4;
ELSE
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt-1);
state <= command1;
END IF;
when slv_ack4 =>
ena <= '0' ;
sda_out <= '1';
scl_ena <= '0';
state <= ready2;
when ready2 =>
ena <= '1';
addr_rw <= "10010001";
state <= start2;
when start2 =>
scl_ena <= '1';
sda_out <= addr_rw(bit_cnt);
state <= command2;
when command2 =>
if(bit_cnt = 0) then
sda_out <= 'Z';
bit_cnt <= 7;
state <= slv_ack5;
else
bit_cnt <= bit_cnt - 1;
sda_out <= addr_rw(bit_cnt - 1);
state <= command2;
end if;
when slv_ack5 =>
rw <= '1';
sda_out <= '1';
state <= rd;
when rd =>
if (bit_cnt = 0) then
sda_out <= '0';
bit_cnt <= 7;
data_rd <= data_rx;
state <= mstr_ack;
else
bit_cnt <= bit_cnt - 1;
state <= rd;
end if;
when mstr_ack =>
ena <= '0';
scl_ena <= '0';
state <= stop1;
when stop1 => -- bit STOP
sda_out <= '1';
state <= ready2;
END CASE;
END IF;
if (data_clk'event and data_clk ='0') then
case state is
when rd =>
data_rx(bit_cnt) <= sda;
when others => Null;
end case;
end if;
END PROCESS;
--set sda output
WITH state SELECT
sda_ena_n <= data_clk WHEN start, --generate start condition
data_clk when start1,
data_clk when start2,
not data_clk when stop1,
not data_clk WHEN stop, --generate stop condition
'Z' when rd,
sda_out WHEN OTHERS; --set to internal sda signal
--set scl and sda outputs
SCL <= scl_clk when scl_ena = '1' else '1';
sda <= sda_ena_n;
end arch;
Comment