diff options
Diffstat (limited to 'PIC/dpram.vhd')
| -rw-r--r-- | PIC/dpram.vhd | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/PIC/dpram.vhd b/PIC/dpram.vhd new file mode 100644 index 0000000..44d7adf --- /dev/null +++ b/PIC/dpram.vhd @@ -0,0 +1,110 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Data memory with UART memory-mapped registers. +-- Addresses 0x70-0x72 are used (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 + +entity dpram is + generic (DEPTH : positive := 128); + 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(6 downto 0); + q : out std_logic_vector(7 downto 0); + q_status : out std_logic_vector(2 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 + ); +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'; + +begin + -- STATUS output is combinatorial + q_status <= mem(16#03#)(2 downto 0); + + 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; + + -- 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 = "1110000" 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; + + read : process(clk) + begin + if rising_edge(clk) then + uart_rx_rd_en <= '0'; -- default: no pop + if re = '1' then + if addr = "1110001" then -- 0x71 UART_RX + q <= uart_rx_byte; -- FWFT head, valid combinatorially + if uart_rx_empty = '0' then + uart_rx_rd_en <= '1'; -- advance FIFO pointer + end if; + elsif addr = "1110010" then -- 0x72 UART_STATUS + q <= "00000" & uart_rx_full & uart_rx_empty & uart_tx_pending; + 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 + mem(16#03#) <= d_status; + end if; + if we = '1' then + if addr = "0000011" then -- 0x03 STATUS: direct write + mem(16#03#) <= d; + elsif addr = "1110000" or -- 0x70 UART_TX + addr = "1110001" or -- 0x71 UART_RX (read-only but handled gracefully) + addr = "1110010" then -- 0x72 UART_STATUS (read-only) + -- UART-mapped addresses: don't write to RAM; still update STATUS + mem(16#03#) <= d_status; + else + mem(16#03#) <= d_status; + mem(to_integer(unsigned(addr))) <= d; + end if; + end if; + end if; + end process write; + +end architecture rtl; |
