library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Data memory with UART and 1-Wire memory-mapped registers. -- Addresses 0x70-0x72 are UART (unimplemented in real PIC16F84A, no header conflict): -- 0x70 UART_TX write: send byte (held until tx_done) -- 0x71 UART_RX read: current FIFO head (FWFT), pulses rd_en to pop -- 0x72 UART_STATUS read: "00000" & rx_full & rx_empty & tx_busy -- Addresses 0x73-0x75 are 1-Wire: -- 0x73 OW_DATA write: tx_byte to send; read: rx_byte received -- 0x74 OW_CMD write: bits[1:0]=op (00=reset,01=write,10=read), any write pulses start -- 0x75 OW_STATUS read: "000000" & presence & busy entity dpram is generic (DEPTH : positive := 256); port ( clk : in std_logic; we : in std_logic; re : in std_logic; d : in std_logic_vector(7 downto 0); d_status : in std_logic_vector(7 downto 0); addr : in std_logic_vector(7 downto 0); q : out std_logic_vector(7 downto 0); q_status : out std_logic_vector(7 downto 0); port_a : out std_logic_vector(7 downto 0); port_b : out std_logic_vector(7 downto 0); we_status : in std_logic; -- UART interface uart_tx_byte : out std_logic_vector(7 downto 0) := (others => '0'); uart_tx_send : out std_logic := '0'; uart_tx_done : in std_logic; uart_rx_byte : in std_logic_vector(7 downto 0); uart_rx_rd_en : out std_logic := '0'; uart_rx_empty : in std_logic; uart_rx_full : in std_logic; -- 1-Wire interface ow_tx_byte : out std_logic_vector(7 downto 0) := (others => '0'); ow_op : out std_logic_vector(1 downto 0) := "00"; ow_start : out std_logic := '0'; ow_rx_byte : in std_logic_vector(7 downto 0); ow_presence : in std_logic; ow_busy : in std_logic; -- Timer0 interface tmr0_val : in std_logic_vector(7 downto 0); -- current TMR0 value tmr0_we : out std_logic := '0'; -- CPU writing TMR0 tmr0_in : out std_logic_vector(7 downto 0) := (others => '0'); -- OPTION_REG (bank 1, 0x81) — read by timer0 option_reg : out std_logic_vector(7 downto 0); -- Interrupt control (INTCON at 0x0B) t0if_set : in std_logic; -- timer0 overflow: sets INTCON.T0IF (bit 2) gie_clear : in std_logic; -- interrupt ack: clears INTCON.GIE (bit 7) gie_set : in std_logic; -- RETFIE: sets INTCON.GIE (bit 7) irq_pending : out std_logic -- GIE & T0IE & T0IF ); end entity dpram; architecture rtl of dpram is type mem_t is array (0 to DEPTH - 1) of std_logic_vector(7 downto 0); signal mem : mem_t := (others => (others => '0')); signal uart_tx_pending : std_logic := '0'; signal ow_start_i : std_logic := '0'; signal ow_op_i : std_logic_vector(1 downto 0) := "00"; signal ow_tx_byte_i : std_logic_vector(7 downto 0) := (others => '0'); begin -- STATUS output is combinatorial (full 8-bit register) q_status <= mem(16#03#); port_a <= mem(16#05#); port_b <= mem(16#06#); -- tx_send is high while a transmission is in progress uart_tx_send <= uart_tx_pending; ow_start <= ow_start_i; ow_op <= ow_op_i; ow_tx_byte <= ow_tx_byte_i; option_reg <= mem(16#81#); irq_pending <= mem(16#0B#)(7) and mem(16#0B#)(5) and mem(16#0B#)(2); tmr0_we <= '1' when we = '1' and addr = "00000001" else '0'; tmr0_in <= d; -- SR: set when CPU writes to 0x08, clear when UART asserts tx_done tx_ctrl : process(clk) begin if rising_edge(clk) then if we = '1' and addr = "01110000" then -- 0x70 UART_TX uart_tx_byte <= d; uart_tx_pending <= '1'; elsif uart_tx_done = '1' then uart_tx_pending <= '0'; end if; end if; end process tx_ctrl; ow_ctrl : process(clk) begin if rising_edge(clk) then ow_start_i <= '0'; if we = '1' then if addr = "01110011" then -- 0x73 OW_DATA ow_tx_byte_i <= d; elsif addr = "01110100" then -- 0x74 OW_CMD ow_op_i <= d(1 downto 0); ow_start_i <= '1'; end if; end if; end if; end process ow_ctrl; read : process(clk) begin if rising_edge(clk) then uart_rx_rd_en <= '0'; -- default: no pop if re = '1' then if addr = "00000000" or addr = "10000000" then -- 0x00/0x80 INDF: indirect via FSR q <= mem(to_integer(unsigned(mem(16#04#)))); elsif addr = "00000001" then -- 0x01 TMR0 (bank 0, read from timer0) q <= tmr0_val; elsif addr = "00001011" or addr = "10001011" then -- 0x0B/0x8B INTCON (mirrored) q <= mem(16#0B#); elsif addr = "01110001" then -- 0x71 UART_RX q <= uart_rx_byte; if uart_rx_empty = '0' then uart_rx_rd_en <= '1'; end if; elsif addr = "01110010" then -- 0x72 UART_STATUS q <= "00000" & uart_rx_full & uart_rx_empty & uart_tx_pending; elsif addr = "01110011" then -- 0x73 OW_DATA q <= ow_rx_byte; elsif addr = "01110101" then -- 0x75 OW_STATUS q <= "000000" & ow_presence & ow_busy; elsif addr = "00000011" or addr = "10000011" then -- 0x03/0x83 STATUS (mirrored) q <= mem(16#03#); else q <= mem(to_integer(unsigned(addr))); end if; end if; end if; end process read; write : process(clk) begin if rising_edge(clk) then if we_status = '1' then -- only Z/DC/C (bits 2:0) come from ALU; preserve RP0, TO, PD etc. mem(16#03#) <= mem(16#03#)(7 downto 3) & d_status(2 downto 0); end if; if we = '1' then if addr = "00000000" or addr = "10000000" then -- 0x00/0x80 INDF: indirect via FSR mem(16#03#) <= mem(16#03#)(7 downto 3) & d_status(2 downto 0); mem(to_integer(unsigned(mem(16#04#)))) <= d; elsif addr = "00000001" then -- 0x01 TMR0: routed to timer0, not RAM mem(16#03#) <= mem(16#03#)(7 downto 3) & d_status(2 downto 0); elsif addr = "00001011" or addr = "10001011" then -- 0x0B/0x8B INTCON (mirrored): direct write mem(16#0B#) <= d; elsif addr = "00000011" or addr = "10000011" then -- 0x03/0x83 STATUS (mirrored): direct write mem(16#03#) <= d; elsif addr = "01110000" or -- 0x70 UART_TX addr = "01110001" or -- 0x71 UART_RX (read-only) addr = "01110010" or -- 0x72 UART_STATUS (read-only) addr = "01110011" or -- 0x73 OW_DATA addr = "01110100" or -- 0x74 OW_CMD addr = "01110101" then -- 0x75 OW_STATUS (read-only) -- peripheral-mapped addresses: don't write to RAM mem(16#03#) <= mem(16#03#)(7 downto 3) & d_status(2 downto 0); else mem(16#03#) <= mem(16#03#)(7 downto 3) & d_status(2 downto 0); mem(to_integer(unsigned(addr))) <= d; end if; end if; -- Hardware INTCON modifications (last = highest priority) if t0if_set = '1' then mem(16#0B#)(2) <= '1'; end if; if gie_clear = '1' then mem(16#0B#)(7) <= '0'; end if; if gie_set = '1' then mem(16#0B#)(7) <= '1'; end if; end if; end process write; end architecture rtl;