OpenCores
URL https://opencores.org/ocsvn/onewire/onewire/trunk

Subversion Repositories onewire

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /onewire
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/HDL/ds1820_mstr.vhd
0,0 → 1,266
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ds1820_mstr.vhd
-- description: interfaces to the ds1820 devices on the one wire bus.
-- this includes discovering the devices, configuring them, and reading the temperatures
--
-- The design consists of the following major blocks:
-- ow_mstr - low level interface to the one wire bus including byte and bit accesses
-- ow_search - discovers devices on the one wire bus, both ds1820 types and others
-- ow_temp - configures the ds1820 devices on the bus and reads the temperatures
-- ow_idram - a ram for storing the 64 bit long device ids
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ds1820_mstr is
port (
--global signals
clk : in std_logic;
srst : in std_logic; --synchronous reset
stb1us : in std_logic; --1us strobe, used to time transactions
busy : out std_logic; --device is in middle of read,write or init
err : out std_logic; --something went wrong, this is cleared by next command
--controls from upper level of hierarchy
search_stb : in std_logic; --searches for devices on bus
temp_init : in std_logic; --starts initialization of all sensors
temp_conv : in std_logic; --starts temperature conversion on all sensors
temp_read : in std_logic; --starts temperature read from all sensors
--response to upper level of hierarchy
temp : out signed(15 downto 0); --temperature of the current sensor
tempidx : out unsigned(4 downto 0); --index of the current temp sensor
tempstb : out std_logic; --temperature available strobe
--one wire bus interface
owin : in std_logic; --one wire input
owout : out std_logic --one wire output
--dio : inout std_logic
);
end ds1820_mstr;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ds1820_mstr is
--bit module signals
type s16ary is array (integer range <>) of signed(15 downto 0);
signal ow_zbit : std_logic;
signal ow_rbit : std_logic;
signal ow_obit : std_logic;
signal ow_wbit : std_logic;
signal ow_ibit : std_logic;
signal ow_rbyte : std_logic;
signal ow_obyte : std_logic_vector(7 downto 0);
signal ow_wbyte : std_logic;
signal ow_ibyte : std_logic_vector(7 downto 0);
signal ow_busy : std_logic;
signal ow_ppwr : std_logic;
--search module signals
signal ows_wbit : std_logic;
signal ows_obit : std_logic;
signal ows_rbit : std_logic;
signal ows_zbit : std_logic;
signal ows_busy : std_logic;
signal ows_err : std_logic;
signal ows_wbyte : std_logic;
signal ows_obyte : std_logic_vector(7 downto 0);
signal ows_idnum : std_logic_vector(4 downto 0);
signal ows_idbit : std_logic_vector(5 downto 0);
 
--temp module signals
signal owt_wbit : std_logic;
signal owt_obit : std_logic;
signal owt_zbit : std_logic;
signal owt_busy : std_logic;
signal owt_err : std_logic;
signal owt_wbyte : std_logic;
signal owt_obyte : std_logic_vector(7 downto 0);
signal owt_rbyte : std_logic;
signal owt_idnum : std_logic_vector(4 downto 0);
signal owt_idbit : std_logic_vector(5 downto 0);
 
signal id_we : std_logic;
signal id_ibit : std_logic;
signal id_obit : std_logic;
signal id_num : std_logic_vector(4 downto 0);
signal id_bit : std_logic_vector(5 downto 0);
--byte module signals
signal ow8_rbit : std_logic;
signal ow8_wbit : std_logic;
begin
-------------------------------------
-- signal decoding ---
-------------------------------------
-- ows is the search module, owt is the temp module
-- rbit, rbyte, wbit, wbyte are the read and write strobes that initiate commands
-- ibit,obit, ibyte, obyte are the bit and byte input and output values
-- the following signals are muxed with priorities, allowing both the temperture and search modules
-- (owt and ows) to control the one wire interface.
ow_rbit <= ows_rbit;
ow_wbit <= ows_wbit when ows_busy = '1' else owt_wbit;
ow_ibit <= ows_obit when ows_busy = '1' else owt_obit;
ow_zbit <= ows_zbit when ows_busy = '1' else owt_zbit;
ow_wbyte <= ows_wbyte when ows_busy = '1' else owt_wbyte;
ow_ibyte <= ows_obyte when ows_busy = '1' else owt_obyte;
ow_rbyte <= owt_rbyte;
id_bit <= ows_idbit when ows_busy = '1' else owt_idbit ;
id_num <= ows_idnum when ows_busy = '1' else owt_idnum ;
 
-------------------------------------
-- one wire controller ---
-------------------------------------
--ow_mstr - interfaces to the one wire bus, handles reset, rd/wr byte, rd/wr bit
u_onewire : entity work.ow_mstr(rtl)
port map (
--global signals
clk => clk,
srst => srst,
stb1us => stb1us, -- 1us timing strobe
busy => ow_busy, --indicates the one wire interface is busy
init_stb => ow_zbit, --sends an init/reset pulse to bus
wrbit => ow_wbit, --write a single bit to the bus
inbit => ow_ibit, --data bit to write
rdbit => ow_rbit, --read a single bit from the bus
outbit => ow_obit, --read bit
wrbyte => ow_wbyte, --write a byte to the bus
inbyte => ow_ibyte, --data byte to write
rdbyte => ow_rbyte, --read a byte from the bus
outbyte => ow_obyte, --read byte
--one wire bus interface
owin => owin, --one wire input
owout => owout --one wire output
);
-------------------------------------
-- search controller ---
-------------------------------------
--ow_search - searches the one wire bus for all the one wire devices
-- this detects the ds1820 temp sensors and other devices with 64 bit ids
u_ows : entity work.ow_search(rtl)
port map (
--global signals
clk => clk,
srst => srst,
start => search_stb, --iniitates the ow bus search for devices
busyin => ow_busy, --(input) indicates the ow_mstr is busy
busy => ows_busy, --(output) indicates the search is busy
error => ows_err, --the search algorithm hit a snag
--ow1 & ow8 interfaces
rdbit => ows_rbit, --read command to ow1
wrbit => ows_wbit, --write command to ow1
zzbit => ows_zbit, --reset pulse command to ow1
obit => ows_obit, --write value to ow1
ibit => ow_obit, --value read from ow1
wrbyte => ows_wbyte, --write command to ow8
obyte => ows_obyte, --write value to ow8
--id ram interface,
id_num => ows_idnum, --current device index (0=31)
id_bit => ows_idbit, --current bit index (0-63)
id_rbit => id_obit, --bit read from RAM
id_wbit => id_ibit, --bit written to RAM
id_we => id_we --write enable to RAM
 
);
 
-------------------------------------
-- temp sensor controller ---
-------------------------------------
--ow_temp - handles the temperature reading from devices.
--performs initialization, conversion start, and read back of results.
u_owt : entity work.ow_temp(rtl)
port map (
--globals
clk => clk,
srst => srst,
busyin => ow_busy, --(input) os_mstr is busy
--signals to upper layer hierarchy
init => temp_init, --command strobe to initialize sensors
conv => temp_conv, --command strobe to start conversions
read => temp_read, --command strobe to read the temps
busy => owt_busy, --(output) temp module is busy
error => owt_err, --indicates temp module error
--temp values output on a muxed bus
temp => temp, --output temp value
tempidx => tempidx, --temp index
tempstb => tempstb, --temp strobe
--ow1 and ow8 interfaces
zzbit => owt_zbit, --reset pulse command to ow1
wrbit => owt_wbit, --write command to ow1
obit => owt_obit, --write value to ow1
ibit => ow_ibit, --value read from ow1
wrbyte => owt_wbyte, --write command to ow8
rdbyte => owt_rbyte, --read command to ow8
ibyte => ow_obyte, --read value from ow8
obyte => owt_obyte, --write value to ow8
--id ram interface,
id_num => owt_idnum, --current device index (0=31)
id_bit => owt_idbit, --current bit index (0-63)
id_rbit => id_obit --bit read from RAM
);
-------------------------------------
-- ID RAM ---
-------------------------------------
-- ow_idram - store and recalls the device ids for devices on the ow bus.
-- this is implemented in a seperate module to ensure that it uses a internal ram
-- which greatly reduces the FPGA utilization (saves a lot of FFs and LUTs)
u_idram : entity work.ow_idram(rtl)
port map(
--globals
clk => clk,
--srst => srst,
--ram signals
mode => ows_busy, --1=search,0=other, used to compute read addresses
idnum => id_num, --index of the id to read or write
idbit => id_bit, --index of the bit within the id to read or write
we => id_we, --write the currently indexed bit
wdat => id_ibit, --bit value to write to the currently indexed bit
rdat => id_obit --bit value of the currently indexed bit
);
-- crc8 - computes the CRC for the ow command and responses.
-- not yet implemented
--u_crc : entity work.crc8(rtl)
--port map (
-- clk => clk,
-- srst => srst,
-- clken => stb1us,
-- crcen => owc_en,
-- crcclr => ow1_init,
-- rdstb => ow1_rbit,
-- busyin => ow1_busy,
-- din => ow1_odat,
-- crc => owc_crc
--);
err <= ows_err or owt_err;
busy <= owt_busy or ows_busy;
end rtl;
/trunk/HDL/ds1820_mstr_tb.vhd
0,0 → 1,318
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ds1820_mstr_tb.vhd
-- description: Testbench for both the ow_mstr and ds1820_mster modules
--
-------------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use ieee.std_logic_textio.all;
library std;
use STD.textio.all;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ds1820_mstr_tb is
end ds1820_mstr_tb;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture sim of ds1820_mstr_tb is
 
-------------------------------------
-- Check Temps Proceedure ---
-------------------------------------
--check_temp - proceedure to check the output data, temp and tempidx, against expected values
procedure check_temp (
signal temp : in signed(15 downto 0); --the temp reported from the DUT
signal idx : in unsigned(4 downto 0); --the index of the sensor (sensor number) from the DUT
exptemp : in signed(15 downto 0); --expected temperature value
expidx : in unsigned(4 downto 0)) --expected index value
is
variable myline : line;
variable dec : integer;
variable frac : integer;
begin
--line := "";
if idx /= expidx then
write(myline,string'("Error: wrong idx, expected "));
write(myline,to_integer(expidx));
write(myline,string'(", got "));
write(myline,to_integer(idx));
writeline(output,myline);
assert false report "bad tempidx value" severity error;
end if;
if temp /= exptemp then
--write(output, std_logic_vector(temp));
write(myline,string'("Error: wrong temp on sensor "));
write(myline,to_integer(expidx));
write(myline,string'(", expected "));
dec := to_integer(exptemp) / 16;
frac := ((to_integer(exptemp) - 16*dec)*100)/16;
write(myline,dec);
write(myline,string'("."));
write(myline,frac);
write(myline,string'(", got "));
dec := to_integer(temp) / 16;
frac := ((to_integer(temp) - 16*dec)*100)/16;
write(myline,dec);
write(myline,string'("."));
write(myline,frac);
write(myline,string'(", got "));
writeline(output,myline);
assert false report "bad temp value" severity error;
end if;
end procedure check_temp;
-------------------------------------------
--- Signal declaration ---
-------------------------------------------
constant clkfreqmhz : integer := 100; --clock frequency in mhz
constant halfperiodns : time := 1000 ns /(clkfreqmhz*2);--half the clock period
signal clk : std_logic;
constant CONVERSION_TIME : integer := 188; --ADC conversion time in ms
signal srst : std_logic := '0'; --synchronous reset
signal rst_cntr : unsigned(7 downto 0):= x"ff";
signal stb1us_cntr : integer range 1 to clkfreqmhz := 1; --counter used to generate stb1us
signal stb1us : std_logic := '0'; --strobe 1 us, goes high for one clock every 1 us
 
signal search_init : std_logic := '0'; --triggers the search module
signal temp_init : std_logic := '0'; --triggers the initialization module
signal temp_conv : std_logic := '0'; --triggers the temperature conversion
signal temp_read : std_logic := '0'; --triggers the reading of the temperature results
signal ow_busy : std_logic; -- the one wire bus is busy
signal ow_err : std_logic; --there is an error on the one wire bus
signal temp : signed(15 downto 0); --signed temp from sensor, value is 16 times the temp in C
signal tempidx : unsigned(4 downto 0); --index of the current temp sensor
signal tempstb : std_logic; --strobe to indicate an updated temp sensor value
signal owin : std_logic; --one wire input to dut
signal owout : std_logic; --one wire output from dut
signal dio : std_logic; --one wire bus
 
begin
 
-------------------------------------
-- global timing signals ---
-------------------------------------
 
p_osc : process
begin
clk <= '0';
wait for halfperiodns;
clk <= '1';
wait for halfperiodns;
end process p_osc;
p_rst : process
begin
srst <= '1';
wait for 5 us;
wait until clk = '1';
srst <= '0';
wait;
end process p_rst;
 
--generate a 1 us strobe for timing
p_stb1us : process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
stb1us <= '0';
stb1us_cntr <= 1;
else
if stb1us_cntr = clkfreqmhz then
stb1us <= '1';
stb1us_cntr <= 1;
else
stb1us <= '0';
stb1us_cntr <= stb1us_cntr + 1;
end if;
end if;
end if;
end process p_stb1us;
 
-------------------------------------
-- DUT ---
-------------------------------------
--ow_mstr - DUT (device under test)
-- one wire master - this performs all the one wire logic
-- such as configuring and reading the DS1820 devices
u_dut : entity work.ds1820_mstr(rtl)
port map(
--global signals
clk => clk,
srst => srst,
stb1us => stb1us, --1 us strobe
busy => ow_busy,
err => ow_err,
--high level interfaces, lets this module do the heavy lifting. For microprocessor control,
search_stb => search_init, --searches for devices on bus
temp_init => temp_init, --initiates temperature read from all devices
temp_conv => temp_conv, --initiates temperature read from all devices
temp_read => temp_read, --initiates temperature read from all devices
temp => temp, --temperatures read from temp devices
tempidx => tempidx, --temperatures index
tempstb => tempstb, --temperatures ready strobe
--one wire bus interface, requires external 5k resistor on bus
owin => owin, --one wire input
owout => owout --one wire output
);
 
-----------------------------------------
-- one wire bus, open collector ---
-----------------------------------------
--handle in/out nature of one wire interface
dio <= '0' when owout = '0' else 'Z'; --output, only drives low, tristates when not low, external 5k pullup
owin <= '0' when dio = '0' else '1'; --input, make sure H,Z,1 all map to '1' for simulation
dio <= 'H'; --simulates the external pullup resistor
-----------------------------------------
-- test bench control and checks ---
-----------------------------------------
--p_control - controls the testing, initiates commands to the DUT
p_control : process
begin
search_init <= '0'; --searches for devices on bus
temp_init <= '0'; --initiates temperature read from all devices
temp_conv <= '0'; --initiates temperature read from all devices
temp_read <= '0'; --initiates temperature read from all devices
--wait for reset and a bit of time to settle
wait for 10 us;
--initiate a search of the one wire devices on the bus
wait until clk = '0';
search_init <= '1';
wait until clk = '0';
search_init <= '0';
wait until clk = '0';
--wait for search to complete
wait until ow_busy = '0';
wait until clk = '0';
--initialize all the temperature sensors on the bus
wait until clk = '0';
temp_init <= '1';
wait until clk = '0';
temp_init <= '0';
wait until clk = '0';
--wait for search to complete
wait until ow_busy = '0';
wait for 5 us;
--start conversions on all the sensors
wait until clk = '0';
temp_conv <= '1';
wait until clk = '0';
temp_conv <= '0';
wait until clk = '0';
--wait for conversion commands to complete
wait until ow_busy = '0';
--now wait until the conversions are actually complete
wait for 190 ms;
--read the temp from all the sensors
wait until clk = '0';
temp_read <= '1';
wait until clk = '0';
temp_read <= '0';
wait until clk = '0';
--wait for all reads to take place
wait until ow_busy = '0';
wait until clk = '0';
--now wait until the conversions are actually complete
wait;
end process p_control;
--p_check - checks the output of the DUT and alerts if it is incorrect
p_check : process
variable exptemp : signed(15 downto 0);
variable expidx : unsigned(4 downto 0);
begin
--check data from sensor 1
wait until tempstb = '1';
exptemp := to_signed(-24,16); -- -1.5C
expidx := to_unsigned(0,5);
check_temp(temp,tempidx,exptemp,expidx);
--check data from sensor 2
wait until tempstb = '1';
exptemp := to_signed(1844,16); -- +115.25C
expidx := to_unsigned(1,5);
check_temp(temp,tempidx,exptemp,expidx);
--check data from sensor 2
wait until tempstb = '1';
exptemp := to_signed(916,16); -- +57.25C
expidx := to_unsigned(2,5);
check_temp(temp,tempidx,exptemp,expidx);
wait for 5 us;
assert false report "Test completed" severity note;
wait;
end process;
 
p_error : process
begin
wait until ow_err = '1';
assert true report "Bus error reported" severity error;
end process;
 
--------------------------------------------
-- Simulated OW bus devices, ds1820 ---
--------------------------------------------
--simulated temperature sensor
u_ds18b20_1 : entity work.ds18b20_sim(sim)
generic map (
timing => "min",
devid => x"00a0458d3ea2be28"
)
port map (
--dio => dio1,
pwrin => '1',
dio => dio,
tempin => -1.54
);
 
--simulated temperature sensor
u_ds18b20_2 : entity work.ds18b20_sim(sim)
generic map (
timing => "min",
devid => x"002984456a32bf28"
)
port map (
--dio => dio2,
pwrin => '1',
dio => dio,
tempin => 115.3
);
 
--simulated temperature sensor
u_ds18b20_3 : entity work.ds18b20_sim(sim)
generic map (
timing => "min",
devid => x"0083726dab32bf28"
)
port map (
--dio => dio3,
pwrin => '1',
dio => dio,
tempin => 57.25
);
 
end sim;
/trunk/HDL/ds18b20_sim.vhd
0,0 → 1,676
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ds18b20_sim.vhd
-- description: A simulation model for the DS18B20 temperature probe
--
-- Generics are used to set the device ID, the NVROM, and the timing model
-- inputs are used to set the temperature to report back
--
-- This only simulates the SEARCH, ROM, SKIP, CONFIG, CONV, and READ commands
-- save and recall to/from EEPROM were started, but not tested
-- it is not a complete model. It does not validate timing.
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ds18b20_sim is
generic (
timing : in string := "ave";
devid : in std_logic_vector(63 downto 0) := x"0000000000000128";
nvrom : in std_logic_vector(23 downto 0) := x"3f0064"
);
port (
--global signals
pwrin : in std_logic; --tie to '1' if power provided, '0' if using parasitic power
tempin : in real;
dio : inout std_logic --synchronous reset
);
end ds18b20_sim;
 
 
--library unisim;
--use unisim.vcomponents.all;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
library work;
 
architecture sim of ds18b20_sim is
 
--low time to trigger a reaset
constant tmin_rstl : time := 240 us;
constant tave_rstl : time := 400 us;
constant tmax_rstl : time := 480 us;
signal trstl : time := tmin_rstl;
--high time between reset pulse and presence pulse
signal tpdih : time;
constant tmin_pdih : time := 15 us;
constant tave_pdih : time := 45 us;
constant tmax_pdih : time := 60 us;
--presence pulse low time
signal tpdlo : time;
constant tmin_pdlo : time := 60 us;
constant tave_pdlo : time := 180 us;
constant tmax_pdlo : time := 240 us;
--write 0 low time
signal tlow0 : time;
constant tmin_low0 : time := 60 us;
constant tave_low0 : time := 100 us;
constant tmax_low0 : time := 120 us;
--write 1 low time
signal tlow1 : time;
constant tmin_low1 : time := 1 us;
constant tave_low1 : time := 10 us;
constant tmax_low1 : time := 15 us;
--master write data sample time
signal tsamp : time := 1 us;
constant tmin_samp : time := 15 us;
constant tave_samp : time := 30 us;
constant tmax_samp : time := 60 us;
--slave read recovery time
signal trec : time := 1 us;
constant tmin_rec : time := 1 us;
constant tave_rec : time := 3 us;
constant tmax_rec : time := 6 us;
--slave read data valid time
signal trdv : time := 15 us;
constant tmin_rdv : time := 15 us;
constant tave_rdv : time := 30 us;
constant tmax_rdv : time := 60 us;
 
--recall from eeprom timing
--note: dallas part does not spec this timing
signal trecall : time := 100 us;
 
--convert time
signal tconv : time := 15 us;
signal tconv9 : time := 15 us;
constant tmax_conv9 : time := 93.75 us;
constant tave_conv9 : time := tmax_conv9 * 2/3;
constant tmin_conv9 : time := tmax_conv9 * 1/2;
signal tconv10 : time := 15 us;
constant tmax_conv10 : time := 93.75 us;
constant tave_conv10 : time := tmax_conv10 * 2/3;
constant tmin_conv10 : time := tmax_conv10 * 1/2;
signal tconv11 : time := 15 us;
constant tmax_conv11 : time := 93.75 us;
constant tave_conv11 : time := tmax_conv11 * 2/3;
constant tmin_conv11 : time := tmax_conv11 * 1/2;
signal tconv12 : time := 15 us;
constant tmax_conv12 : time := 93.75 us;
constant tave_conv12 : time := tmax_conv12 * 2/3;
constant tmin_conv12 : time := tmax_conv12 * 1/2;
signal tcopy : time := 1 us;
constant tmax_copy : time := 10 ms;
constant tave_copy : time := 2 ms;
constant tmin_copy : time := 1 ms;
 
signal clk10m : std_logic;
signal rstdet : std_logic := '0'; --indicates a detected a reset pulse from the master
signal trise : time := now;
signal tfall : time := now;
signal rstdly : std_logic := '1';
--signal tdif : time;
signal timertime : time;
signal timer : unsigned(15 downto 0);
signal timertrig : std_logic := '0';
signal timerdone : std_logic := '1';
 
 
type state_type is (S_IDLE, S_RSTRESP,S_RSTRESP2,S_RSTRESP3,
S_GETBYTE, S_GETBYTE2, S_PARSE,
S_READROM, S_READROM2, S_SRCHROM, S_SRCHROMNOT, S_SRCHROMWR,
S_MATCHROM, S_MATCHROM2, S_SRCHALARM, S_SKIPROM,
S_PARSE2, S_CONV, S_COPY, S_WRITE1, S_WRITE2, S_WRITE3,
S_READ, S_READRCVR, S_CRC, S_RECALL, S_RDPWR,
S_START, S_MID, S_END);
signal state : state_type := S_IDLE;
signal nxt_state : state_type := S_IDLE;
signal dout : std_logic := 'Z'; --read output bit from slave to master
signal rstdout : std_logic := '1'; --read output bit from main process
signal recalldout : std_logic := '1'; --read output bit from recall process
signal copydout : std_logic := '1'; --read output bit from copy process
signal convdout : std_logic := '1'; --read output bit from conv process
signal readdout : std_logic := '1'; -- output data from read state machine
signal din : std_logic := '1'; --resolved input data bit
--signal rstout : std_logic := 'Z';
signal bitcnt : integer;
signal shiftbyte : std_logic_vector(7 downto 0);
signal shiftid : std_logic_vector(63 downto 0);
signal busy : std_logic := '0';
 
--These signals are for the read state machine
signal bitout : std_logic := '1'; --bit value to be read by master
signal wrbitin : std_logic := '0'; -- the bit value written by the master
signal wrbiterr : std_logic := '0'; -- indicates a master write pulse with an illegal timing
signal writedet : std_logic := '0'; -- strobe indicating the master wrote a bit
signal readen : std_logic := '0'; --enables the slave responses to the master read pulses
signal readdet : std_logic := '0'; -- strobe indicating the master read a bit
signal readdly : std_logic := '0'; -- delayed version of din for detecting read strobes
signal readbit : std_logic := '0'; -- data to output from read state machine
--signal readbit : std_logic := '0'; -- bit to drive the read output
 
signal res : integer range 9 to 12; --high alram value in volatile mem
signal alarmhi : std_logic := '0';
signal alarmlo : std_logic := '0';
signal trighi : std_logic_vector(7 downto 0) := nvrom(7 downto 0);
signal triglo : std_logic_vector(7 downto 0) := nvrom(15 downto 8);
--signal temp : std_logic_vector(15 downto 0); --last temperature conversion
signal slvtemp : std_logic_vector(15 downto 0) := x"0190"; --the temperature read from device, default to 25C
signal config : std_logic_vector(7 downto 0) := nvrom(23 downto 16);
signal convtrig : std_logic := '0';
signal convdone : std_logic := '1';
signal copytrig : std_logic := '0';
signal copydone : std_logic := '1';
signal recalltrig : std_logic := '0';
signal recalldone : std_logic := '1';
signal eeprom : std_logic_vector(23 downto 0) := nvrom;
signal scratch : std_logic_vector(63 downto 0) := x"1000ff" & nvrom & x"0000";
 
signal crc : std_logic_vector(7 downto 0);
begin
trstl <= tmin_rstl when timing = "MIN" else tave_rstl when timing = "AVE" else tmax_rstl;
tpdih <= tmin_pdih when timing = "MIN" else tave_pdih when timing = "AVE" else tmax_pdih;
tpdlo <= tmin_pdlo when timing = "MIN" else tave_pdlo when timing = "AVE" else tmax_pdlo;
tsamp <= tmin_samp when timing = "MIN" else tave_samp when timing = "AVE" else tmax_samp;
trdv <= tmin_rdv when timing = "MIN" else tave_rdv when timing = "AVE" else tmax_rdv;
tconv9 <= tmin_conv9 when timing = "MIN" else tave_conv9 when timing = "AVE" else tmax_conv9;
tconv10 <= tmin_conv10 when timing = "MIN" else tave_conv10 when timing = "AVE" else tmax_conv10;
tconv11 <= tmin_conv11 when timing = "MIN" else tave_conv11 when timing = "AVE" else tmax_conv11;
tconv12 <= tmin_conv12 when timing = "MIN" else tave_conv12 when timing = "AVE" else tmax_conv12;
tconv <= tconv9 when res = 9 else tconv10 when res=10 else tconv11 when res = 11 else tconv12;
tcopy <= tmin_copy when timing = "MIN" else tave_copy when timing = "AVE" else tmax_copy;
--rstdly <= dio after trstl;
--rst <= '1' when rstdly = '0' and dio = '0' else '1';
 
res <= 9 + to_integer(unsigned(config(6 downto 5)));
 
p_clk10m : process
begin
clk10m <= '0';
wait for 50 ns;
clk10m <= '1';
wait for 50 ns;
end process;
 
p_edges : process
begin
wait until din = '0';
tfall <= now;
wait until din = '1';
trise <= now;
end process;
 
 
--this handles the master reseting this slave
rstdly <= transport din after trstl;
 
p_rst : process
begin
wait until rstdly = '0';
--if last transition was falling edge and it was long ago...
if tfall > trise and now - tfall >= trstl then
rstdet <= '1';
wait until din <= '1';
rstdet <= '0';
end if;
end process;
 
--p_readstb and p_read - work together to facilitate a read
-- readen is set high to enable a read, then if din is low for 1 us the readdet signal triggers
-- which causes readout to be driven low for a bit time if shift(0) is low
-- after the bit time expires, din returns high, causing readdet to go low, and cycle is complete
readdly <= transport din after 1us;
p_readstb : process
begin
wait until readdly = '0';
if tfall > trise and now - tfall >= 1us and readen = '1' then
readdet <= '1';
wait until din <= '1';
readdet <= '0';
end if;
end process;
 
p_read : process
begin
wait until readdet = '1' and readen = '1';
readdout <= readbit;
wait for trdv;
readdout <= '1';
end process;
 
--this handles the master writing bits to this slave
p_write : process
begin
wait until din = '1';
--dont detect writes during read operations
if readen = '0' and readdet = '0' then
if now - tfall > tmin_low0 and now-tfall < tmax_low0 then
wrbitin <= '0';
writedet <= '1';
wrbiterr <= '0';
elsif now - tfall > tmin_low1 and now-tfall < tmax_low1 then
wrbitin <= '1';
writedet <= '1';
wrbiterr <= '0';
elsif now - tfall < trstl then
wrbiterr <= '1';
end if;
end if;
wait until din = '0';
writedet <= '0';
end process;
 
 
p_timer : process(clk10m)
begin
if rising_edge(clk10m) then
if timertrig = '1' then
timer <= to_unsigned(integer(timertime/100 ns),16);
timerdone <= '0';
elsif timer > 1 then
timer <= timer -1;
else
timerdone <= '1';
end if;
end if;
end process;
 
--this handles the master reading a bit from this slave
--dout <= '0' when rdbiten = '1' and dout = '0' and now-tfall < trdv else '1';
 
p_state :process(clk10m)
begin
if rising_edge (clk10m) then
if rstdet = '1' then
state <= S_RSTRESP;
rstdout <= '1';
readen <= '0';
else
case state is
when S_IDLE =>
rstdout <= '1';
readen <= '0';
bitcnt <= 0;
convtrig <= '0';
copytrig <= '0';
recalltrig <= '0';
shiftbyte <= x"00";
shiftid <= devid;
when S_RSTRESP =>
readen <= '0';
bitcnt <= 0;
rstdout <= '1';
shiftbyte <= x"00";
shiftid <= devid;
if timertrig = '0' and din = '1' then
timertime <= tpdih;
timertrig <= '1';
elsif timertrig = '1' then
timertrig <= '0';
state <= S_RSTRESP2;
end if;
when S_RSTRESP2 =>
if timertrig = '0' and timerdone = '1' then
rstdout <= '0';
timertime <= tpdlo;
timertrig <= '1';
elsif timertrig = '1' then
timertrig <= '0';
state <= S_RSTRESP3;
end if;
when S_RSTRESP3 =>
if timerdone = '1' then
rstdout <= '1';
state <= S_GETBYTE;
nxt_state <= S_PARSE;
end if;
when S_GETBYTE =>
if writedet = '0' then
state <= S_GETBYTE2;
end if;
when S_GETBYTE2 =>
if writedet = '1' then
shiftbyte <= wrbitin & shiftbyte(7 downto 1);
if bitcnt < 7 then
bitcnt <= bitcnt + 1;
state <= S_GETBYTE;
else
bitcnt <= 0;
state <= nxt_state;
end if;
end if;
when S_PARSE =>
shiftid <= devid;
case shiftbyte is
when x"33" => --read the rom id from the device, can only be used on single device bus
state <= S_READROM;
when x"55" => --match rom, used to address a single device on the bus
state <= S_MATCHROM;
when x"F0" => --use to find the devices on a multiple device bus
state <= S_SRCHROM;
when x"EC" => --search alarm, used to find devices that have active alarms
if alarmhi = '1' or alarmlo = '1' then
state <= S_SRCHROM;
else
state <= S_IDLE;
end if;
when x"CC" => --skip rom, skips rom addressing, for single device busses or broadcast commands
state <= S_GETBYTE;
nxt_state <= S_PARSE2;
when others =>
state <= S_IDLE;
end case;
when S_READROM =>
readen <= '1';
if readdet = '1' then
shiftid <= shiftid(0) & shiftid(63 downto 1);
if bitcnt < 55 then
bitcnt <= bitcnt + 1;
state <= S_READRCVR;
nxt_state <= S_READROM;
else
state <= S_CRC;
nxt_state <= S_READROM2;
shiftid <= x"00000000000000" & crc;
end if;
end if;
when S_READROM2 =>
state <= S_GETBYTE;
nxt_state <= S_PARSE2;
when S_MATCHROM =>
if writedet = '0' then
state <= S_MATCHROM2;
end if;
when S_MATCHROM2 =>
if writedet = '1' then
if wrbitin /= shiftid(0) then
state <= S_IDLE; --this part is removed from search, goto idle, wait for rstdet
else
shiftid <= shiftid(0) & shiftid(63 downto 1);
if bitcnt < 63 then
bitcnt <= bitcnt + 1;
state <= S_MATCHROM;
else
bitcnt <= 0;
state <= S_GETBYTE;
nxt_state <= S_PARSE2;
end if;
end if;
end if;
when S_SRCHROM =>
readen <= '1';
readbit <= shiftid(0);
if readdet = '1' then
state <= S_READRCVR;
nxt_state <= S_SRCHROMNOT;
end if;
when S_SRCHROMNOT =>
readen <= '1';
readbit <= not shiftid(0);
if readdet = '1' then
state <= S_READRCVR;
nxt_state <= S_SRCHROMWR;
end if;
when S_SRCHROMWR =>
readen <= '0';
if writedet = '1' then
if wrbitin /= shiftid(0) then
state <= S_IDLE; --this part is removed from search, goto idle, wait for rstdet
else
shiftid <= shiftid(0) & shiftid(63 downto 1);
if bitcnt < 63 then
bitcnt <= bitcnt + 1;
state <= S_SRCHROM;
else
bitcnt <= 0;
state <= S_GETBYTE;
nxt_state <= S_PARSE2;
end if;
end if;
end if;
when S_PARSE2 =>
case shiftbyte is
when x"44" => --convert temp
convtrig <= '1';
state <= S_CONV;
when x"48" => --copy scratchpad to eeprom
copytrig <= '1';
state <= S_COPY;
when x"4e" => --write scratchpad
state <= S_GETBYTE; -- data in order is Thi,Tlo,config
nxt_state <= S_WRITE1;
when x"be" => --read scratchpad
state <= S_READ; --data in order is TempLSB,TempMSB,AlarmHi,AlarmLo,config,FF,00,F0,CRC
shiftid <= x"1000ff" & config & trighi & triglo & slvtemp;
bitcnt <= 0;
when x"b8" => --recall scratchpad from eeprom
recalltrig <= '1';
state <= S_RECALL;
when x"b4" => --read the power bit to determine if parasitic;y powered
state <= S_RDPWR;
when others =>
state <= S_IDLE;
end case;
when S_CONV =>
if convtrig = '1' then
convtrig <= '0';
elsif convdone = '1' then
state <= S_IDLE;
end if;
when S_COPY =>
if copytrig = '1' then
copytrig <= '0';
elsif copydone = '1' then
state <= S_IDLE;
end if;
when S_WRITE1 =>
scratch(7 downto 0) <= shiftbyte;
state <= S_GETBYTE;
nxt_state <= S_WRITE2;
when S_WRITE2 =>
scratch(15 downto 8) <= shiftbyte;
state <= S_GETBYTE;
nxt_state <= S_WRITE3;
when S_WRITE3 =>
scratch(23 downto 16) <= '0' & shiftbyte(6 downto 5) & "11111";
state <= S_IDLE;
when S_RECALL =>
if recalltrig = '1' then
recalltrig <= '0';
elsif recalldone = '1' then
config <= eeprom(23 downto 16);
trighi <= eeprom(15 downto 8);
triglo <= eeprom(7 downto 0);
state <= S_IDLE;
end if;
when S_READ =>
readen <= '1';
readbit <= shiftid(0);
if readdet = '1' then
shiftid <= shiftid(0) & shiftid(63 downto 1);
if bitcnt < 63 then
bitcnt <= bitcnt + 1;
state <= S_READRCVR;
nxt_state <= S_READ;
else
state <= S_CRC;
nxt_state <= S_IDLE;
bitcnt <= 0;
shiftid <= x"00000000000000" & crc;
end if;
end if;
when S_READRCVR =>
readen <= '0';
if readdet = '0' then
state <= nxt_state;
end if;
when S_RDPWR =>
readen <= '1';
if readdet = '1' then
state <= S_READRCVR;
nxt_state <= S_IDLE;
end if;
when S_CRC =>
readen <= '1';
if readdet = '1' then
shiftid <= shiftid(0) & shiftid(63 downto 1);
if bitcnt < 7 then
bitcnt <= bitcnt + 1;
state <= S_READRCVR;
nxt_state <= S_READ;
else
state <= S_READRCVR;
nxt_state <= S_IDLE;
bitcnt <= 0;
shiftid <= x"00000000000000" & crc;
end if;
end if;
when others =>
state <= S_IDLE;
end case;
end if;
end if;
end process;
 
p_crc : process
begin
crc <= x"00";
wait until state = S_READ or state = S_READROM;
crc <= x"00";
while state = S_READ or state = S_READROM loop
wait until din = '0' or (state /= S_READ and state /= S_READROM);
if din = '0' then
if (crc(0) xor shiftid(0)) = '1' then
crc <= ('0' & crc(7 downto 1)) xor x"8c";
else
crc <= ('0' & crc(7 downto 1));
end if;
end if;
end loop;
end process;
 
 
p_convert : process
variable tstart : time := 0 us;
begin
convdout <= '1';
convdone <= '1';
wait until convtrig = '1';
convdone <= '0';
tstart := now;
while state = S_CONV loop
assert (din = '1' or pwrin = '1') report "power fail during parasitic powered conversion" severity error;
wait for 1 us;
if now - tstart > tconv then
convdone <= '1';
if res = 9 then
slvtemp <= std_logic_vector(to_signed(integer(tempin*2.0),13)) &"000";
elsif res = 10 then
slvtemp <= std_logic_vector(to_signed(integer(tempin*4.0),14)) &"00";
elsif res = 11 then
slvtemp <= std_logic_vector(to_signed(integer(tempin*8.0),15)) &'0';
else
slvtemp <= std_logic_vector(to_signed(integer(tempin*16.0),16));
end if;
if signed(slvtemp(11 downto 4)) < signed(trighi) then
alarmhi <= '0';
else
alarmhi <= '1';
end if;
if signed(slvtemp(11 downto 4)) > signed(triglo) then
alarmlo <= '0';
else
alarmlo <= '1';
end if;
elsif rstdet = '1' then
convdone <= '1';
elsif din = '0' and pwrin = '1' then
--master is reading convert ready bit
wait for 1 us;
convdout <= '0';
wait for trdv;
convdout <= '1';
end if;
end loop;
end process;
 
p_copy : process
variable tstart : time := 0 us;
begin
copydout <= '1';
wait until copytrig = '1';
copydone <= '0';
tstart := now;
wait for 10 us;
while state = S_COPY loop
assert (din = '1' or pwrin = '1') report "power fail during parasitic powered copy to eeprom" severity error;
wait for 1 us;
if now - tstart > tcopy then
copydone <= '1';
eeprom <= config & trighi & triglo;
elsif rstdet = '1' then
copydone <= '1';
elsif din = '0' then
--master is reading copy ready bit
wait for 1 us;
copydout <= '0';
wait for trdv;
copydout <= '1';
end if;
end loop;
end process;
 
 
 
p_recall : process
variable tstart : time := 0 us;
begin
recalldout <= '1';
wait until recalltrig = '1';
recalldone <= '0';
tstart := now;
wait for 10 us;
while state = S_RECALL loop
assert (din = '1' or pwrin = '1') report "power fail during parasitic recall from eeprom" severity error;
wait for 1 us;
if now - tstart > trecall then
recalldone <= '1';
elsif rstdet = '1' then
recalldone <= '1';
elsif din = '0' then
--master is reading recall ready bit
wait for 1 us;
recalldout <= '0';
wait for trdv;
recalldout <= '1';
end if;
end loop;
end process;
 
din <= '0' when dio = '0' else '1';
dout <= rstdout and copydout and convdout and recalldout and readdout;
dio <= '0' when dout = '0' else 'Z';
busy <= '0' when state = S_IDLE else '1';
 
end sim;
/trunk/HDL/ow_bit.vhd
0,0 → 1,231
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: onewire_bit.vhd
-- description: handles single bit transactions on the one wire bus
-- it is used by higher level entities to initialize, search, read, and write the one
-- wire devices on the one wire bus.
-- Each operation consists of a start, that is always low, middle, which for reads
-- represents the time for the slave to respond, and the end, which allows for
-- the slave to finish its operation and provides spacing between bit patterns.
-- For reads and resets, the data is sampled at the end of the mid time
--
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
library work;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_bit is
port (
--globals
clk : in std_logic;
srst : in std_logic;
clken : in std_logic;
--interface to higher level
rstb : in std_logic;
wstb : in std_logic;
istb : in std_logic;
din : in std_logic;
dout : out std_logic;
busy : out std_logic;
--one wire bus
owout : out std_logic; --one wire input
owin : in std_logic --one wire output
);
end ow_bit;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_bit is
type pulse_state_type is (S_IDLE, S_START, S_MID, S_END); --, S_DONE
signal pulse_state : pulse_state_type := S_IDLE;
 
constant r_start : unsigned(11 downto 0) := to_unsigned(5,12); --low time
constant r_mid : unsigned(11 downto 0) := to_unsigned(10,12); --high z until sample time
constant r_end : unsigned(11 downto 0) := to_unsigned(65,12); --recovery time
constant w_start : unsigned(11 downto 0) := to_unsigned(5,12); --low time
constant w_mid : unsigned(11 downto 0) := to_unsigned(65,12); --dout time
constant w_end : unsigned(11 downto 0) := to_unsigned(10,12); --recovery time
constant rw_cnt : unsigned(11 downto 0) := to_unsigned(1,12); --number of samples for read or write
constant i_start : unsigned(11 downto 0) := to_unsigned(500,12); --reset low time
constant i_mid : unsigned(11 downto 0) := to_unsigned(100,12); --high z till sample time
constant i_end : unsigned(11 downto 0) := to_unsigned(220,12); --recovery time till end of rst response
constant i_cnt : unsigned(3 downto 0) := to_unsigned(1,4); --number of samples (i_end each) to wait for init response
 
signal start_time : unsigned(11 downto 0); -- low pulse time
signal mid_time : unsigned(11 downto 0); -- high pulse time
signal end_time : unsigned(11 downto 0); -- time between samples, or the last sample and the end
--signal rd_count : unsigned(4 downto 0) := to_unsigned(30,5); -- number of read smaples for this bit
signal owo : std_logic := '0'; --one wire output bit
--signal owo2 : std_logic := '0'; --one wire output bit combined with one wire power
--signal owi : std_logic := '0'; --one wire input bit
--signal owt : std_logic := '0'; --one wire tristate, implements open collector bus
signal wstb_cap : std_logic := '0'; --captures and holds write requests
signal rstb_cap : std_logic := '0'; --captures and holds read requests
signal istb_cap : std_logic := '0'; --captures and holds init requests (reset/presence sequence)
signal din_cap : std_logic := '0'; --captures and holds input data
signal pulse_end : std_logic;
signal busy_int : std_logic;
signal timer : unsigned(11 downto 0) := x"000"; --used to time one wire bus transactions
--signal rdcntr : unsigned(4 downto 0); --used to count samples in the read mode
--signal owopwr : std_logic; --internal state of dout combined with power input
signal samp : std_logic; --AND'ed value of owi samples
 
attribute mark_debug : string;
attribute mark_debug of pulse_state : signal is "true";
attribute mark_debug of timer : signal is "true";
attribute mark_debug of samp : signal is "true";
attribute mark_debug of din : signal is "true";
attribute mark_debug of dout : signal is "true";
attribute mark_debug of rstb_cap: signal is "true";
attribute mark_debug of wstb_cap : signal is "true";
attribute mark_debug of istb_cap : signal is "true";
attribute mark_debug of busy_int : signal is "true";
attribute mark_debug of pulse_end : signal is "true";
begin
-------------------------------------
-- strobe captures ---
-------------------------------------
-- p_capstb - captures the pulse strobes, and clears then when the pulse is complete
-- this is necessary if the clken is used because the strobes happen on the system clk and
-- the pulse is timed by the stb1us. We need to hold the strobes throughout the pulse because the active
-- strobe is used to zelect the timing for the pulse.
p_capstb : process (clk)
begin
if rising_edge(clk) then
if srst = '1' then
rstb_cap <= '0';
wstb_cap <= '0';
istb_cap <= '0';
din_cap <= '0';
elsif busy_int = '0' then
if rstb = '1' then
rstb_cap <= '1';
elsif wstb = '1' then
wstb_cap <= '1';
din_cap <= din;
elsif istb = '1' then
istb_cap <= '1';
end if;
elsif pulse_state = S_END then
rstb_cap <= '0';
wstb_cap <= '0';
istb_cap <= '0';
din_cap <= '0';
end if;
end if;
end process p_capstb;
 
-------------------------------------
-- control muxing ---
-------------------------------------
--busy_int indicates that a pulse is pending (one of the strobe captures is high) or the pulse is active
busy_int <= '0' when rstb_cap = '0' and wstb_cap = '0' and istb_cap = '0'
and pulse_state = S_IDLE
else '1';
start_time <= w_start when wstb_cap = '1' else i_start when istb_cap = '1' else r_start;
mid_time <= w_mid when wstb_cap = '1' else i_mid when istb_cap = '1' else r_mid;
end_time <= w_end when wstb_cap = '1' else i_end when istb_cap = '1' else r_end;
 
-------------------------------------
-- pulse generator ---
-------------------------------------
--p_pulse - generates the pulse, and if needed captures the read bit or read presence pulse
-- all pulses consist of a start time, a middle time, and an end time.
-- for read, write, and init, the start time is always low, and starts the timing for the pulse
-- for a read or init, the middle time is used for the slave to react. data is sampled at the end of the mid time
-- for the write, the middle time is where the actual data, zero or one, is output.
-- the end time is used to space between pulses.
-- |start| middle |end|
-- Write one ----_____-------------
-- Write zero ----______________----
-- read ----_____xxxxxxxxx----
-- init ----_____---------____
p_pulse : process (clk)
begin
if rising_edge(clk) then
if srst = '1' then
pulse_state <= S_IDLE;
timer <= x"000";
--rdcntr <= "00000";
owo <= '1';
samp <= '1';
elsif clken = '1' then
case pulse_state is
when S_IDLE =>
samp <= '1';
if busy_int = '1' then
pulse_state <= S_START;
timer <= start_time;
owo <= '0';
end if;
when S_START =>
if timer > 0 then
timer <= timer -1;
else
if wstb_cap = '1' then
owo <= din_cap;
else
owo <= '1';
end if;
timer <= mid_time;
pulse_state <= S_MID;
end if;
when S_MID =>
if timer > 0 then
timer <= timer -1;
else
samp <= owin;
timer <= end_time;
--rdcntr <= rd_count;
pulse_state <= S_END;
owo <= '1';
end if;
when S_END =>
if timer > 0 then
timer <= timer -1;
else
pulse_state <= S_IDLE;
end if;
--when S_DONE =>
-- pulse_state <= S_IDLE;
end case;
end if;
end if;
end process p_pulse;
dout <= samp; --this is the value read back from a read pulse or a reset pulse
busy <= busy_int or rstb or wstb or istb;
 
--The output is driven high when pwr = 1, otherwise is only driven low when owo is low
owout <= owo;
end rtl;
/trunk/HDL/ow_byte.vhd
0,0 → 1,136
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ow_byte.vhd
-- description: handles read and write byte operations on the one wire bus
--
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
library work;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_byte is
port (
--globals
clk : in std_logic;
srst : in std_logic;
--clken : in std_logic;
--ow1 interface
rdbit : out std_logic; -- rd bit strobe
wrbit : out std_logic; -- wr bit strobe
ibit : in std_logic; -- rd bit data
obit : out std_logic; -- wr bit data
busyin : in std_logic; -- busy from the bit interface
--high level interface to owt,owi, or external
rdbyte : in std_logic; -- read byte strobe
obyte : out std_logic_vector(7 downto 0); -- result of the byte read
wrbyte : in std_logic; -- write byte strobe
ibyte : in std_logic_vector(7 downto 0); -- write data
busy : out std_logic -- busy signal the to external modules
);
end ow_byte;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_byte is
type state_type is (S_IDLE, S_STROBE, S_SHIFT);
signal state : state_type := S_IDLE;
 
signal bitcnt : integer range 0 to 7 := 0; --counts the bytes during the transfer
signal shift : std_logic_vector(7 downto 0); -- used to shift in and out data
signal rdwr_n : std_logic; -- 1 for read, 0 for write
signal irdbit : std_logic; -- internal state of rdbit strobe
signal iwrbit : std_logic; -- internal state of wrbit strobe
 
attribute mark_debug : string;
attribute mark_debug of state : signal is "true";
attribute mark_debug of rdwr_n : signal is "true";
attribute mark_debug of shift : signal is "true";
attribute mark_debug of bitcnt : signal is "true";
attribute mark_debug of irdbit : signal is "true";
attribute mark_debug of iwrbit : signal is "true";
begin
-------------------------------------
-- bit shifter ---
-------------------------------------
-- p_shifty - shifts data in and out the shift register, and counts down bits
p_shifty : process (clk)
begin
if rising_edge(clk) then
if srst = '1' then
shift <= (others => '0');
bitcnt <= 0;
rdwr_n <= '1';
irdbit <= '0';
iwrbit<= '0';
state <= S_IDLE;
else
case state is
when S_IDLE =>
--wait for read byte or write byte strobe
if busyin = '0' and (rdbyte = '1' or wrbyte = '1') then
rdwr_n <= rdbyte; --remember whether it was read or write
shift <= ibyte; --load the byte to shift out(not needed for read)
bitcnt <= 0; --set bit counter
state <= S_STROBE;
end if;
when S_STROBE =>
if irdbit = '0' and iwrbit = '0' then
--if we havent started the read or write yet
irdbit <= rdwr_n; --read one bit if it is a read
iwrbit <= not rdwr_n; --write one bit if its a write
else
--if we are the bit operation has already started, clear the strobes
irdbit <= '0';
iwrbit<= '0';
state <= S_SHIFT;
end if;
when S_SHIFT =>
if busyin = '0' then --wait for the bit operation to finish
shift <= ibit & shift(7 downto 1); --shift the bit in or out
if bitcnt = 7 then --check for last bit
state <= S_IDLE; --return to idle when finished
else
bitcnt <= bitcnt +1; --more bits to go, count down bits
state <= S_STROBE; --strobe the next bit operatoin
end if;
end if;
end case;
end if;
end if;
end process p_shifty;
-------------------------------------
-- IO signals ---
-------------------------------------
--copy the internal signals to the external ports
rdbit <= irdbit;
wrbit <= iwrbit;
obit <= shift(0); --the output bit to the ow_bit module
obyte <= shift; --the read byte after shifting in all bits
busy <= '0' when state = S_IDLE and rdbyte = '0' and wrbyte = '0' else '1'; --if we are not idle we are busy
end rtl;
/trunk/HDL/ow_idram.vhd
0,0 → 1,102
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ow_idram.vhd
-- description: stores the list of one wire ids. Each id is 64 bits long. holds upto 32 ids.
-- controls reset the bit counter, inc the bit counter, and write to the current location
--
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
library work;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_idram is
port (
--global signals
clk : in std_logic;
--srst : in std_logic; --synchronous reset
mode : in std_logic; --mode, 1=search, 0=other, used to calc read addr
idnum : in std_logic_vector(4 downto 0); --index of the id to read or write
idbit : in std_logic_vector(5 downto 0); --index of the bit within the id to read or write
we : in std_logic; --write the currently indexed bit
wdat : in std_logic; --bit value to write to the currently indexed bit
rdat : out std_logic --bit value of the currently indexed bit
);
end ow_idram;
 
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_idram is
 
type mem_type is array (2047 downto 0) of std_logic;
signal mem : mem_type ;
attribute syn_ramstyle: string;
attribute syn_ramstyle of mem: signal is "no_rw_check";
signal rd_addr : integer range 0 to 2047;
signal wr_addr : integer range 0 to 2047;
signal mem_rdat : std_logic;
begin
 
 
------------------------------------------------------
-- ADDRESSES ---
------------------------------------------------------
--the read idnum has to be calculated for the search mode. In search, we write to the current id,
-- but read from the previous id. The previous id is needed in order to decide certain branches
-- in the search algorithm. When we are at the 0th id, there is no previous id, so we just override
-- this with zeros.
wr_addr <= to_integer( unsigned(idnum) & unsigned(idbit) );
rd_addr <= to_integer( unsigned(idnum) & unsigned(idbit) ) when mode = '0'
else to_integer( (unsigned(idnum)-1) & unsigned(idbit) );
--if in search mode and there is no previous id, then return '0'
rdat <= '0' when mode = '1' and idnum = "00000" else mem_rdat;
 
------------------------------------------------------
--- WRITE ---
------------------------------------------------------
process (clk) -- Write memory.
begin
if rising_edge(clk) then
if (we = '1') then
--mem(to_integer(unsigned(idnum & idbit))) <= wdat;
mem(wr_addr) <= wdat;
end if;
end if;
end process;
------------------------------------------------------
--- READ ---
------------------------------------------------------
process (clk) -- Read memory.
begin
if rising_edge(clk) then
mem_rdat <= mem(rd_addr);
end if;
end process;
 
end rtl;
/trunk/HDL/ow_mstr.vhd
0,0 → 1,138
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: onewire_mstr.vhd
-- description: reading and writing devies on a one wire bus
--
-- To simplify the design, there is a low level entity, ow_bit, that handles the
-- read/write/init bit patterns. There is also a byte level entity,
-- ow_byte, that operates on bytes by controlling the ow_bit entity.
-- Controllers of this module can use bit or byte accesses to the one wire bus.
-- to execute both byte and bit level operations, it is necessary to mux the control
-- to the ow_bit interface to the various higher level functions.
-----------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_mstr is
port (
--global signals
clk : in std_logic;
srst : in std_logic; --synchronous reset
stb1us : in std_logic; --1us strobe, used to time transactions
busy : out std_logic; --device is in middle of read,write or init
--low level interfaces, used for micro processor control of bus
init_stb : in std_logic; --sends an init/reset pulse to bus
wrbyte : in std_logic; --write a byte to the bus
inbyte : in std_logic_vector(7 downto 0); --data byte to write
wrbit : in std_logic; --write a single bit to the bus
inbit : in std_logic; --data bit to write
rdbyte : in std_logic; --read a byte from the bus
outbyte : out std_logic_vector(7 downto 0); --read byte
rdbit : in std_logic; --read a single bit from the bus
outbit : out std_logic; --read bit
--one wire bus interface, requires external 5k resistor on bus
owin : in std_logic; --one wire input
owout : out std_logic --one wire output
);
end ow_mstr;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_mstr is
 
signal busyout : std_logic;
--bit module signals
signal ow1_rbit : std_logic;
signal ow1_obit : std_logic;
signal ow1_wbit : std_logic;
signal ow1_ibit : std_logic;
signal ow1_zbit : std_logic;
signal ow1_busy : std_logic;
--byte module signals
signal ow8_rbit : std_logic;
signal ow8_wbit : std_logic;
signal ow8_obit : std_logic;
signal ow8_busy : std_logic;
begin
-------------------------------------
-- signal decoding ---
-------------------------------------
-- the following signals are muxed with priorities, allowing ow8 or external control of the bit interface
ow1_rbit <= ow8_rbit when ow8_busy = '1' else rdbit;
ow1_wbit <= ow8_wbit when ow8_busy = '1' else wrbit;
ow1_ibit <= ow8_obit when ow8_busy = '1' else inbit;
ow1_zbit <= init_stb;
-------------------------------------
-- u_ow1 ---
-------------------------------------
--handles single bit read/write/reset of the one wire bus
u_ow1 : entity work.ow_bit(rtl)
port map(
--globals
clk => clk,
srst => srst,
clken => stb1us,
--interface to higher level
rstb => ow1_rbit,
wstb => ow1_wbit,
istb => ow1_zbit,
din => ow1_ibit,
dout => ow1_obit,
busy => ow1_busy,
--one wire bus
owin => owin, --one wire input
owout => owout --one wire output
);
-------------------------------------
-- u_ow8 ---
-------------------------------------
u_ow8 : entity work.ow_byte(rtl)
port map(
--globals
clk => clk,
srst => srst,
--ow1 interface
rdbit => ow8_rbit,
wrbit => ow8_wbit,
ibit => ow1_obit,
obit => ow8_obit,
busyin => ow1_busy,
--high level interface to owt,owi, or external
rdbyte => rdbyte,
obyte => outbyte,
wrbyte => wrbyte,
ibyte => inbyte,
busy => ow8_busy
);
outbit <= ow1_obit;
busy <= ow8_busy or ow1_busy;
end rtl;
/trunk/HDL/ow_search.vhd
0,0 → 1,339
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ow_search.vhd
-- description: searches a one wire bus for up to 8 one wire devices, and reports
-- the 8 IDs. If there are more than 8 IDs or if a device disapears during the
-- search it will activate the err flag. Only DS1820 devices are supported
--
-----------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_search is
port (
--global signals
clk : in std_logic;
srst : in std_logic;
--signals to upper layer hierarchy
start : in std_logic;
busyin : in std_logic; --busy signal from either ow_byte or ow_bit
busy : out std_logic; --busy indication to higher level modules
error : out std_logic; --indicates a problem on the bus
--signals to lower layer hierarchy (ow_bit and ow_byte)
rdbit : out std_logic; --strobe to read a bit from ow_bit
wrbit : out std_logic; --strobe to write a bit to ow_bit
zzbit : out std_logic; --strobe to send/recieve init/response pulses
obit : out std_logic; --the bit to write in a wrbit command to ow_bit
ibit : in std_logic; --the data recieved from a rdbit command to the ow_bit
wrbyte : out std_logic; --strobe to wrte a byte to ow_byte
obyte : out std_logic_vector(7 downto 0); --data to write to the ow_byte
--interface to id ram
id_num : out std_logic_vector(4 downto 0); --index of the id to read or write
id_bit : out std_logic_vector(5 downto 0); --index of the bit to read or write
id_rbit : in std_logic; --bit value of the currently indexed bit of the current rom
id_wbit : out std_logic; --bit value to write to the currently indexed bit
id_we : out std_logic --write the currently indexed bit
);
end ow_search;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_search is
 
 
type h_state_type is (H_IDLE, H_RST, H_SKIP, H_READBIT, H_READCMP, H_PARSE, H_INCLOOP, H_FILL, H_ERROR);
signal h_state : h_state_type := H_IDLE;
type f_state_type is (F_IDLE, F_FIND, F_INC);
signal f_state : f_state_type := F_IDLE;
 
signal idcnt : integer range 0 to 31;
signal lastfork : integer range 0 to 63;
signal lastzero : integer range 0 to 63;
signal idbitnum : integer range 0 to 63;
signal lastdev : std_logic := '0';
signal h_err : std_logic := '0';
signal f_err : std_logic := '0';
signal irdbit : std_logic := '0';
signal iwrbit : std_logic := '0';
signal iwe : std_logic := '0';
signal iobit : std_logic := '0';
signal iwrbyte : std_logic := '0';
signal izzbit : std_logic := '0';
signal rxpat : std_logic_vector(1 downto 0);
signal h_start : std_logic := '0';
signal restart : std_logic := '0';
signal h_busy : std_logic := '0';
 
constant scan_cmd : std_logic_vector(7 downto 0) := x"f0";
 
 
attribute mark_debug : string;
attribute mark_debug of f_state : signal is "true";
attribute mark_debug of h_state : signal is "true";
attribute mark_debug of idbitnum : signal is "true";
attribute mark_debug of lastfork : signal is "true";
attribute mark_debug of lastzero : signal is "true";
attribute mark_debug of rxpat : signal is "true";
attribute mark_debug of iwrbyte : signal is "true";
attribute mark_debug of irdbit : signal is "true";
attribute mark_debug of iwrbit : signal is "true";
attribute mark_debug of iwe : signal is "true";
attribute mark_debug of iobit : signal is "true";
attribute mark_debug of id_rbit : signal is "true";
attribute mark_debug of obyte : signal is "true";
attribute mark_debug of lastdev : signal is "true";
attribute mark_debug of start : signal is "true";
attribute mark_debug of busyin : signal is "true";
 
begin
 
------------------------------------------------------
-- HUNT - search for the next device on bus ---
------------------------------------------------------
--p_hunt - hunts for the next device using the algorithm described in Maxim (Analog Devices) app note APP187
-- the app note is modified slightly for optimization in VHDL
-- "restart" resets all parameters to rediscover all ROM iDs
-- "hunt" searches for the next ROM ID in the sort order
p_hunt : process (clk)
begin
if rising_edge(clk) then
if srst = '1' or restart = '1' then
h_state <= H_IDLE;
idbitnum <= 0;
lastfork <= 0;
lastdev <= '0';
rxpat <= "00";
h_err <= '0';
iwrbyte <= '0';
izzbit <= '0';
irdbit <= '0';
iwrbit <= '0';
iwe <= '0';
iobit <= '0';
obyte <= x"00";
else
case h_state is
when H_IDLE =>
idbitnum <= 0;
lastzero <= 0;
rxpat <= "00";
iwrbyte <= '0';
irdbit <= '0';
iwrbit <= '0';
iwe <= '0';
iobit <= '0';
obyte <= x"00";
if h_start = '1' then
if lastdev = '0' then
h_state <= H_RST;
izzbit <= '1';
h_err <= '0';
else
h_state <= H_FILL;
iwe <= '1';
iobit <= '0';
end if;
else
izzbit <= '0';
end if;
when H_RST =>
if izzbit = '1' then
izzbit <= '0';
elsif busyin = '0' then
if ibit = '1' then
h_state <= H_ERROR;
else
obyte <= x"f0";
iwrbyte <= '1';
h_state <= H_SKIP;
end if;
end if;
when H_SKIP =>
if iwrbyte = '1' then
iwrbyte <= '0';
elsif busyin = '0' then
irdbit <= '1';
h_state <= H_READBIT;
end if;
when H_READBIT =>
if irdbit = '1' then
irdbit <= '0';
elsif busyin = '0' then
rxpat(1) <= ibit;
irdbit <= '1';
h_state <= H_READCMP;
end if;
when H_READCMP =>
if irdbit = '1' then
irdbit <= '0';
elsif busyin = '0' then
rxpat(0) <= ibit;
h_state <= H_PARSE;
end if;
when H_PARSE =>
case rxpat is
when "11" =>
h_state <= H_ERROR;
when "00" =>
if idbitnum = lastfork then
--last_romid(63 downto 0) <= last_romid(0) & last_romid(63 downto 1);
--new_romid(63 downto 0) <= '1' & new_romid(63 downto 1);
iobit <= '1';
iwrbit <= '1';
iwe <= '1';
h_state <= H_INCLOOP;
elsif idbitnum > lastfork then
--last_romid(63 downto 0) <= last_romid(0) & last_romid(63 downto 1);
--new_romid(63 downto 0) <= '0' & new_romid(63 downto 1);
iobit <= '0';
iwrbit <= '1';
iwe <= '1';
lastzero <= idbitnum;
h_state <= H_INCLOOP;
else
--last_romid(63 downto 0) <= last_romid(0) & last_romid(63 downto 1);
--new_romid(63 downto 0) <= last_romid(0) & new_romid(63 downto 1);
iobit <= id_rbit;
iwrbit <= '1';
iwe <= '1';
if id_rbit = '0' then
lastzero <= idbitnum;
end if;
h_state <= H_INCLOOP;
end if;
when others =>
--last_romid(63 downto 0) <= last_romid(0) & last_romid(63 downto 1);
--new_romid(63 downto 0) <= rxpat(1) & new_romid(63 downto 1);
iobit <= rxpat(1);
iwrbit <= '1';
iwe <= '1';
h_state <= H_INCLOOP;
end case;
when H_INCLOOP =>
if iwrbit = '1' or iwe = '1' then
iwrbit <= '0';
iwe <= '0';
elsif busyin = '0' then
if idbitnum = 63 then
h_state <= H_IDLE;
lastfork <= lastzero;
if lastzero = 0 then
lastdev <= '1';
end if;
else
idbitnum <= idbitnum + 1;
irdbit <= '1';
h_state <= H_READBIT;
end if;
end if;
when H_FILL =>
if iwe = '1' then
iwe <= '0';
elsif idbitnum = 63 then
h_state <= H_IDLE;
else
idbitnum <= idbitnum + 1;
iobit <= '0';
iwe <= '1';
end if;
when others =>
h_err <= '1';
h_state <= H_IDLE;
end case;
end if;
end if;
end process p_hunt;
 
h_busy <= '0' when h_state = H_IDLE and h_start = '0' else '1';
 
------------------------------------------------------
-- FINDALL - find all devices, one by one ---
------------------------------------------------------
--p_findall - finds all (at least up to 8) of the roms on the bus
-- this process initiates up to 8 searches, each finds the next device
-- in the sorted (by device ID) order.
p_findall : process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
idcnt <= 0;
f_state <= F_IDLE;
restart <= '0';
else
case f_state is
when F_IDLE =>
if start = '1' then
restart <= '1';
elsif restart = '1' then
restart <= '0';
h_start <= '1';
f_state <= F_FIND;
idcnt <= 0;
f_err <= '0';
end if;
when F_FIND =>
if h_start = '1' then
h_start <= '0';
elsif h_busy = '0' then
if h_err = '1' then
f_state <= F_IDLE;
f_err <= '1';
else
f_state <= F_INC;
end if;
end if;
when F_INC =>
if idcnt = 31 then
idcnt <= 0;
f_state <= F_IDLE;
else
idcnt <= idcnt + 1;
f_state <= F_FIND;
h_start <= '1';
end if;
end case;
end if;
end if;
end process p_findall;
 
------------------------------------------------------
-- External Signals ---
------------------------------------------------------
 
id_num <= std_logic_vector(to_unsigned(idcnt,5));
id_bit <= std_logic_vector(to_unsigned(idbitnum,6));
id_we <= iwe;
id_wbit <= iobit;
 
rdbit <= irdbit;
wrbit <= iwrbit;
zzbit <= izzbit;
obit <= iobit;
wrbyte <= iwrbyte;
 
busy <= '0' when f_state = F_IDLE and h_state = H_IDLE and start = '0' and restart = '0' else '1';
error <= f_err;
 
end rtl;
/trunk/HDL/ow_temp.vhd
0,0 → 1,392
----------------------------------------------------------------------------------
-- <c>2018 william b hunter
-- This file is part of ow2rtd.
--
-- ow2rtd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lessor General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- ow2rtd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU Lessor General Public License
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
-----------------------------------------------------------------------------------
-- Create Date: 5/15/2018
-- file: ow_temp.vhd
-- description: configures each ds1820 device, starts a conversion on each device, or reads the results
-- of each device. temps are set to 10 bit to shorten conversion times (and who needs 1/16 C resolution
-- when the accuracy is +-0.5C ). The temperatures are output on a bus with a strobe and a device index.
-----------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
--use work.p_ow_types.all;
 
-------------------------------------------------------------------------------------
-- Entity declaration
-------------------------------------------------------------------------------------
entity ow_temp is
generic (
BITS : integer := 12;
DEFTEMP : std_logic_vector(11 downto 0) := x"7ff";
CRC : boolean := false
);
port (
--global signals
clk : in std_logic;
srst : in std_logic;
busyin : in std_logic; --busy signal from either ow_byte or ow_bit
--signals to upper layer hierarchy
init : in std_logic; --init a device for temp reading
conv : in std_logic; --send convert command to the device
read : in std_logic; --read a device
temp : out signed(15 downto 0); --current device temp
tempidx : out unsigned(4 downto 0); --current device index
tempstb : out std_logic; --stobe indicating a temperature output
busy : out std_logic; --busy indication to higher level modules
error : out std_logic; --indicates a problem on the bus
--signals to lower layer hierarchy (ow_bit and ow_byte)
zzbit : out std_logic; --reset strobe to ow_bit interface
wrbit : out std_logic; --write strobe to ow_bit interface
ibit : in std_logic; --the data read from the ow_bit interface
obit : out std_logic; --the data written to the ow_bit interface
rdbyte : out std_logic; --read strobe to ow_byte interface
wrbyte : out std_logic; --write strobe to ow_byte interface
obyte : out std_logic_vector(7 downto 0); --data to write to the ow_byte
ibyte : in std_logic_vector(7 downto 0); --data read from the ow_byte
--interface to id ram
id_num : out std_logic_vector(4 downto 0); --index of the id to read or write
id_bit : out std_logic_vector(5 downto 0); --index of the bit to read or write
id_rbit : in std_logic --bit value of the currently indexed bit of the current rom
);
end ow_temp;
 
-------------------------------------------------------------------------------------
-- Architecture declaration
-------------------------------------------------------------------------------------
architecture rtl of ow_temp is
type t_state_type is (T_IDLE, T_GETTYPE, T_TXID, T_RST, T_TXTOUT, T_TXTOUT2, T_ERROR,
T_INIT, T_INIT1, T_INIT2, T_INIT3, T_INIT4,
T_CONV, T_CONV1, T_CONV2, T_CONV3, T_CONV4,
T_READ, T_READ1, T_READ2, T_READ3, T_READ4, T_READ5, T_READ6, T_READ7
);
signal t_state : t_state_type := T_IDLE;
signal t_next : t_state_type := T_IDLE;
type slv8ary is array (integer range <>) of std_logic_vector(7 downto 0);
constant ROMSTR : integer := 1;
constant ROMTXT : std_logic_vector( 7 downto 0) := x"55";
constant ROMTXTLEN : integer := 1;
constant INITSTR : integer := 2;
constant INITTXT : slv8ary(1 to 4) := ( x"4e",x"7f",x"80",x"3f");
constant INITTXTLEN : integer := INITTXT'length;
constant CONVSTR : integer := 3;
constant CONVTXT : std_logic_vector( 7 downto 0) := x"44";
constant CONVTXTLEN : integer := 1;
constant READSTR : integer := 4;
constant READTXT : std_logic_vector( 7 downto 0) := x"be";
constant READTXTLEN : integer := 1; --READTXT'length;
constant LASTSTR : integer := READSTR;
constant DS1822 : std_logic_vector(7 downto 0) := x"28";
 
signal txtlen : integer range 1 to 4;
signal txtstr : integer range 1 to LASTSTR;
signal txtptr : integer range 1 to 4;
signal txbyte : std_logic_vector(7 downto 0);
signal ididx : integer range 0 to 31; --idx of the current device
signal t_err : std_logic := '0';
signal irdbyte : std_logic := '0';
signal iwrbyte : std_logic := '0';
signal izzbit : std_logic := '0';
signal iwrbit : std_logic := '0';
--signal iobit : std_logic := '0';
 
signal readbits : integer range 1 to 10;
signal shift : std_logic_vector(15 downto 0);
signal bytecnt : integer range 0 to 9;
signal bitcnt : integer range 0 to 63;
signal curid : std_logic_vector(71 downto 0);
 
signal stall : std_logic := '0'; -- this signal is used to stall the state machine one clock after each action
 
--attribute mark_debug : string;
--attribute mark_debug of pulse_state : signal is "true";
--attribute mark_debug of timer : signal is "true";
begin
------------------------------------------------------
-- TX MUX - mux between output commands ---
------------------------------------------------------
--select the byte to transmit from the text strings or the rom value
txbyte <= CONVTXT when txtstr = CONVSTR else READTXT when txtstr = READSTR
else ROMTXT when txtstr = ROMSTR else INITTXT(txtptr);
txtlen <= CONVTXTLEN when txtstr = CONVSTR else READTXTLEN when txtstr = READSTR
else ROMTXTLEN when txtstr = ROMSTR else INITTXTLEN;
------------------------------------------------------
-- P_TEMP - INIT, CONV, READ temp sensors ---
------------------------------------------------------
--p_temp - sends rom match command followed by init command, convert command or
-- read command to the targeted temp sensor and reads data back (if a read command)
p_temp : process (clk)
begin
if rising_edge(clk) then
if srst = '1' then
tempstb <= '0';
t_state <= T_IDLE;
t_err <= '0';
izzbit <= '0';
iwrbit <= '0';
irdbyte <= '0';
iwrbyte <= '0';
ididx <= 0;
bytecnt <= 0;
bitcnt <= 0;
elsif stall = '1' then
tempstb <= '0';
iwrbit <= '0';
izzbit <= '0';
iwrbyte <= '0';
irdbyte <= '0';
stall <= '0';
else
--allow 1 extra clock for ram read, temperature conversions
-- but not when idle or we will miss the triggers
if t_state /= T_IDLE then
stall <= '1';
end if;
case t_state is
when T_IDLE =>
tempstb <= '0';
obyte <= x"00";
--shift <= x"000000000000000000";
shift <= x"0000";
izzbit <= '0';
irdbyte <= '0';
iwrbyte <= '0';
izzbit <= '0';
ididx <= 0;
--shift <= x"00" & ids(ididx);
--idtype <= x"00";
bytecnt <= 0;
bitcnt <= 0;
if init = '1' then
t_state <= T_GETTYPE;
t_next <= T_INIT;
t_err <= '0';
elsif conv = '1' then
t_state <= T_GETTYPE;
t_next <= T_CONV;
t_err <= '0';
elsif read = '1' then
t_state <= T_GETTYPE;
t_next <= T_READ;
t_err <= '0';
end if;
when T_GETTYPE =>
--get the device type from the idrom
shift(7 downto 0) <= id_rbit & shift(7 downto 1);
if bitcnt = 7 then
bitcnt <= 0;
t_state <= t_next;
else
bitcnt <= bitcnt + 1;
end if;
when T_TXID =>
if busyin = '0' then
iwrbit <= '1';
if bitcnt = 63 then
t_state <= t_next;
bitcnt <= 0;
else
bitcnt <= bitcnt + 1;
end if;
end if;
when T_INIT =>
if busyin = '0' then
if shift(7 downto 0) = DS1822 then
t_state <= T_RST;
t_next <= T_INIT1;
izzbit <= '1';
else
t_state <= T_INIT4;
end if;
end if;
when T_INIT1 =>
txtptr <= 1;
txtstr <= ROMSTR;
t_state <= T_TXTOUT;
t_next <= T_INIT2;
when T_INIT2 =>
t_state <= T_TXID;
t_next <= T_INIT3;
when T_INIT3 =>
txtptr <= 1;
txtstr <= INITSTR;
t_state <= T_TXTOUT;
t_next <= T_INIT4;
when T_INIT4 =>
if ididx = 31 then
t_state <= T_IDLE;
else
ididx <= ididx + 1;
t_state <= T_GETTYPE;
t_next <= T_INIT;
end if;
when T_CONV =>
--this state cycles through all devices and initiates a conversion on all ds1822s
if busyin = '0' then
if shift(7 downto 0) = DS1822 then
t_state <= T_RST;
t_next <= T_CONV1;
izzbit <= '1';
else
t_state <= T_CONV4;
end if;
end if;
when T_CONV1 =>
txtptr <= 1;
txtstr <= ROMSTR;
t_state <= T_TXTOUT;
t_next <= T_CONV2;
when T_CONV2 =>
t_state <= T_TXID;
t_next <= T_CONV3;
when T_CONV3 =>
txtptr <= 1;
txtstr <= CONVSTR;
t_state <= T_TXTOUT;
t_next <= T_CONV4;
when T_CONV4 =>
if ididx = 31 then
t_state <= T_IDLE;
else
ididx <= ididx + 1;
t_state <= T_GETTYPE;
t_next <= T_CONV;
end if;
when T_READ =>
--this state cycles through all devices and reads all ds18B20s
if busyin = '0' then
if shift(7 downto 0) = DS1822 then
t_state <= T_RST;
t_next <= T_READ1;
izzbit <= '1';
else
t_state <= T_READ7;
end if;
end if;
when T_READ1 =>
txtptr <= 1;
txtstr <= ROMSTR;
t_state <= T_TXTOUT;
t_next <= T_READ2;
when T_READ2 =>
t_state <= T_TXID;
t_next <= T_READ3;
when T_READ3 =>
txtptr <= 1;
txtstr <= READSTR;
t_state <= T_TXTOUT;
t_next <= T_READ4;
bytecnt <= 0;
when T_READ4 =>
if busyin = '0' then
irdbyte <= '1';
bytecnt <= 0;
t_state <= T_READ5;
end if;
when T_READ5 =>
--this state cycles through the 9 bytes to read
if busyin = '0' then
--if CRC = true then
-- shift <= ibyte & shift(71 downto 8);
--else
-- shift <= x"00000000000000" & ibyte & shift(15 downto 8);
--end if;
shift <= ibyte & shift(15 downto 8);
if (bytecnt = 1 and CRC = false) or (bytecnt = 9 and CRC = true) then
t_state <= T_READ6;
else
bytecnt <= bytecnt + 1;
irdbyte <= '1';
end if;
end if;
when T_READ6 =>
tempstb <= '1';
t_state <= T_READ7;
when T_READ7 =>
tempstb <= '0';
if ididx = 31 then
t_state <= T_IDLE;
else
ididx <= ididx + 1;
t_state <= T_GETTYPE;
t_next <= T_READ;
end if;
when T_RST =>
if busyin = '0' then
if ibit = '1' then
t_state <= T_ERROR;
else
t_state <= t_next;
end if;
end if;
when T_TXTOUT =>
if busyin = '0' then
--if txtstr = ROMSTR and txtptr > 1 then
-- obyte <= shift(7 downto 0);
-- shift <= shift(7 downto 0) & shift(71 downto 8);
--else
obyte <= txbyte;
--end if;
iwrbyte <= '1';
t_state <= T_TXTOUT2;
end if;
when T_TXTOUT2 =>
iwrbyte <= '0';
if txtptr = txtlen then
t_state <= t_next;
txtptr <= 1;
else
txtptr <= txtptr + 1;
t_state <= T_TXTOUT;
end if;
when T_ERROR =>
t_err <= '1';
t_state <= T_IDLE;
end case;
end if;
end if;
end process p_temp;
------------------------------------------------------
-- External Signals ---
------------------------------------------------------
 
temp <= signed(shift(15 downto 0));
tempidx <= to_unsigned(ididx,5);
busy <= '0' when t_state = T_IDLE and conv = '0' and init = '0' and read = '0' else '1';
wrbyte <= iwrbyte;
rdbyte <= irdbyte;
zzbit <= izzbit;
wrbit <= iwrbit;
obit <= id_rbit;
id_num <= std_logic_vector(to_unsigned(ididx,5));
id_bit <= std_logic_vector(to_unsigned(bitcnt,6));
 
error <= t_err;
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.