1 |
2 |
skeptonomi |
----------------------------------------------------------------------------------
|
2 |
|
|
-- <c>2018 william b hunter
|
3 |
|
|
-- This file is part of ow2rtd.
|
4 |
|
|
--
|
5 |
|
|
-- ow2rtd is free software: you can redistribute it and/or modify
|
6 |
|
|
-- it under the terms of the GNU Lessor General Public License as published by
|
7 |
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
8 |
|
|
-- (at your option) any later version.
|
9 |
|
|
--
|
10 |
|
|
-- ow2rtd is distributed in the hope that it will be useful,
|
11 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
|
|
-- GNU General Public License for more details.
|
14 |
|
|
--
|
15 |
|
|
-- You should have received a copy of the GNU Lessor General Public License
|
16 |
|
|
-- along with ow2rtd. If not, see <https://www.gnu.org/licenses/>.
|
17 |
|
|
-----------------------------------------------------------------------------------
|
18 |
|
|
-- Create Date: 5/15/2018
|
19 |
|
|
-- file: onewire_bit.vhd
|
20 |
|
|
-- description: handles single bit transactions on the one wire bus
|
21 |
|
|
-- it is used by higher level entities to initialize, search, read, and write the one
|
22 |
|
|
-- wire devices on the one wire bus.
|
23 |
|
|
-- Each operation consists of a start, that is always low, middle, which for reads
|
24 |
|
|
-- represents the time for the slave to respond, and the end, which allows for
|
25 |
|
|
-- the slave to finish its operation and provides spacing between bit patterns.
|
26 |
|
|
-- For reads and resets, the data is sampled at the end of the mid time
|
27 |
|
|
--
|
28 |
|
|
-----------------------------
|
29 |
|
|
|
30 |
|
|
library IEEE;
|
31 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
32 |
|
|
use IEEE.numeric_std.all;
|
33 |
|
|
library work;
|
34 |
|
|
|
35 |
|
|
-------------------------------------------------------------------------------------
|
36 |
|
|
-- Entity declaration
|
37 |
|
|
-------------------------------------------------------------------------------------
|
38 |
|
|
entity ow_bit is
|
39 |
|
|
port (
|
40 |
|
|
--globals
|
41 |
|
|
clk : in std_logic;
|
42 |
|
|
srst : in std_logic;
|
43 |
|
|
clken : in std_logic;
|
44 |
|
|
--interface to higher level
|
45 |
|
|
rstb : in std_logic;
|
46 |
|
|
wstb : in std_logic;
|
47 |
|
|
istb : in std_logic;
|
48 |
|
|
din : in std_logic;
|
49 |
|
|
dout : out std_logic;
|
50 |
|
|
busy : out std_logic;
|
51 |
|
|
--one wire bus
|
52 |
|
|
owout : out std_logic; --one wire input
|
53 |
|
|
owin : in std_logic --one wire output
|
54 |
|
|
);
|
55 |
|
|
end ow_bit;
|
56 |
|
|
|
57 |
|
|
-------------------------------------------------------------------------------------
|
58 |
|
|
-- Architecture declaration
|
59 |
|
|
-------------------------------------------------------------------------------------
|
60 |
|
|
architecture rtl of ow_bit is
|
61 |
|
|
type pulse_state_type is (S_IDLE, S_START, S_MID, S_END); --, S_DONE
|
62 |
|
|
signal pulse_state : pulse_state_type := S_IDLE;
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
constant r_start : unsigned(11 downto 0) := to_unsigned(5,12); --low time
|
66 |
|
|
constant r_mid : unsigned(11 downto 0) := to_unsigned(10,12); --high z until sample time
|
67 |
|
|
constant r_end : unsigned(11 downto 0) := to_unsigned(65,12); --recovery time
|
68 |
|
|
constant w_start : unsigned(11 downto 0) := to_unsigned(5,12); --low time
|
69 |
|
|
constant w_mid : unsigned(11 downto 0) := to_unsigned(65,12); --dout time
|
70 |
|
|
constant w_end : unsigned(11 downto 0) := to_unsigned(10,12); --recovery time
|
71 |
|
|
constant rw_cnt : unsigned(11 downto 0) := to_unsigned(1,12); --number of samples for read or write
|
72 |
|
|
constant i_start : unsigned(11 downto 0) := to_unsigned(500,12); --reset low time
|
73 |
|
|
constant i_mid : unsigned(11 downto 0) := to_unsigned(100,12); --high z till sample time
|
74 |
|
|
constant i_end : unsigned(11 downto 0) := to_unsigned(220,12); --recovery time till end of rst response
|
75 |
|
|
constant i_cnt : unsigned(3 downto 0) := to_unsigned(1,4); --number of samples (i_end each) to wait for init response
|
76 |
|
|
|
77 |
|
|
signal start_time : unsigned(11 downto 0); -- low pulse time
|
78 |
|
|
signal mid_time : unsigned(11 downto 0); -- high pulse time
|
79 |
|
|
signal end_time : unsigned(11 downto 0); -- time between samples, or the last sample and the end
|
80 |
|
|
--signal rd_count : unsigned(4 downto 0) := to_unsigned(30,5); -- number of read smaples for this bit
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
signal owo : std_logic := '0'; --one wire output bit
|
84 |
|
|
--signal owo2 : std_logic := '0'; --one wire output bit combined with one wire power
|
85 |
|
|
--signal owi : std_logic := '0'; --one wire input bit
|
86 |
|
|
--signal owt : std_logic := '0'; --one wire tristate, implements open collector bus
|
87 |
|
|
signal wstb_cap : std_logic := '0'; --captures and holds write requests
|
88 |
|
|
signal rstb_cap : std_logic := '0'; --captures and holds read requests
|
89 |
|
|
signal istb_cap : std_logic := '0'; --captures and holds init requests (reset/presence sequence)
|
90 |
|
|
signal din_cap : std_logic := '0'; --captures and holds input data
|
91 |
|
|
signal pulse_end : std_logic;
|
92 |
|
|
signal busy_int : std_logic;
|
93 |
|
|
signal timer : unsigned(11 downto 0) := x"000"; --used to time one wire bus transactions
|
94 |
|
|
--signal rdcntr : unsigned(4 downto 0); --used to count samples in the read mode
|
95 |
|
|
--signal owopwr : std_logic; --internal state of dout combined with power input
|
96 |
|
|
signal samp : std_logic; --AND'ed value of owi samples
|
97 |
|
|
|
98 |
|
|
attribute mark_debug : string;
|
99 |
|
|
attribute mark_debug of pulse_state : signal is "true";
|
100 |
|
|
attribute mark_debug of timer : signal is "true";
|
101 |
|
|
attribute mark_debug of samp : signal is "true";
|
102 |
|
|
attribute mark_debug of din : signal is "true";
|
103 |
|
|
attribute mark_debug of dout : signal is "true";
|
104 |
|
|
attribute mark_debug of rstb_cap: signal is "true";
|
105 |
|
|
attribute mark_debug of wstb_cap : signal is "true";
|
106 |
|
|
attribute mark_debug of istb_cap : signal is "true";
|
107 |
|
|
attribute mark_debug of busy_int : signal is "true";
|
108 |
|
|
attribute mark_debug of pulse_end : signal is "true";
|
109 |
|
|
|
110 |
|
|
|
111 |
|
|
begin
|
112 |
|
|
-------------------------------------
|
113 |
|
|
-- strobe captures ---
|
114 |
|
|
-------------------------------------
|
115 |
|
|
-- p_capstb - captures the pulse strobes, and clears then when the pulse is complete
|
116 |
|
|
-- this is necessary if the clken is used because the strobes happen on the system clk and
|
117 |
|
|
-- the pulse is timed by the stb1us. We need to hold the strobes throughout the pulse because the active
|
118 |
|
|
-- strobe is used to zelect the timing for the pulse.
|
119 |
|
|
p_capstb : process (clk)
|
120 |
|
|
begin
|
121 |
|
|
if rising_edge(clk) then
|
122 |
|
|
if srst = '1' then
|
123 |
|
|
rstb_cap <= '0';
|
124 |
|
|
wstb_cap <= '0';
|
125 |
|
|
istb_cap <= '0';
|
126 |
|
|
din_cap <= '0';
|
127 |
|
|
elsif busy_int = '0' then
|
128 |
|
|
if rstb = '1' then
|
129 |
|
|
rstb_cap <= '1';
|
130 |
|
|
elsif wstb = '1' then
|
131 |
|
|
wstb_cap <= '1';
|
132 |
|
|
din_cap <= din;
|
133 |
|
|
elsif istb = '1' then
|
134 |
|
|
istb_cap <= '1';
|
135 |
|
|
end if;
|
136 |
|
|
elsif pulse_state = S_END then
|
137 |
|
|
rstb_cap <= '0';
|
138 |
|
|
wstb_cap <= '0';
|
139 |
|
|
istb_cap <= '0';
|
140 |
|
|
din_cap <= '0';
|
141 |
|
|
end if;
|
142 |
|
|
end if;
|
143 |
|
|
end process p_capstb;
|
144 |
|
|
|
145 |
|
|
-------------------------------------
|
146 |
|
|
-- control muxing ---
|
147 |
|
|
-------------------------------------
|
148 |
|
|
--busy_int indicates that a pulse is pending (one of the strobe captures is high) or the pulse is active
|
149 |
|
|
busy_int <= '0' when rstb_cap = '0' and wstb_cap = '0' and istb_cap = '0'
|
150 |
|
|
and pulse_state = S_IDLE
|
151 |
|
|
else '1';
|
152 |
|
|
|
153 |
|
|
start_time <= w_start when wstb_cap = '1' else i_start when istb_cap = '1' else r_start;
|
154 |
|
|
mid_time <= w_mid when wstb_cap = '1' else i_mid when istb_cap = '1' else r_mid;
|
155 |
|
|
end_time <= w_end when wstb_cap = '1' else i_end when istb_cap = '1' else r_end;
|
156 |
|
|
|
157 |
|
|
|
158 |
|
|
-------------------------------------
|
159 |
|
|
-- pulse generator ---
|
160 |
|
|
-------------------------------------
|
161 |
|
|
--p_pulse - generates the pulse, and if needed captures the read bit or read presence pulse
|
162 |
|
|
-- all pulses consist of a start time, a middle time, and an end time.
|
163 |
|
|
-- for read, write, and init, the start time is always low, and starts the timing for the pulse
|
164 |
|
|
-- 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
|
165 |
|
|
-- for the write, the middle time is where the actual data, zero or one, is output.
|
166 |
|
|
-- the end time is used to space between pulses.
|
167 |
|
|
-- |start| middle |end|
|
168 |
|
|
-- Write one ----_____-------------
|
169 |
|
|
-- Write zero ----______________----
|
170 |
|
|
-- read ----_____xxxxxxxxx----
|
171 |
|
|
-- init ----_____---------____
|
172 |
|
|
p_pulse : process (clk)
|
173 |
|
|
begin
|
174 |
|
|
if rising_edge(clk) then
|
175 |
|
|
if srst = '1' then
|
176 |
|
|
pulse_state <= S_IDLE;
|
177 |
|
|
timer <= x"000";
|
178 |
|
|
--rdcntr <= "00000";
|
179 |
|
|
owo <= '1';
|
180 |
|
|
samp <= '1';
|
181 |
|
|
elsif clken = '1' then
|
182 |
|
|
case pulse_state is
|
183 |
|
|
when S_IDLE =>
|
184 |
|
|
samp <= '1';
|
185 |
|
|
if busy_int = '1' then
|
186 |
|
|
pulse_state <= S_START;
|
187 |
|
|
timer <= start_time;
|
188 |
|
|
owo <= '0';
|
189 |
|
|
end if;
|
190 |
|
|
when S_START =>
|
191 |
|
|
if timer > 0 then
|
192 |
|
|
timer <= timer -1;
|
193 |
|
|
else
|
194 |
|
|
if wstb_cap = '1' then
|
195 |
|
|
owo <= din_cap;
|
196 |
|
|
else
|
197 |
|
|
owo <= '1';
|
198 |
|
|
end if;
|
199 |
|
|
timer <= mid_time;
|
200 |
|
|
pulse_state <= S_MID;
|
201 |
|
|
end if;
|
202 |
|
|
when S_MID =>
|
203 |
|
|
if timer > 0 then
|
204 |
|
|
timer <= timer -1;
|
205 |
|
|
else
|
206 |
|
|
samp <= owin;
|
207 |
|
|
timer <= end_time;
|
208 |
|
|
--rdcntr <= rd_count;
|
209 |
|
|
pulse_state <= S_END;
|
210 |
|
|
owo <= '1';
|
211 |
|
|
end if;
|
212 |
|
|
when S_END =>
|
213 |
|
|
if timer > 0 then
|
214 |
|
|
timer <= timer -1;
|
215 |
|
|
else
|
216 |
|
|
pulse_state <= S_IDLE;
|
217 |
|
|
end if;
|
218 |
|
|
--when S_DONE =>
|
219 |
|
|
-- pulse_state <= S_IDLE;
|
220 |
|
|
end case;
|
221 |
|
|
end if;
|
222 |
|
|
end if;
|
223 |
|
|
end process p_pulse;
|
224 |
|
|
|
225 |
|
|
dout <= samp; --this is the value read back from a read pulse or a reset pulse
|
226 |
|
|
busy <= busy_int or rstb or wstb or istb;
|
227 |
|
|
|
228 |
|
|
--The output is driven high when pwr = 1, otherwise is only driven low when owo is low
|
229 |
|
|
owout <= owo;
|
230 |
|
|
|
231 |
|
|
end rtl;
|