-
Notifications
You must be signed in to change notification settings - Fork 0
/
scsi_data_bus_io.vhdl
128 lines (114 loc) · 3.5 KB
/
scsi_data_bus_io.vhdl
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
library ieee;
use ieee.std_logic_1164.all;
entity scsi_data_bus_io is
port(
-- Internal bus signals
rst : in std_logic;
clk : in std_logic;
write_enable : in std_logic;
output_enable : in std_logic;
direction : in std_logic;
busy : out std_logic;
err : out std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
-- SCSI bus signals
scsi_req : out std_logic;
scsi_ack : in std_logic;
scsi_db : inout std_logic_vector(7 downto 0);
scsi_dbp : inout std_logic
);
begin
end;
architecture behavioral of scsi_data_bus_io is
-- Control signals
signal input_write_enable : std_logic;
signal output_write_enable : std_logic;
signal scsi_output_enable : std_logic;
signal pending_reg_next : std_logic;
signal busy_reg_next : std_logic;
signal req_reg_next : std_logic;
-- Data registers
signal input_data_reg : std_logic_vector(7 downto 0);
signal output_data_reg : std_logic_vector(7 downto 0);
signal err_reg : std_logic;
-- Control registers
signal direction_reg : std_logic; -- 0 = input, 1 = output
signal pending_reg : std_logic;
signal busy_reg : std_logic;
signal req_reg : std_logic;
-- Parity generation
signal parity_data : std_logic_vector(7 downto 0);
signal parity : std_logic;
signal parity_err : std_logic;
begin
-- Control signals
input_write_enable <= not busy_reg and write_enable;
output_write_enable <= busy_reg and not req_reg and not scsi_ack and not direction_reg;
scsi_output_enable <= ((pending_reg and not pending_reg_next) or (not pending_reg and busy_reg)) and direction_reg and output_enable;
pending_reg_next <= input_write_enable or (pending_reg and req_reg and not scsi_ack);
busy_reg_next <= pending_reg or (busy_reg and not pending_reg and not req_reg_next);
req_reg_next <= (not busy_reg and not pending_reg) or (not busy_reg and pending_reg and not scsi_ack) or (busy_reg and not pending_reg and not scsi_ack) or (busy_reg and pending_reg);
-- Data registers
process(clk)
begin
if rising_edge(clk) then
if input_write_enable = '1' then
input_data_reg <= data_in;
end if;
end if;
end process;
process(rst, clk)
begin
if rst = '1' then
output_data_reg <= X"00";
err_reg <= '0';
elsif falling_edge(clk) then
if output_write_enable = '1' then
output_data_reg <= scsi_db;
err_reg <= parity_err;
end if;
end if;
end process;
-- Control registers
process(rst, clk)
begin
if rst = '1' then
direction_reg <= '0';
elsif rising_edge(clk) then
if input_write_enable = '1' then
direction_reg <= direction;
end if;
end if;
end process;
process(rst, clk)
begin
if rst = '1' then
pending_reg <= '0';
elsif rising_edge(clk) then
pending_reg <= pending_reg_next;
end if;
end process;
process(rst, clk)
begin
if rst = '1' then
busy_reg <= '0';
req_reg <= '1';
elsif falling_edge(clk) then
busy_reg <= busy_reg_next;
req_reg <= req_reg_next;
end if;
end process;
-- Parity generation
parity_data <= input_data_reg when direction_reg = '1' else scsi_db;
parity <= not (((parity_data(7) xor parity_data(6)) xor (parity_data(5) xor parity_data(4))) xor ((parity_data(3) xor parity_data(2)) xor (parity_data(1) xor parity_data(0))));
parity_err <= parity xor scsi_dbp;
-- Internal outputs
busy <= busy_reg;
err <= err_reg;
data_out <= output_data_reg;
-- SCSI outputs
scsi_req <= req_reg;
scsi_db <= (others => 'Z') when scsi_output_enable = '0' else input_data_reg;
scsi_dbp <= 'Z' when scsi_output_enable = '0' else parity;
end architecture;