Skip to content

Instantly share code, notes, and snippets.

@fbrosser
Created November 21, 2011 15:00
Show Gist options
  • Save fbrosser/1382869 to your computer and use it in GitHub Desktop.
Save fbrosser/1382869 to your computer and use it in GitHub Desktop.
Debugging temp-sensor interface
----------------------------------------------------------------------------------
-- 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