library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ds1820 is
port(clk : in std_logic;
dq : inout std_logic;
temp_h : out std_logic_vector(7 downto 0);
temp_l : out std_logic_vector(7 downto 0));
end ds1820;
architecture Behavioral of ds1820 is
TYPE STATE_TYPE is (RESET,CMD_CC,WRITE_BYTE,WRITE_LOW,WRITE_HIGH,READ_BIT,CMD_44,WAIT800MS,CMD_BE,GET_TMP,WAIT4MS);
signal STATE: STATE_TYPE:=RESET;
signal clk_temp : std_logic:='0';
signal clk1m : std_logic;
signal write_temp : std_logic_vector(7 downto 0):="00000000";
signal TMP : std_logic_vector(11 downto 0);
signal tmp_bit : std_logic;
signal WRITE_BYTE_CNT : integer range 0 to 8:=0;
signal WRITE_LOW_CNT : integer range 0 to 2:=0;
signal WRITE_HIGH_CNT : integer range 0 to 2:=0;
signal READ_BIT_CNT : integer range 0 to 3:=0;
signal GET_TMP_CNT : integer range 0 to 12:=0;
signal cnt : integer range 0 to 100001:=0;
signal count : integer range 0 to 25:=0;
signal WRITE_BYTE_FLAG : integer range 0 to 4:=0;
begin
ClkDivider:process (clk)
begin
if rising_edge(clk) then
if (count = 24) then
count <= 0;
clk_temp<= not clk_temp;
else
count <= count +1;
end if;
end if;
clk1m<=clk_temp;
end Process;
STATE_TRANSITION:process(STATE,clk1m)
begin
if rising_edge(clk1m) then
case STATE is
when RESET=>
if (cnt>=0 and cnt<500) then
dq<='0';
cnt<=cnt+1;
STATE<=RESET;
elsif (cnt>=500 and cnt<1000) then
dq<='Z';
cnt<=cnt+1;
STATE<=RESET;
elsif (cnt>=1000) then
cnt<=0;
STATE<=CMD_CC;
end if;
when CMD_CC=>
write_temp<="11001100";
STATE<=WRITE_BYTE;
when WRITE_BYTE=>
case WRITE_BYTE_CNT is
when 0 to 7=>
if (write_temp(WRITE_BYTE_CNT)='0') then
STATE<=WRITE_LOW;
else
STATE<=WRITE_HIGH;
end if;
WRITE_BYTE_CNT<=WRITE_BYTE_CNT+1;
when 8=>
if (WRITE_BYTE_FLAG=0) then -- 第一次写0XCC完毕
STATE<=CMD_44;
WRITE_BYTE_FLAG<=1;
elsif (WRITE_BYTE_FLAG=1) then --写0X44完毕
STATE<=RESET;
WRITE_BYTE_FLAG<=2;
elsif (WRITE_BYTE_FLAG=2) then --第二次写0XCC完毕
STATE<=CMD_BE;
WRITE_BYTE_FLAG<=3;
elsif (WRITE_BYTE_FLAG=3) then --写0XBE完毕
STATE<=GET_TMP;
WRITE_BYTE_FLAG<=0;
end if;
WRITE_BYTE_CNT<=0;
end case;
when WRITE_LOW=>
case WRITE_LOW_CNT is
when 0=>
dq<='0';
if (cnt=78) then
cnt<=0;
WRITE_LOW_CNT<=1;
else
cnt<=cnt+1;
end if;
when 1=>
dq<='Z';
if (cnt=2) then
cnt<=0;
WRITE_LOW_CNT<=2;
else
cnt<=cnt+1;
end if;
when 2=>
STATE<=WRITE_BYTE;
WRITE_LOW_CNT<=0;
when others=>WRITE_LOW_CNT<=0;
end case;
when WRITE_HIGH=>
case WRITE_HIGH_CNT is
when 0=>
dq<='0';
if (cnt=8) then
cnt<=0;
WRITE_HIGH_CNT<=1;
else
cnt<=cnt+1;
end if;
when 1=>
dq<='Z';
if (cnt=72) then
cnt<=0;
WRITE_HIGH_CNT<=2;
else
cnt<=cnt+1;
end if;
when 2=>
STATE<=WRITE_BYTE;
WRITE_HIGH_CNT<=0;
when others=>WRITE_HIGH_CNT<=0;
end case;
when READ_BIT=>
case READ_BIT_CNT is
when 0=>
dq<='0';
if (cnt=4) then
READ_BIT_CNT<=1;
cnt<=0;
else
cnt<=cnt+1;
end if;
when 1=>
dq<='Z';
if (cnt=4) then
READ_BIT_CNT<=2;
cnt<=0;
else
cnt<=cnt+1;
end if;
when 2=>
TMP_BIT<=dq;
if (cnt=1) then
READ_BIT_CNT<=3;
cnt<=0;
else
cnt<=cnt+1;
end if;
when 3=>
if (cnt=45) then
cnt<=0;
READ_BIT_CNT<=0;
STATE<=GET_TMP;
else
cnt<=cnt+1;
end if;
when others=>READ_BIT_CNT<=0;
end case;
when CMD_44=>
write_temp<="01000100";
STATE<=WRITE_BYTE;
when WAIT800MS=>
if (cnt>=100000) then
STATE<=RESET;
cnt<=0;
else
cnt<=cnt+1;
STATE<=WAIT800MS;
end if;
when CMD_BE=>
write_temp<="10111110";
STATE<=WRITE_BYTE;
when GET_TMP=>
case GET_TMP_CNT is
when 0 to 11=>
STATE<=READ_BIT;
TMP(GET_TMP_CNT)<=TMP_BIT;
GET_TMP_CNT<=GET_TMP_CNT+1;
when 12=>
GET_TMP_CNT<=0;
STATE<=WAIT4MS;
end case;
when WAIT4MS=>
if (cnt>=4000) then
STATE<=RESET;
cnt<=0;
else
cnt<=cnt+1;
STATE<=WAIT4MS;
end if;
when others=>STATE<=RESET;
end case;
end if;
end process;
temp_h<='0'&TMP(11 downto 5);
temp_l<="0000"&TMP(4 downto 1);
end Behavioral;
今天刚编好的,在XILINX SPARTAN3 STARTER KIT 上测试能正常显示温度
代码中还存在一些不当之处,欢迎大家指教
还有一点不解的是,代码中的WAIT800MS这个状态不要,也就是不用等待800ms,也能正常工作,请高手不吝赐教!
|