Created
November 21, 2011 15:00
-
-
Save fbrosser/1382869 to your computer and use it in GitHub Desktop.
Debugging temp-sensor interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
---------------------------------------------------------------------------------- | |
-- Fredrik Brosser | |
-- DS18S20 1-Wire Communication | |
-- EDA234, Group 2 | |
-- | |
-- ComTest.vhd | |
-- Last Updated: 2011-11-16 | |
-- | |
-- Target Device: XC9572XL | |
-- I/O Pins Used: | |
-- Macrocells Used: | |
-- Product Terms Used: | |
-- | |
---------------------------------------------------------------------------------- | |
library IEEE; | |
use IEEE.STD_LOGIC_1164.ALL; | |
use IEEE.STD_LOGIC_UNSIGNED.ALL; | |
use IEEE.STD_LOGIC_ARITH.ALL; | |
--use IEEE.NUMERIC_STD.ALL; | |
Entity ComTest is | |
port( -- Global clock | |
clk : in std_logic; | |
-- Global reset | |
rst : in std_logic; | |
-- Hardware trigger / Trigger from Control Unit | |
trig : in std_logic; | |
-- Signal to MUX, for selecting active sensor (0/1 for DQ0/DQ1, resp.) | |
Tsel : in std_logic; | |
-- Valid data on temperature bus | |
TAv : out std_logic; | |
-- Output to 1-Wire bus 1 | |
DQ0 : inout std_logic; | |
-- Output to 1-Wire bus 0 | |
DQ1 : inout std_logic; | |
-- Internal temperature data output | |
TOut : out std_logic_vector(7 downto 0); | |
-- The following signals are used for debugging in hardware only | |
RxMode : out std_logic; | |
Rsted : out std_logic; | |
tbOut : out std_logic; | |
tsOut : out std_logic; | |
EOut : out std_logic; | |
HWTrig : out std_logic; | |
doneSend : out std_logic; | |
DoneConv : out std_logic | |
); | |
end ComTest; | |
Architecture Behavioral of ComTest is | |
-- Internal signal declarations | |
-- Buffer Enable | |
signal E : std_logic; | |
signal nextE : std_logic; | |
-- Valid data on temperature bus | |
signal TAvInt : std_logic; | |
signal nextTAvInt : std_logic; | |
-- State variables (as integers) | |
signal state : integer range 0 to 15; | |
signal nextState : integer range 0 to 15; | |
-- Data to be sent on bus | |
signal data : std_logic_vector(7 downto 0); | |
signal nextData : std_logic_vector(7 downto 0); | |
-- Internal temperature data output | |
signal tempOut : std_logic_vector(7 downto 0); | |
signal nextTempOut : std_logic_vector(7 downto 0); | |
-- Sign bit from sensor | |
signal signBit : std_logic; | |
signal nextSignBit : std_logic; | |
-- Sampling of bus by master | |
signal sample : std_logic; | |
signal nextSample : std_logic; | |
-- Counter used when sending a logical 0 on bus ('Zero Counter') | |
signal ZC : std_logic_vector(3 downto 0); | |
signal nextZC : std_logic_vector(3 downto 0); | |
-- Signal for keeping track of our progress through the read-cycle | |
signal progress : std_logic_vector(1 downto 0); | |
signal nextProgress : std_logic_vector(1 downto 0); | |
-- Counter for keeping track of which bit we are currently transmitting or sampling | |
signal bitCnt : std_logic_vector(2 downto 0); | |
signal nextBitCnt : std_logic_vector(2 downto 0); | |
-- Internal counter used to create timing pulses | |
signal cntInt : std_logic_vector(8 downto 0); | |
signal nextCntInt : std_logic_vector(8 downto 0); | |
-- Timing pulses, 512, 256, 8 and 4 us, respectively | |
signal delayLong : std_logic; | |
signal delayMedium : std_logic; | |
signal delayShort : std_logic; | |
signal delayTiny : std_logic; | |
-- Constants related to timing | |
constant LongDelayConstant : std_logic_vector := "111111110"; | |
constant MediumDelayConstant : std_logic_vector := "11111111"; | |
constant ShortDelayConstant : std_logic_vector := "111"; | |
constant TinyDelayConstant : std_logic_vector := "11"; | |
-- Base value (reset) for ZC | |
constant ZCrst : std_logic_vector := "1010"; | |
begin | |
EOut <= E; | |
TAv <= TAvInt; | |
---------------------------------------------------------------------------------- | |
-- SyncP, synchronous (clocked) process responsible for clocking in the new | |
-- states according to nextState | |
-- | |
-- NB! : This is the only clocked process, | |
-- keeping track of all state or value updates (current => next) | |
-- | |
---------------------------------------------------------------------------------- | |
SyncP : process(clk, rst) | |
begin | |
if(not(rst) = '1') then | |
state <= 0; | |
cntInt <= (others => '0'); | |
ZC <= ZCrst; | |
progress <= (others => '0'); | |
bitCnt <= (others => '1'); | |
data <= (others => '1'); | |
sample <= '1'; | |
E <= '0'; | |
tempOut <= (others => '1'); | |
signBit <= '0'; | |
TAvInt <= '0'; | |
elsif(clk'Event and clk = '1') then | |
state <= nextState; | |
ZC <= nextZC; | |
cntInt <= nextCntInt; -- cntInt + 1; | |
progress <= nextProgress; | |
bitCnt <= nextBitCnt; | |
data <= nextData; | |
sample <= nextSample; | |
E <= nextE; | |
tempOut <= nextTempOut; | |
signBit <= nextSignBit; | |
TAvInt <= nextTAvInt; | |
end if; | |
end process; | |
---------------------------------------------------------------------------------- | |
-- BusP, process responsible for handling the buffered output to the bus, | |
-- according to the enable signal | |
-- | |
---------------------------------------------------------------------------------- | |
BusP : process(E, TSel) | |
begin | |
-- Default : both buses in threestate | |
DQ0 <= 'Z'; | |
DQ1 <= 'Z'; | |
if (E = '1') then | |
if(TSel = '0') then | |
DQ0 <= '0'; | |
elsif(Tsel = '1') then | |
DQ1 <= '0'; | |
end if; | |
end if; | |
end process; | |
---------------------------------------------------------------------------------- | |
-- CountP, internal counter responsible for creating pulses with certain | |
-- time intervals. Uses a local (to the Architecture) counter variable. | |
-- | |
---------------------------------------------------------------------------------- | |
CountP : process(cntInt) | |
begin | |
-- Increment internal counter | |
nextCntInt <= cntInt + 1; | |
-- Gives pulses every 4 us | |
if(cntInt(1 downto 0) = TinyDelayConstant) then | |
delayTiny <= '1'; | |
else | |
delayTiny <= '0'; | |
end if; | |
-- Gives pulses every 8 us | |
if(cntInt(2 downto 0) = ShortDelayConstant) then | |
delayShort <= '1'; | |
else | |
delayShort <= '0'; | |
end if; | |
-- Gives pulses every 256 us | |
if(cntInt(7 downto 0) = MediumDelayConstant) then | |
delayMedium <= '1'; | |
else | |
delayMedium <= '0'; | |
end if; | |
-- Gives pulses every 512 us | |
if(cntInt = LongDelayConstant) then | |
delayLong <= '1'; | |
nextCntInt <= (others => '0'); | |
else | |
delayLong <= '0'; | |
end if; | |
end process; | |
---------------------------------------------------------------------------------- | |
-- SendP, State Machine handling the master side of the 1-wire bus | |
-- communication with the DS18S20. Divided into stages/modes as follows: | |
-- | |
-- 1. INIT (Reset - Presence pulses) | |
-- 2. SEND (Transmission of data from Master to DS18S20) | |
-- 3. READ (Master reads data from DS18S20) | |
-- 4. IDLE (Bus is idle, pulled high by pull-up resistor) | |
-- | |
---------------------------------------------------------------------------------- | |
SendP : process(trig, state, delayLong, delayMedium, delayShort, delayTiny, progress, ZC, bitCnt, Tsel, DQ0, DQ1, sample, data, E, tempOut, signBit, TAvInt) | |
begin | |
-- Defaults | |
nextState <= state; | |
nextProgress <= progress; | |
nextBitCnt <= bitCnt; | |
nextZC <= ZC; | |
nextSample <= sample; | |
nextData <= data; | |
nextE <= E; | |
nextTempOut <= tempOut; | |
nextSignBit <= signBit; | |
nextTAvInt <= TAvInt; | |
-- Signals used for hardware debugging | |
RxMode <= '0'; | |
doneSend <= '0'; | |
Rsted <= '0'; | |
tbOut <= delayLong; | |
tsOut <= delayShort; | |
TOut <= tempOut; | |
doneConv <= '0'; | |
-- Logic Analyzer trigger | |
HWTrig <= '0'; | |
case state is | |
---------------------------------------------------------------------------------- | |
-- INIT | |
---------------------------------------------------------------------------------- | |
when 0 => | |
-- Initialization of debug signals | |
nextE <= '0'; | |
RxMode <= '0'; | |
-- Initialization of signals | |
nextProgress <= "00"; | |
nextZC <= ZCrst; | |
nextSignBit <= '0'; | |
-- Wait for button press | |
Rsted <= '1'; | |
if(not(trig) = '1') then | |
nextState <= state + 1; | |
HWTrig <= '1'; | |
-- Entering the read cycle - data no longer valid | |
nextTAvInt <= '0'; | |
end if; | |
when 1 => | |
-- Enable output and send logical 0 | |
nextE <= '0'; | |
if(delayLong = '1') then | |
nextState <= state + 1; | |
end if; | |
if(progress = "01") then | |
doneConv <= '1'; | |
end if; | |
when 2 => | |
nextE <= '1'; | |
if(delayLong = '1') then | |
nextState <= state + 1; | |
nextData <= X"CC"; | |
end if; | |
when 3 => | |
-- Put bus into threestate and wait for response | |
nextE <= '0'; | |
if(delayLong = '1') then | |
nextState <= state + 1; | |
end if; | |
---------------------------------------------------------------------------------- | |
-- SEND | |
---------------------------------------------------------------------------------- | |
-- Prepare for transmit of the byte in data | |
when 4 => | |
-- Release bus | |
nextE <= '0'; | |
if(delayShort = '1') then | |
nextState <= 5; | |
end if; | |
-- Send logical 0 or 1 | |
-- by driving bus low for a certain number of shortDelay periods (1 for 1's, xZCrst for 0's) | |
when 5 => | |
-- Drive bus low | |
-- Send logical 1 | |
if(data(7-conv_integer(bitCnt)) = '1' and delayShort = '1') then | |
nextE <= '0'; | |
if(ZC = "0000") then | |
nextState <= state + 1; | |
nextZC <= ZCrst; | |
elsif(ZC = ZCrst) then | |
nextE <= '1'; | |
NextZC <= (ZC - 1); | |
else | |
NextZC <= (ZC - 1); | |
end if; | |
-- Send logical 0 | |
elsif(data(7-conv_integer(bitCnt)) = '0' and delayShort = '1') then | |
nextE <= '1'; | |
-- Countdown complete, reset iterator for next 0 | |
if(ZC = "0000") then | |
nextState <= state + 1; | |
nextZC <= ZCrst; | |
-- Count down iterator, keeping the bus low | |
else | |
NextZC <= (ZC - 1); | |
end if; | |
end if; | |
-- Recovery time between transmitted bits, and | |
when 6 => | |
nextE <= '0'; | |
if(delayShort = '1') then | |
if(bitCnt = "000") then | |
-- Done sending byte, move on and reset bit counter | |
nextState <= state + 1; | |
nextBitCnt <= (others => '1'); | |
else | |
-- Send next bit | |
nextBitCnt <= bitCnt - 1; | |
nextState <= state - 1; | |
end if; | |
end if; | |
-- Done sending Command. Disable buffer and give pulse on doneSend | |
when 7 => | |
nextE <= '0'; | |
doneSend <= '1'; | |
if(delayShort = '1') then | |
if(progress = "01") then | |
nextState <= 9; | |
else | |
nextState <= state + 1; | |
end if; | |
end if; | |
-- Prepare to send next Command | |
when 8 => | |
nextE <= '0'; | |
doneSend <= '0'; | |
-- Increase progress variable. NB: assignment at end of process, will compare with 'old' value! | |
nextProgress <= progress + 1; | |
case progress is | |
when "00" => | |
-- Issue Convert T Command (44h) | |
nextData <= X"44"; | |
nextState <= 4; | |
when "01" => | |
-- Do reset and Skip ROM | |
nextData <= X"CC"; | |
nextState <= 1; | |
when "10" => | |
-- Issue Read Scratchpad Command (BEh) | |
nextData <= X"BE"; | |
nextState <= 4; | |
when "11" => | |
-- Master goes into Rx mode | |
nextState <= state + 1; | |
nextProgress <= "11"; | |
when others => | |
-- We should not be here, something is terribly wrong: do full reset | |
nextProgress <= "00"; | |
nextState <= 0; | |
end case; | |
---------------------------------------------------------------------------------- | |
-- READ | |
---------------------------------------------------------------------------------- | |
---------------------------------------------------------------------------------- | |
-- | |
-- Master reads 9 bytes from the bus, starting with LSB of Byte 0 | |
-- However, we are only interested in the temperature registers (Byte 0 and 1), | |
-- so a reset pulse is given after two bytes have been read, telling the DS18S20 | |
-- to discontinue transfer. | |
-- | |
---------------------------------------------------------------------------------- | |
-- Delay and prepare for read phase | |
when 9 => | |
nextE <= '0'; | |
RxMode <= '1'; | |
if(delayMedium = '1') then | |
nextState <= state + 1; | |
end if; | |
-- Pull bus low and wait for response (initiate read time slot, Tinit = 4 us) | |
when 10 => | |
nextE <= '1'; | |
if(delayTiny = '1') then | |
nextState <= state + 1; | |
end if; | |
-- Release bus and allow pullup resistor to perform its magic (Trc = 4 us) | |
when 11 => | |
nextE <= '0'; | |
if(delayTiny = '1') then | |
nextState <= state + 1; | |
end if; | |
-- Sample bus (Tsample = 4 us) | |
when 12 => | |
nextE <= '0'; | |
if(Tsel = '0') then | |
nextSample <= DQ0; | |
elsif(Tsel = '1') then | |
nextSample <= DQ1; | |
end if; | |
if(delayTiny = '1') then | |
nextState <= state + 1; | |
end if; | |
-- Recovery time between read slots | |
when 13 => | |
nextE <= '0'; | |
if(delayMedium = '1') then | |
nextState <= state + 1; | |
end if; | |
-- Go back and sample next bit (or wait for conversion to finish) | |
when 14 => | |
nextE <= '0'; | |
-- Reading 9th bit (temperature sign) | |
if(signBit = '1') then | |
nextTempOut(7) <= sample; | |
nextState <= state + 1; | |
nextProgress <= "00"; | |
else | |
-- Waiting for conversion to finish | |
if(progress = "01") then | |
if(sample = '0') then | |
nextState <= 10; | |
elsif(sample = '1') then | |
nextState <= 8; | |
else | |
nextState <= 10; | |
end if; | |
elsif(progress = "11") then | |
nextState <= 10; | |
-- Reading temperature | |
if(bitCnt = "000") then | |
nextBitCnt <= (others => '1'); | |
nextTempOut(conv_integer(bitCnt)) <= sample; | |
nextSignBit <= '1'; | |
else | |
nextBitCnt <= bitCnt - 1; | |
nextTempOut(conv_integer(bitCnt)) <= sample; | |
end if; | |
else | |
nextState <= 10; | |
end if; | |
end if; | |
when 15 => | |
-- Data on TOut bus is now valid | |
nextTAvInt <= '1'; | |
nextE <= '0'; | |
nextState <= 0; | |
-- Other states. Should never be here. | |
when others => | |
nextE <= '0'; | |
end case; | |
end process; | |
end Behavioral; | |
-- | |
-- UCF | |
#PACE: Start of Constraints generated by PACE | |
#PACE: Start of PACE I/O Pin Assignments | |
NET "clk" LOC = "P5" ; | |
NET "doneSend" LOC = "P28" ; | |
NET "DQ0" LOC = "P25" ; | |
NET "DQ1" LOC = "P20"; | |
NET "rst" LOC = "P39" ; | |
NET "RxMode" LOC = "P29" ; | |
NET "trig" LOC = "P6" ; | |
NET "Rsted" LOC = "P26" ; | |
NET "tbOut" LOC = "P27" ; | |
NET "tsOut" LOC = "P33" ; | |
NET "HWTrig" LOC = "P19" ; | |
NET "EOut" LOC = "P18" ; | |
NET "Tsel" LOC = "P12" ; | |
NET "DoneConv" LOC = "P14" ; | |
NET "TOut(0)" LOC = "P44" ; | |
NET "TOut(1)" LOC = "P43" ; | |
NET "TOut(2)" LOC = "P42" ; | |
NET "TOut(3)" LOC = "P40" ; | |
NET "TOut(4)" LOC = "P38" ; | |
NET "TOut(5)" LOC = "P37" ; | |
NET "TOut(6)" LOC = "P36" ; | |
NET "TOut(7)" LOC = "P35" ; | |
NET "TAv" LOC = "P13" ; | |
#PACE: Start of PACE Area Constraints | |
#PACE: Start of PACE Prohibit Constraints | |
#PACE: End of Constraints generated by PACE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment