1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4
5 CD40105/HC40105 4-bit x 16-word FIFO Register
6
7 Part of the 4000B series of CMOS logic devices, the 40105 includes
8 an asynchronous master reset pin intended to be connected to the
9 system bus.
10
11 Word size can be expanded from 4 bits to 8 bits by connecting two
12 40105s in parallel, with external AND gates to combine the DIR and
13 DOR outputs. They can also be connected in series to extend the
14 FIFO capacity, with DOR -> SI and /SO <- DIR.
15
16 **********************************************************************/
17
18 #include "emu.h"
19 #include "40105.h"
20
21
22
23 //**************************************************************************
24 // MACROS / CONSTANTS
25 //**************************************************************************
26
27 #define LOG 0
28
29
30
31 //**************************************************************************
32 // DEVICE DEFINITIONS
33 //**************************************************************************
34
35 DEFINE_DEVICE_TYPE(CD40105, cmos_40105_device, "cd40105", "CD40105B FIFO Register")
36
37
38 //**************************************************************************
39 // LIVE DEVICE
40 //**************************************************************************
41
42 //-------------------------------------------------
43 // cmos_40105_device - constructor
44 //-------------------------------------------------
45
cmos_40105_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)46 cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
47 : device_t(mconfig, CD40105, tag, owner, clock),
48 m_write_dir(*this),
49 m_write_dor(*this),
50 m_write_q(*this),
51 m_d(0),
52 m_q(0),
53 m_dir(false),
54 m_dor(false),
55 m_si(false),
56 m_so(false)
57 {
58 }
59
60
61 //-------------------------------------------------
62 // device_start - device-specific startup
63 //-------------------------------------------------
64
device_start()65 void cmos_40105_device::device_start()
66 {
67 // resolve callbacks
68 m_write_dir.resolve_safe();
69 m_write_dor.resolve_safe();
70 m_write_q.resolve_safe();
71
72 // state saving
73 save_item(NAME(m_d));
74 save_item(NAME(m_q));
75 save_item(NAME(m_dir));
76 save_item(NAME(m_dor));
77 save_item(NAME(m_si));
78 save_item(NAME(m_so));
79 }
80
81
82 //-------------------------------------------------
83 // device_reset - device-specific reset
84 //-------------------------------------------------
85
device_reset()86 void cmos_40105_device::device_reset()
87 {
88 // invalidate data in queue
89 m_fifo = std::queue<u8>();
90
91 // reset control flip-flops
92 m_dir = true;
93 m_dor = false;
94 m_write_dir(1);
95 m_write_dor(0);
96 }
97
98
99 //-------------------------------------------------
100 // read - read output buffer (Q0 to Q3)
101 //-------------------------------------------------
102
read()103 u8 cmos_40105_device::read()
104 {
105 return m_q;
106 }
107
108
109 //-------------------------------------------------
110 // write - write input buffer (D0 to D3)
111 //-------------------------------------------------
112
write(u8 data)113 void cmos_40105_device::write(u8 data)
114 {
115 m_d = data & 0x0f;
116 }
117
118
119 //-------------------------------------------------
120 // load_input - load new data into FIFO
121 //-------------------------------------------------
122
load_input()123 void cmos_40105_device::load_input()
124 {
125 if (m_fifo.size() == 16)
126 {
127 logerror("Attempt to load data into full FIFO\n");
128 return;
129 }
130
131 m_fifo.push(m_d);
132
133 // DIR remains low if FIFO is full, or else briefly pulses low
134 m_write_dir(0);
135 if (m_fifo.size() == 16)
136 m_dir = false;
137 else
138 m_write_dir(1);
139 }
140
141
142 //-------------------------------------------------
143 // output_ready - place new data at output
144 //-------------------------------------------------
145
output_ready()146 void cmos_40105_device::output_ready()
147 {
148 if (m_fifo.size() == 0)
149 {
150 logerror("Attempt to output data from empty FIFO\n");
151 return;
152 }
153
154 m_q = m_fifo.front();
155 m_write_q(m_q);
156
157 m_dor = true;
158 m_write_dor(1);
159 }
160
161
162 //-------------------------------------------------
163 // si_w - shift in write
164 //-------------------------------------------------
165
WRITE_LINE_MEMBER(cmos_40105_device::si_w)166 WRITE_LINE_MEMBER( cmos_40105_device::si_w )
167 {
168 // load input on rising edge when ready
169 if (m_dir && !m_si && state)
170 {
171 load_input();
172 }
173 else if (m_si && !state && m_fifo.size() > 0)
174 {
175 // data propagates through FIFO when SI goes low
176 if (!m_dor)
177 output_ready();
178 }
179
180 m_si = state;
181 }
182
183
184 //-------------------------------------------------
185 // so_w - shift out write
186 //-------------------------------------------------
187
WRITE_LINE_MEMBER(cmos_40105_device::so_w)188 WRITE_LINE_MEMBER( cmos_40105_device::so_w )
189 {
190 // shift out on falling edge when ready
191 if (m_dor && m_so && !state)
192 {
193 m_fifo.pop();
194 m_dor = false;
195 m_write_dor(0);
196
197 // DOR remains low if FIFO is now empty, or else briefly pulses low
198 if (m_fifo.size() > 0)
199 output_ready();
200
201 if (!m_dir)
202 {
203 // raise DIR since FIFO is no longer full
204 m_dir = true;
205 m_write_dir(1);
206
207 // load new input immediately if SI is held high
208 if (m_si)
209 load_input();
210 }
211 }
212
213 m_so = state;
214 }
215
216
217 //-------------------------------------------------
218 // dir_r - data in ready read
219 //-------------------------------------------------
220
READ_LINE_MEMBER(cmos_40105_device::dir_r)221 READ_LINE_MEMBER( cmos_40105_device::dir_r )
222 {
223 return m_dir;
224 }
225
226
227 //-------------------------------------------------
228 // dor_r - data out ready read
229 //-------------------------------------------------
230
READ_LINE_MEMBER(cmos_40105_device::dor_r)231 READ_LINE_MEMBER( cmos_40105_device::dor_r )
232 {
233 return m_dor;
234 }
235