summaryrefslogtreecommitdiffstats
path: root/hdl/onewire.vhd
diff options
context:
space:
mode:
authorVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
committerVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
commit46e1210381106707c2df7f07c56023eb6b760763 (patch)
tree6740a17199f76e2965a511dafcbc7ffb61ceafeb /hdl/onewire.vhd
parenteb8643ddbef43547eb7bfe58789a3908926c7258 (diff)
downloadvhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.tar.gz
vhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.zip
BSRAM progmem. fix Makefile memory command that does not work. add interrupts, bank 1, timer0. Timer0 not tested.
Diffstat (limited to 'hdl/onewire.vhd')
-rw-r--r--hdl/onewire.vhd195
1 files changed, 195 insertions, 0 deletions
diff --git a/hdl/onewire.vhd b/hdl/onewire.vhd
new file mode 100644
index 0000000..440d34d
--- /dev/null
+++ b/hdl/onewire.vhd
@@ -0,0 +1,195 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity onewire is
+ generic (
+ CLK_FREQ : positive := 50_000_000
+ );
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ ow_pin : inout std_logic; -- 4.7 kohm pull-up to 3.3 V externally
+
+ start : in std_logic;
+ op : in std_logic_vector(1 downto 0); -- "00" reset, "01" write, "10" read
+ tx_byte : in std_logic_vector(7 downto 0);
+ rx_byte : out std_logic_vector(7 downto 0);
+ presence : out std_logic;
+ busy : out std_logic;
+ done : out std_logic
+ );
+end entity onewire;
+
+architecture rtl of onewire is
+
+ constant us : positive := CLK_FREQ / 1_000_000;
+
+ constant RESET_LOW_TICKS : positive := 480 * us;
+ constant PRESENCE_WAIT_TICKS : positive := 15 * us;
+ constant PRESENCE_SAMPLE_END : positive := 75 * us;
+ constant RESET_RECOVER_TICKS : positive := 480 * us;
+ constant WRITE0_LOW_TICKS : positive := 60 * us;
+ constant WRITE1_LOW_TICKS : positive := 6 * us;
+ constant SLOT_TICKS : positive := 70 * us;
+ constant READ_INIT_TICKS : positive := 6 * us;
+ constant READ_SAMPLE_TICKS : positive := 15 * us;
+
+ type state_t is (
+ IDLE,
+ RST_PULL, RST_RELEASE, RST_SAMPLE, RST_RECOVER,
+ WR_PULL, WR_RELEASE,
+ RD_PULL, RD_RELEASE, RD_SAMPLE, RD_RECOVER,
+ BYTE_NEXT
+ );
+
+ signal state : state_t := IDLE;
+ signal ow_drive : std_logic := '0';
+ signal ow_sense : std_logic;
+ signal timer : natural range 0 to RESET_LOW_TICKS + 1 := 0;
+ signal bit_index : natural range 0 to 8 := 0;
+ signal shift_reg : std_logic_vector(7 downto 0) := (others => '0');
+ signal cur_bit : std_logic := '0';
+ signal is_read : std_logic := '0';
+ signal rx_byte_i : std_logic_vector(7 downto 0) := (others => '0');
+
+ signal presence_internal : std_logic := '0';
+begin
+
+ ow_pin <= '0' when ow_drive = '1' else 'Z';
+ ow_sense <= ow_pin;
+
+ presence <= presence_internal;
+
+ rx_byte <= rx_byte_i;
+ busy <= '0' when state = IDLE else '1';
+
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ done <= '0';
+ timer <= timer + 1;
+
+ if reset = '1' then
+ state <= IDLE;
+ ow_drive <= '0';
+ timer <= 0;
+ else
+ case state is
+ when IDLE =>
+ timer <= 0;
+
+ if start = '1' then
+ presence_internal <= '0';
+ case op is
+ -- reset
+ when "00" =>
+ timer <= 0;
+ state <= RST_PULL;
+
+ -- write
+ when "01" =>
+ state <= WR_PULL;
+ shift_reg <= tx_byte;
+ bit_index <= 0;
+ is_read <= '0';
+
+ -- read
+ when "10" =>
+ state <= RD_PULL;
+ bit_index <= 0;
+ is_read <= '1';
+
+ when others => null;
+ end case;
+ end if;
+
+ when RST_PULL =>
+ ow_drive <= '1';
+
+ if timer >= RESET_LOW_TICKS then
+ state <= RST_RELEASE;
+ end if;
+
+
+ when RST_RELEASE =>
+ ow_drive <= '0';
+ timer <= 0;
+ state <= RST_SAMPLE;
+
+ when RST_SAMPLE =>
+ if ow_sense = '0' then
+ presence_internal <= '1';
+ end if;
+
+ if (ow_sense = '1' and presence_internal = '1') or
+ timer >= PRESENCE_SAMPLE_END then
+ state <= RST_RECOVER;
+ end if;
+
+ when RST_RECOVER =>
+ -- wait for 480us since RST_RELEASE
+ if timer >= RESET_RECOVER_TICKS then
+ done <= '1';
+ state <= IDLE;
+ end if;
+
+ when WR_PULL =>
+ ow_drive <= '1';
+ if (shift_reg(bit_index) = '1' and timer >= WRITE1_LOW_TICKS) or
+ (shift_reg(bit_index) = '0' and timer >= WRITE0_LOW_TICKS) then
+ state <= WR_RELEASE;
+ end if;
+
+ when WR_RELEASE =>
+ ow_drive <= '0';
+
+ if timer >= SLOT_TICKS then
+ state <= BYTE_NEXT;
+ end if;
+
+ when RD_PULL =>
+ ow_drive <= '1';
+
+ if timer >= READ_INIT_TICKS then
+ state <= RD_RELEASE;
+ end if;
+
+ when RD_RELEASE =>
+ ow_drive <= '0';
+
+ if timer >= READ_INIT_TICKS + 2 * us then
+ state <= RD_SAMPLE;
+ end if;
+
+ when RD_SAMPLE =>
+ rx_byte_i <= ow_sense & rx_byte_i(7 downto 1);
+ state <= RD_RECOVER;
+
+ when RD_RECOVER =>
+ if timer >= SLOT_TICKS then
+ state <= BYTE_NEXT;
+ end if;
+
+ when BYTE_NEXT =>
+ timer <= 0;
+ if bit_index = 7 then
+ bit_index <= 0;
+ done <= '1';
+ state <= IDLE;
+ else
+ bit_index <= bit_index + 1;
+ if is_read = '1' then
+ state <= RD_PULL;
+ else
+ state <= WR_PULL;
+ end if;
+ end if;
+ when others => state <= IDLE;
+ end case;
+ end if;
+ end if;
+ end process;
+
+end architecture rtl;