summaryrefslogtreecommitdiffstats
path: root/hdl/dpram.vhd
diff options
context:
space:
mode:
authorVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
committerVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
commiteb8643ddbef43547eb7bfe58789a3908926c7258 (patch)
treefadfba88a1c71b266b8c67df166a3a6ead6b30d1 /hdl/dpram.vhd
parent129a1c975dbd0c042576010b1f6eb40d19fc5733 (diff)
downloadvhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.tar.gz
vhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.zip
refactor dir structure, add fib.c
Diffstat (limited to 'hdl/dpram.vhd')
-rw-r--r--hdl/dpram.vhd110
1 files changed, 110 insertions, 0 deletions
diff --git a/hdl/dpram.vhd b/hdl/dpram.vhd
new file mode 100644
index 0000000..44d7adf
--- /dev/null
+++ b/hdl/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;