1 | library IEEE;
|
2 | use IEEE.STD_LOGIC_1164.all;
|
3 | use IEEE.STD_LOGIC_ARITH.all;
|
4 | use ieee.numeric_std.all;
|
5 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
6 |
|
7 | --
|
8 | -- onewirebit
|
9 | -- onewirebit is the implementation of the lowest protocol
|
10 | -- layer, the bit layer. This entity is able to send bit to
|
11 | -- the bus and receive bity from the bus.
|
12 | --
|
13 |
|
14 | entity onewirebit is
|
15 | port(
|
16 | CLK : in bit; -- system clock
|
17 | dq : inout std_logic; -- route this to the physical pin connected to the onewire bus
|
18 | reset : in bit; -- set this bit to '1' to send a reset condition, if a slave is present invalue will be set to '1', otherwise to '0'
|
19 | writing : in bit; -- set this bit to '1' to start write process, one clock later clear this bit, after that for finished becoming '1'
|
20 | outvalue : in bit; -- set this bit to the value to be written to the bus. Do not change this value while the entity is writing this value!
|
21 | readbit : in bit; -- set this bit to '1' to read a bit from the bus
|
22 | invalue : out bit; -- after finishing the readbit command, the readed value can be read here. Alternative it is used for the return value of reset.
|
23 | finished : out bit -- after setting writing or readbit to '1' wait after one cycle for this bit to become '1' again
|
24 | );
|
25 | end onewirebit;
|
26 |
|
27 | architecture Behavioral of onewirebit is
|
28 | type states is (state_idle, state_reset0, state_reset1, state_reset2, state_wb, state_rb0, state_rb1, state_finished);
|
29 | signal state : states := state_idle;
|
30 | signal timer : std_logic_vector (31 downto 0) := (others=>'0');
|
31 | signal dq_outvalue : bit;
|
32 | signal dq_invalue : bit;
|
33 | begin
|
34 | process(CLK)
|
35 | begin
|
36 | if CLK='1' and CLK'event then
|
37 | timer <= timer + '1'; -- increment the timer each cycle
|
38 | --invalue <= dq_invalue;
|
39 | case state is
|
40 | when state_idle =>
|
41 | dq_outvalue <= '1';
|
42 | finished <= '1';
|
43 | if writing='1' then -- there is a new bit to be written to the bus
|
44 | state <= state_wb;
|
45 | timer <= (others => '0'); -- reset the timer for the next state
|
46 | finished <= '0';
|
47 | dq_outvalue <= '0'; -- pull down the line
|
48 | elsif reset='1' then -- there is a reset to be executed
|
49 | state <= state_reset0;
|
50 | finished <= '0';
|
51 | timer <= (others => '0'); -- reset the timer for the next state
|
52 | dq_outvalue <= '0'; -- pull down the line
|
53 | elsif readbit='1' then
|
54 | state <= state_rb0;
|
55 | end if;
|
56 | when state_reset0 => -- wait fore reset time (500µs) to be over
|
57 | if timer=std_logic_vector(to_unsigned(8000,timer'length)) then
|
58 | state <= state_reset1;
|
59 | timer <= (others => '0'); -- reset the timer for the next state
|
60 | dq_outvalue <= '1'; -- release the line
|
61 | end if;
|
62 | when state_reset1 => -- the reset command has been sent, wait for slave responses after 70µs
|
63 | if timer=std_logic_vector(to_unsigned(1120,timer'length)) then
|
64 | invalue <= dq_invalue;
|
65 | state <= state_reset2;
|
66 | timer <= (others => '0'); -- reset the timer for the next state
|
67 | end if;
|
68 | when state_reset2 => -- the response has been recorded, wait for rising edge on the bus
|
69 | if dq_invalue='1' then
|
70 | state <= state_idle; -- go back to the idle state
|
71 | end if;
|
72 | when state_wb => -- the line is pulled low, pull it up after 10µs or 65µs µs, depending on outvalue
|
73 | -- this two conditions could be made in one
|
74 | -- outvalue should be buffered
|
75 | if outvalue='1' and timer=std_logic_vector(to_unsigned(160,timer'length)) then -- when 10µs passed, release the line to write a logic one
|
76 | dq_outvalue <= '1';
|
77 | state <= state_finished;
|
78 | timer <= (others => '0'); -- reset the timer for the next state
|
79 | elsif outvalue='0' and timer=std_logic_vector(to_unsigned(1040,timer'length)) then -- when 65µs passed, release the line to write a logic zero
|
80 | dq_outvalue <= '1';
|
81 | timer <= (others => '0'); -- reset the timer for the next state
|
82 | state <= state_finished;
|
83 | end if;
|
84 | when state_rb0 =>
|
85 | when state_rb1 =>
|
86 | when state_finished => -- wait 20µs for recovery and make shure the line is high (should be 2µs)
|
87 | dq_outvalue <= '1';
|
88 | if timer=std_logic_vector(to_unsigned(320,timer'length)) then
|
89 | state <= state_idle;
|
90 | finished <= '1';
|
91 | end if;
|
92 | end case;
|
93 | end if;
|
94 | end process;
|
95 |
|
96 | process(dq_outvalue, dq)
|
97 | begin
|
98 | if dq_outvalue = '1' then
|
99 | dq <= 'Z';
|
100 | else
|
101 | dq <= '0';
|
102 | end if;
|
103 | --dq <= 'Z' when dq_outvalue='1' else '0';
|
104 | --if dq='0' then
|
105 | -- dq_invalue <= '0';
|
106 | --else
|
107 | -- dq_invalue <= '1';
|
108 | --end if;
|
109 | --dq_invalue <= '0' when dq='0' else '1';
|
110 | end process;
|
111 | dq_invalue <= to_bit(dq);
|
112 | end Behavioral;
|