OpenCores
URL https://opencores.org/ocsvn/pdp8/pdp8/trunk

Subversion Repositories pdp8

[/] [pdp8/] [trunk/] [pdp8/] [ls8e.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 trurl
--------------------------------------------------------------------
2
--!
3
--! PDP-8 Processor
4
--!
5
--! \brief
6
--!      LS8E Serial Printer
7
--!
8
--! \details
9
--!      This device provides a LS8E register set compatible
10
--!      interface to a serial printer.
11
--!
12
--!
13
--! \note
14
--!      The design information for this device is taken from
15
--!      the LS8E Engineering Specificaton number LS8-E-2
16
--!
17
--! \file
18
--!      ls8e.vhd
19
--!
20
--! \author
21
--!      Rob Doyle - doyle (at) cox (dot) net
22
--!
23
--------------------------------------------------------------------
24
--
25
--  Copyright (C) 2009, 2010, 2011, 2012 Rob Doyle
26
--
27
-- This source file may be used and distributed without
28
-- restriction provided that this copyright statement is not
29
-- removed from the file and that any derivative work contains
30
-- the original copyright notice and the associated disclaimer.
31
--
32
-- This source file is free software; you can redistribute it
33
-- and/or modify it under the terms of the GNU Lesser General
34
-- Public License as published by the Free Software Foundation;
35
-- version 2.1 of the License.
36
--
37
-- This source is distributed in the hope that it will be
38
-- useful, but WITHOUT ANY WARRANTY; without even the implied
39
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
40
-- PURPOSE. See the GNU Lesser General Public License for more
41
-- details.
42
--
43
-- You should have received a copy of the GNU Lesser General
44
-- Public License along with this source; if not, download it
45
-- from http://www.gnu.org/licenses/lgpl.txt
46
--
47
--------------------------------------------------------------------
48
--
49
-- Comments are formatted for doxygen
50
--
51
 
52
library ieee;                                   --! IEEE Library
53
use ieee.std_logic_1164.all;                    --! IEEE 1164
54
use work.uart_types.all;                        --! UART Types
55
use work.ls8e_types.all;                        --! PR8E Types
56
use work.cpu_types.all;                         --! CPU Types
57
 
58
--
59
--! LS8E Serial Printer Entity
60
--
61
 
62
entity eLS8E is port (
63
    sys    : in  sys_t;                         --! Clock/Reset
64
    uartBR : in  uartBR_t;                      --! Baud Rate Select
65
    uartHS : in  uartHS_t;                      --! Handshaking Select
66
    devNUM : in  devNUM_t;                      --! IOT Device
67
    cpu    : in  cpu_t;                         --! CPU Input
68
    dev    : out dev_t;                         --! Device Output
69
    dtr    : in  std_logic;                     --! Data Terminal Ready
70
    dsr    : out std_logic;                     --! Data Set Ready
71
    rxd    : in  std_logic;                     --! Serial Data In
72
    txd    : out std_logic                      --! Serial Data Out
73
);
74
end eLS8E;
75
 
76
--
77
--! LS8E Serial Printer RTL
78
--
79
 
80
architecture rtl of eLS8E is
81
    -- State
82
    type     state_t   is (stateIdle, stateBuffered, stateWaiting);
83
    signal   state     : state_t;               --! Transmitter State
84
    signal   clkBR     : std_logic;             --! 16x Baud Rate Clock Enable
85
    -- PR8E Registers
86
    signal   ieSET     : std_logic;             --! Set/Clear Interrupt Enable Register
87
    signal   ieREG     : std_logic;             --! Interrupt Enable Register
88
    signal   flagCLR   : std_logic;             --! Clear Flag Register
89
    signal   flagSET   : std_logic;             --! Set Flag Register
90
    signal   flagREG   : std_logic;             --! Flag REG
91
    signal   busyREG   : std_logic;             --! Printer status
92
    -- RX signals
93
    signal   rxIntr    : std_logic;             --! UART Receiver has data
94
    signal   rxData    : ascii_t;               --! UART Receiver Buffer
95
    -- TX signals
96
    signal   txIntr    : std_logic;             --! UART Transmitter has sent data
97
    signal   txData    : ascii_t;               --! UART Transmitter Buffer
98
    -- Misc
99
    signal   start     : std_logic;             --! Start
100
    signal   loadUART  : std_logic;             --! Load Transmitter UART
101
    signal   DTRd      : std_logic_vector(0 to 1);  --! DTR demet
102
 
103
begin
104
 
105
    --
106
    --! LE8E Bus Interface
107
    --!
108
    --! \details
109
    --!     The Bus Interface decodes the individual LS8E IOT instructions.
110
    --!     The various operations: Enable Interrupts, Disable Interrupts,
111
    --!     Set Flag, and Clear Flag are decoded and provided to the
112
    --!     synchronous process that maintains the PR8E register state.
113
    --!
114
    --! \note
115
    --!     The Bus Interface is totally asynchronous.  The dev.ack,
116
    --!     dev.skip, and dev.devc signals are combinationally derived from
117
    --!     CPU output bus signals.  These signals will be sampled by the
118
    --!     CPU on the device bus input on the next clock cycle.
119
    --
120
 
121
    LS8E_BUSINTF : process(cpu.buss, devNUM, flagREG, ieREG)
122
    begin
123
 
124
        dev     <= nulldev;
125
        ieSET   <= '0';
126
        flagSET <= '0';
127
        flagCLR <= '0';
128
        start   <= '0';
129
 
130
        if cpu.buss.addr(0 to 2) = opIOT and cpu.buss.addr(3 to 8) = devNUM and cpu.buss.lxdar = '1' then
131
 
132
            --
133
            -- Printer IOTs
134
            --
135
 
136
            case cpu.buss.addr(9 to 11) is
137
 
138
                --
139
                -- IOT 6xx0: Set Printer Flag
140
                --  Sets the Printer interrupt enable flip-flop
141
                --  so that an interrupt request will be generated
142
                --  when the printer flag is set.
143
                --
144
 
145
                when opLS0 =>
146
                    dev.ack  <= '1';
147
                    dev.devc <= devWR;
148
                    dev.skip <= '0';
149
                    flagSET  <= '1';
150
 
151
                --
152
                -- IOT 6xx1: Skip on Printer Flag
153
                --  This senses the printer flag.  If the flag
154
                --  is set, then the next instructon is skipped.
155
                --
156
 
157
                when opLS1 =>
158
                    dev.ack  <= '1';
159
                    dev.devc <= devWR;
160
                    dev.skip <= flagREG;
161
 
162
                --
163
                -- IOT 6xx2: Clear Printer Flag
164
                --
165
 
166
                when opLS2 =>
167
                    dev.ack  <= '1';
168
                    dev.devc <= devWR;
169
                    dev.skip <= '0';
170
                    flagCLR  <= '1';
171
 
172
                --
173
                -- IOT 6xx4: Load Printer Buffer
174
                --  Transfers AC(5:11) to the output buffer and
175
                --  later outputs the buffer content to the
176
                --  printer.  The Printer Flag is not cleared.
177
                --
178
 
179
                when opLS4 =>
180
                    dev.ack  <= '1';
181
                    dev.devc <= devWR;
182
                    dev.skip <= '0';
183
                    start    <= '1';
184
 
185
                --
186
                -- IOT 6xx5: Set/Clear Interrupt Enable
187
                --  Enable interrupts if AC(11) is set.
188
                --  Disable interrupts if AC(11) is cleared.
189
                --
190
 
191
                when opLS5 =>
192
                    dev.ack  <= '1';
193
                    dev.devc <= devWR;
194
                    dev.skip <= '0';
195
                    ieSET    <= '1';
196
 
197
                --
198
                -- IOT 6xx6: Load Printer Buffer Sequence
199
                --  Transfers AC(5:11) to the output buffer and
200
                --  later outputs the buffer content to the
201
                --  printer.  The Printer Flag is cleared.
202
                --
203
 
204
                when opLS6 =>
205
                    dev.ack  <= '1';
206
                    dev.devc <= devWR;
207
                    dev.skip <= '0';
208
                    flagCLR  <= '1';
209
                    start    <= '1';
210
 
211
                --
212
                -- Everything else
213
                --
214
 
215
                when others =>
216
                    null;
217
 
218
            end case;
219
        end if;
220
 
221
        dev.intr <= flagREG and ieREG;
222
        dev.data <= o"0000";
223
 
224
    end process;
225
 
226
    --
227
    --! This process maintains the LS8E Registers
228
    --!
229
    --! -# The Printer Flag is cleared by initialize or CAF (IOCLR)
230
    --! -# The Interupt Enable is set by initialize or CAF (IOCLR)
231
    --
232
 
233
    REG_LS8E : process(sys)
234
    begin
235
        if sys.rst = '1' then
236
 
237
            ieREG    <= '1';
238
            flagREG  <= '0';
239
            loadUART <= '0';
240
            txData   <= (others => '0');
241
            state    <= stateIdle;
242
 
243
        elsif rising_edge(sys.clk) then
244
 
245
            if cpu.buss.ioclr = '1' then
246
 
247
                ieREG   <= '1';
248
                flagREG <= '0';
249
 
250
            else
251
 
252
                --
253
                -- Update Interrupt Enable Register
254
                --
255
 
256
                if ieSET = '1' then
257
                    ieREG <= cpu.buss.data(11);
258
                end if;
259
 
260
                --
261
                -- Update Flag Register
262
                --
263
 
264
                if flagCLR = '1' then
265
                    flagREG <= '0';
266
                elsif flagSET = '1' or txIntr = '1' then
267
                    flagREG <= '1';
268
                end if;
269
 
270
                --
271
                -- Send character
272
                --
273
 
274
                case state is
275
 
276
                    --
277
                    -- stateIdle:
278
                    -- Wait for print IOT.  Buffer character to print.
279
                    --
280
 
281
                    when stateIdle =>
282
                        if start = '1' then
283
                            txData <= cpu.buss.data(4 to 11);
284
                            state  <= stateBuffered;
285
                        end if;
286
 
287
                    --
288
                    -- stateBuffered:
289
                    -- Wait for printer to be not busy.  Load UART
290
                    --
291
 
292
                    when stateBuffered =>
293
                        if busyREG = '0' then
294
                            loadUART <= '1';
295
                            state    <= stateWaiting;
296
                        end if;
297
 
298
                    --
299
                    -- stateWaiting:
300
                    -- Wait for IOT to finish.
301
                    --
302
 
303
                    when stateWaiting =>
304
                        if start = '0' then
305
                            state <= stateIdle;
306
                        end if;
307
 
308
                    --
309
                    -- Everything Else
310
                    --
311
 
312
                    when others =>
313
                        null;
314
 
315
                end case;
316
 
317
            end if;
318
        end if;
319
    end process REG_LS8E;
320
 
321
    --
322
    --! This process keeps track of the printer status.
323
    --! The printer status can be controlled by hardware (DTR)
324
    --! signal or by software (XON/XOFF) protocol.
325
    --
326
 
327
    REG_BUSY : process(sys)
328
    begin
329
        if sys.rst = '1' then
330
 
331
            busyREG <= '0';
332
            DTRd    <= (others => '0');
333
 
334
        elsif rising_edge(sys.clk) then
335
 
336
            if cpu.buss.ioclr = '1' then
337
 
338
                busyREG   <= '0';
339
 
340
            else
341
 
342
                --
343
                -- Synchronize DTR
344
                --
345
 
346
                DTRd(0) <= dtr;
347
                DTRd(1) <= DTRd(0);
348
 
349
                case uartHS is
350
 
351
                    --
352
                    -- No Handskaking
353
                    --
354
 
355
                    when uartHSnone =>
356
                        busyREG <= '0';
357
 
358
                    --
359
                    -- Hardware Handshaking
360
                    --
361
 
362
                    when uartHShw =>
363
                        busyREG <= DTRd(1);
364
 
365
                    --
366
                    -- Software (XON/XOFF) handshaking
367
                    --
368
 
369
                    when uartHSsw =>
370
                        if rxIntr = '1' then
371
                            if rxdata = xon then
372
                                busyREG <= '1';
373
                            elsif rxdata = xoff then
374
                                busyREG <= '0';
375
                            end if;
376
                        end if;
377
 
378
                    --
379
                    -- Everythig Else
380
                    --
381
 
382
                    when others =>
383
                        null;
384
 
385
                end case;
386
            end if;
387
        end if;
388
    end process REG_BUSY;
389
 
390
    --
391
    --! UART Baud Rate Generator
392
    --
393
 
394
    iUART_BRG : entity work.eUART_BRG port map (
395
        sys    => sys,
396
        uartBR => uartBR,
397
        clkBR  => clkBR
398
    );
399
 
400
    --
401
    --! The UART Receiver is used for ACK/NAK handshaking
402
    --
403
 
404
    iUART_RX : entity work.eUART_RX port map (
405
        sys   => sys,
406
        clkBR => clkBR,
407
        rxd   => rxd,
408
        intr  => rxIntr,
409
        data  => rxData
410
    );
411
 
412
    --
413
    --! The UART Transmitter sends data to the printer
414
    --
415
 
416
    iUART_TX : entity work.eUART_TX port map (
417
        sys   => sys,
418
        clkBR => clkBR,
419
        data  => txData,
420
        load  => loadUART,
421
        intr  => txIntr,
422
        txd   => txd
423
    );
424
 
425
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.