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,也能正常工作,请高手不吝赐教! 
 |