blob: 44d7adf6b67ae15fb3126b77c8ea6a9262374fb3 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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;
|