URL
https://opencores.org/ocsvn/System09/System09/trunk
Subversion Repositories System09
Compare Revisions
- This comparison shows the changes necessary to convert path
/System09/trunk/rtl/VHDL
- from Rev 118 to Rev 100
- ↔ Reverse comparison
Rev 118 → Rev 100
/peripheral_bus.vhd
86,8 → 86,8
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
----------------------------------------------------------------------- |
-- Entity for peripheral bus -- |
/acia6850.vhd
12,8 → 12,8
-- Asynchronous Communications Interface Adapter (ACIA) |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- ieee.numeric_std |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Author : John E. Kent |
-- |
125,8 → 125,8
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
----------------------------------------------------------------------- |
-- Entity for ACIA_6850 -- |
340,12 → 340,11
-- Generate Read / Write strobes. |
----------------------------------------------------------------------------- |
|
acia_read_write : process(clk, ac_rst) |
ACIA_Read_Write : process(clk, ac_rst) |
begin |
if falling_edge(clk) then |
if rst = '1' then |
CtrlReg(1 downto 0) <= "11"; |
CtrlReg(7 downto 2) <= (others => '0'); |
if ac_rst = '1' then |
CtrlReg <= (others => '0'); |
TxReg <= (others => '0'); |
RxRd <= '0'; |
TxWr <= '0'; |
/Flasher.vhd
14,6 → 14,7
-- Dependencies : ieee.std_logic_1164 |
-- ieee.numeric_std |
-- ieee.std_logic_unsigned |
-- unisim.vcomponents |
-- |
-- Author : John E. Kent |
-- |
52,8 → 53,8
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
----------------------------------------------------------------------- |
-- Entity for B3_SRAM -- |
/ACIA_Clock.vhd
13,6 → 13,7
-- ieee.std_logic_arith |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- work.bit_funcs |
-- |
-- Author : John E. Kent |
54,8 → 55,8
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use ieee.numeric_std.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
library work; |
use work.bit_funcs.all; |
|
/datram.vhd
87,8 → 87,8
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity dat_ram is |
port ( |
/spi-master.vhd
11,7 → 11,10
-- Purpose : Implements a SPI Master Controller |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- ieee.std_logic_arith |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Author : Hans Huebner |
-- |
/ps2_keyboard.vhd
12,6 → 12,7
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Author : Original Verilog version by John Clayton |
-- Converted to VHDL by John E. Kent |
144,7 → 145,7
-- they correspond to 60usec for a 49.152MHz clock. |
-- |
-- Author: John Kent |
--2001-02-10 Converted to VHDL |
-- 2001-02-10 Converted to VHDL |
-- 2004-09-11 Added ctrl key |
-- Changed undefined key codes to x"ff" |
-- Reversed clock polarity |
153,9 → 154,9
-- 2007-02-06 Added Generic Clock parameter |
-- 2010-05-31 Revised header, added GPL |
-- 2010-06-17 Change some signal names for consistancy |
-- 2010-10-24 Rearranged code to prevent shift key outputting characters |
-- |
-- |
-- |
--------------------------------------------------------------------------------------- |
|
library ieee; |
163,8 → 164,8
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use ieee.numeric_std.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity ps2_keyboard is |
generic ( |
202,10 → 203,7
constant LEFT_SHIFT : integer := 16#12#; |
constant RIGHT_SHIFT : integer := 16#59#; |
constant CTRL_CODE : integer := 16#14#; |
constant LEFT_ALT : integer := 16#11#; |
constant CAPS_CODE : integer := 16#58#; |
constant SCROLL_LOCK : integer := 16#7E#; |
constant NUM_LOCK : integer := 16#77#; |
constant CAPS_CODE : integer := 16#58#; |
|
|
-- constants |
230,9 → 228,9
--constant TIMER_5USEC_BITS_PP : integer := 7; -- Number of bits needed for timer |
|
-- Values for generic Clock up to 50 MHz |
constant TIMER_60USEC_VALUE_PP : integer := CLK_FREQ_MHZ * 60; -- Number of clock cycles for 60usec. |
constant TIMER_60USEC_VALUE_PP : integer := CLK_FREQ_MHZ * 60; -- Number of sys_clks for 60usec. |
constant TIMER_60USEC_BITS_PP : integer := 12; -- Number of bits needed for timer |
constant TIMER_5USEC_VALUE_PP : integer := CLK_FREQ_MHZ * 5; -- Number of clock cycles for debounce |
constant TIMER_5USEC_VALUE_PP : integer := CLK_FREQ_MHZ * 5; -- Number of sys_clks for debounce |
constant TIMER_5USEC_BITS_PP : integer := 8; -- Number of bits needed for timer |
|
constant TRAP_SHIFT_KEYS_PP : integer := 1; -- Default: No shift key trap. |
376,72 → 374,66
|
m1_state_logic : process( m1_state, q, |
tx_shifting_done, tx_write, |
ps2_clk_s, ps2_data_s, |
timer_60usec_done, timer_5usec_done ) |
ps2_clk_s, ps2_data_s, |
timer_60usec_done, timer_5usec_done ) |
begin |
-- Output signals default to this value, unless changed in a state condition. |
ps2_clk_hi_z <= '1'; |
ps2_data_hi_z <= '1'; |
tx_error <= '0'; |
enable_timer_60usec <= '0'; |
enable_timer_5usec <= '0'; |
ps2_clk_hi_z <= '1'; |
ps2_data_hi_z <= '1'; |
tx_error <= '0'; |
enable_timer_60usec <= '0'; |
enable_timer_5usec <= '0'; |
|
case (m1_state) is |
-- |
-- receive clock transitions |
-- |
when m1_rx_clk_h => |
enable_timer_60usec <= '1'; |
if (tx_write = '1') then |
m1_next_state <= m1_tx_reset_timer; |
elsif (ps2_clk_s = '0') then |
m1_next_state <= m1_rx_falling_edge_marker; |
else |
m1_next_state <= m1_rx_clk_h; |
case (m1_state) is |
when m1_rx_clk_h => |
enable_timer_60usec <= '1'; |
if (tx_write = '1') then |
m1_next_state <= m1_tx_reset_timer; |
elsif (ps2_clk_s = '0') then |
m1_next_state <= m1_rx_falling_edge_marker; |
else |
m1_next_state <= m1_rx_clk_h; |
end if; |
|
when m1_rx_falling_edge_marker => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_rx_clk_l; |
when m1_rx_falling_edge_marker => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_rx_clk_l; |
|
when m1_rx_clk_l => |
enable_timer_60usec <= '1'; |
if (tx_write = '1') then |
m1_next_state <= m1_tx_reset_timer; |
elsif (ps2_clk_s = '1') then |
m1_next_state <= m1_rx_rising_edge_marker; |
else |
m1_next_state <= m1_rx_clk_l; |
end if; |
|
when m1_rx_rising_edge_marker => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_rx_clk_h; |
|
-- |
-- write to keyboard (Tx) |
-- |
when m1_tx_reset_timer => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_tx_force_clk_l; |
when m1_rx_clk_l => |
enable_timer_60usec <= '1'; |
if (tx_write = '1') then |
m1_next_state <= m1_tx_reset_timer; |
elsif (ps2_clk_s = '1') then |
m1_next_state <= m1_rx_rising_edge_marker; |
else |
m1_next_state <= m1_rx_clk_l; |
end if; |
|
when m1_tx_force_clk_l => |
enable_timer_60usec <= '1'; |
ps2_clk_hi_z <= '0'; -- Force the ps2_clk line low. |
if (timer_60usec_done = '1') then |
m1_next_state <= m1_tx_first_wait_clk_h; |
else |
m1_next_state <= m1_tx_force_clk_l; |
end if; |
when m1_rx_rising_edge_marker => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_rx_clk_h; |
|
when m1_tx_first_wait_clk_h => |
enable_timer_5usec <= '1'; |
ps2_data_hi_z <= '0'; -- Start bit. |
if (ps2_clk_s = '0') and (timer_5usec_done = '1') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_first_wait_clk_h; |
end if; |
when m1_tx_reset_timer => |
enable_timer_60usec <= '0'; |
m1_next_state <= m1_tx_force_clk_l; |
|
when m1_tx_force_clk_l => |
enable_timer_60usec <= '1'; |
ps2_clk_hi_z <= '0'; -- Force the ps2_clk line low. |
if (timer_60usec_done = '1') then |
m1_next_state <= m1_tx_first_wait_clk_h; |
else |
m1_next_state <= m1_tx_force_clk_l; |
end if; |
|
when m1_tx_first_wait_clk_h => |
enable_timer_5usec <= '1'; |
ps2_data_hi_z <= '0'; -- Start bit. |
if (ps2_clk_s = '0') and (timer_5usec_done = '1') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_first_wait_clk_h; |
end if; |
|
-- This state must be included because the device might possibly |
-- delay for up to 10 milliseconds before beginning its clock pulses. |
448,285 → 440,267
-- During that waiting time, we cannot drive the data (q[0]) because it |
-- is possibly 1, which would cause the keyboard to abort its receive |
-- and the expected clocks would then never be generated. |
when m1_tx_first_wait_clk_l => |
ps2_data_hi_z <= '0'; |
if (ps2_clk_s = '0') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_first_wait_clk_l; |
end if; |
when m1_tx_first_wait_clk_l => |
ps2_data_hi_z <= '0'; |
if (ps2_clk_s = '0') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_first_wait_clk_l; |
end if; |
|
when m1_tx_wait_clk_h => |
enable_timer_5usec <= '1'; |
ps2_data_hi_z <= q(0); |
if (ps2_clk_s = '1') and (timer_5usec_done = '1') then |
m1_next_state <= m1_tx_rising_edge_marker; |
else |
m1_next_state <= m1_tx_wait_clk_h; |
end if; |
when m1_tx_wait_clk_h => |
enable_timer_5usec <= '1'; |
ps2_data_hi_z <= q(0); |
if (ps2_clk_s = '1') and (timer_5usec_done = '1') then |
m1_next_state <= m1_tx_rising_edge_marker; |
else |
m1_next_state <= m1_tx_wait_clk_h; |
end if; |
|
when m1_tx_rising_edge_marker => |
ps2_data_hi_z <= q(0); |
m1_next_state <= m1_tx_clk_h; |
when m1_tx_rising_edge_marker => |
ps2_data_hi_z <= q(0); |
m1_next_state <= m1_tx_clk_h; |
|
when m1_tx_clk_h => |
ps2_data_hi_z <= q(0); |
if (tx_shifting_done = '1') then |
m1_next_state <= m1_tx_wait_keyboard_ack; |
elsif (ps2_clk_s = '0') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_clk_h; |
end if; |
when m1_tx_clk_h => |
ps2_data_hi_z <= q(0); |
if (tx_shifting_done = '1') then |
m1_next_state <= m1_tx_wait_keyboard_ack; |
elsif (ps2_clk_s = '0') then |
m1_next_state <= m1_tx_clk_l; |
else |
m1_next_state <= m1_tx_clk_h; |
end if; |
|
when m1_tx_clk_l => |
ps2_data_hi_z <= q(0); |
if (ps2_clk_s = '1') then |
m1_next_state <= m1_tx_wait_clk_h; |
else |
m1_next_state <= m1_tx_clk_l; |
end if; |
when m1_tx_clk_l => |
ps2_data_hi_z <= q(0); |
if (ps2_clk_s = '1') then |
m1_next_state <= m1_tx_wait_clk_h; |
else |
m1_next_state <= m1_tx_clk_l; |
end if; |
|
when m1_tx_wait_keyboard_ack => |
if (ps2_clk_s = '0') and (ps2_data_s = '1') then |
m1_next_state <= m1_tx_error; |
elsif (ps2_clk_s = '0') and (ps2_data_s = '0') then |
m1_next_state <= m1_tx_done_recovery; |
else |
m1_next_state <= m1_tx_wait_keyboard_ack; |
end if; |
when m1_tx_wait_keyboard_ack => |
if (ps2_clk_s = '0') and (ps2_data_s = '1') then |
m1_next_state <= m1_tx_error; |
elsif (ps2_clk_s = '0') and (ps2_data_s = '0') then |
m1_next_state <= m1_tx_done_recovery; |
else |
m1_next_state <= m1_tx_wait_keyboard_ack; |
end if; |
|
when m1_tx_done_recovery => |
if (ps2_clk_s = '1') and (ps2_data_s = '1') then |
m1_next_state <= m1_rx_clk_h; |
else |
m1_next_state <= m1_tx_done_recovery; |
end if; |
when m1_tx_done_recovery => |
if (ps2_clk_s = '1') and (ps2_data_s = '1') then |
m1_next_state <= m1_rx_clk_h; |
else |
m1_next_state <= m1_tx_done_recovery; |
end if; |
|
when m1_tx_error => |
tx_error <= '1'; |
if (ps2_clk_s = '1') and (ps2_data_s ='1') then |
m1_next_state <= m1_rx_clk_h; |
else |
m1_next_state <= m1_tx_error; |
end if; |
when m1_tx_error => |
tx_error <= '1'; |
if (ps2_clk_s = '1') and (ps2_data_s ='1') then |
m1_next_state <= m1_rx_clk_h; |
else |
m1_next_state <= m1_tx_error; |
end if; |
|
when others => |
m1_next_state <= m1_rx_clk_h; |
end case; |
when others => |
m1_next_state <= m1_rx_clk_h; |
end case; |
end process; |
|
-- |
|
-- This is the bit counter |
-- |
bit_counter: process(clk, reset, m1_state, bit_count ) |
begin |
if clk'event and clk = '0' then |
if ( reset = '1' ) or ( rx_shifting_done = '1' ) or |
(m1_state = m1_tx_wait_keyboard_ack) then -- After tx is done. |
bit_count <= "0000"; -- normal reset |
elsif (timer_60usec_done = '1' ) and |
( m1_state = m1_rx_clk_h ) and |
( ps2_clk_s = '1' ) then |
bit_count <= "0000"; -- rx watchdog timer reset |
elsif ( m1_state = m1_rx_falling_edge_marker ) or -- increment for rx |
(m1_state = m1_tx_rising_edge_marker) then -- increment for tx |
bit_count <= bit_count + 1; |
end if; |
end if; |
|
if (bit_count = TOTAL_BITS) then |
rx_shifting_done <= '1'; |
else |
rx_shifting_done <= '0'; |
end if; |
|
if (bit_count = (TOTAL_BITS-1)) then |
tx_shifting_done <= '1'; |
else |
tx_shifting_done <= '0'; |
end if; |
if clk'event and clk = '0' then |
if ( reset = '1' ) or |
( rx_shifting_done = '1' ) or |
(m1_state = m1_tx_wait_keyboard_ack) then -- After tx is done. |
bit_count <= "0000"; -- normal reset |
elsif (timer_60usec_done = '1' ) and |
(m1_state = m1_rx_clk_h) and |
(ps2_clk_s = '1') then |
bit_count <= "0000"; -- rx watchdog timer reset |
elsif (m1_state = m1_rx_falling_edge_marker) or -- increment for rx |
(m1_state = m1_tx_rising_edge_marker) then -- increment for tx |
bit_count <= bit_count + 1; |
end if; |
end if; |
end process; |
|
assign: process( bit_count, tx_write, m1_state, tx_data_empty_o, m1_state ) |
assign: process( bit_count, tx_write, tx_data_empty_o, m1_state ) |
begin |
-- |
-- This is the signal which enables loading of the shift register. |
-- It also indicates "ack" to the device writing to the transmitter. |
-- |
if ((tx_write = '1') and (m1_state = m1_rx_clk_h)) or |
((tx_write = '1') and (m1_state = m1_rx_clk_l)) then |
tx_data_empty_o <= '1'; |
else |
tx_data_empty_o <= '0'; |
end if; |
tx_data_empty <= tx_data_empty_o; |
if (bit_count = TOTAL_BITS) then |
rx_shifting_done <= '1'; |
else |
rx_shifting_done <= '0'; |
end if; |
|
if (bit_count = (TOTAL_BITS-1)) then |
tx_shifting_done <= '1'; |
else |
tx_shifting_done <= '0'; |
end if; |
|
-- This is the signal which enables loading of the shift register. |
-- It also indicates "ack" to the device writing to the transmitter. |
if ((tx_write = '1') and (m1_state = m1_rx_clk_h)) or |
((tx_write = '1') and (m1_state = m1_rx_clk_l)) then |
tx_data_empty_o <= '1'; |
else |
tx_data_empty_o <= '0'; |
end if; |
tx_data_empty <= tx_data_empty_o; |
end process; |
|
-- This is the ODD parity bit for the transmitted word. |
-- assign tx_parity_bit = ~^tx_data; |
-- |
tx_parity_bit <= not( tx_data(7) xor tx_data(6) xor tx_data(5) xor tx_data(4) xor |
tx_data(3) xor tx_data(2) xor tx_data(1) xor tx_data(0) ); |
|
-- This is the shift register |
q_shift : process(clk, tx_data_empty_o, tx_parity_bit, tx_data, |
m1_state, q, ps2_data_s, rx_shifting_done ) |
begin |
-- |
-- This is the ODD parity bit for the transmitted word. |
-- assign tx_parity_bit = ~^tx_data; |
-- |
tx_parity_bit <= not( tx_data(7) xor tx_data(6) xor tx_data(5) xor tx_data(4) xor |
tx_data(3) xor tx_data(2) xor tx_data(1) xor tx_data(0) ); |
|
if clk'event and clk='0' then |
if (reset = '1') then |
q <= (others=>'0'); |
elsif (tx_data_empty_o = '1') then |
q <= "1" & tx_parity_bit & tx_data & "0"; |
elsif ( (m1_state = m1_rx_falling_edge_marker) or |
(m1_state = m1_tx_rising_edge_marker) ) then |
q <= ps2_data_s & q((TOTAL_BITS-1) downto 1); |
end if; |
end if; |
|
if clk'event and clk='0' then |
if (reset = '1') then |
q <= "00000000000"; |
elsif (tx_data_empty_o = '1') then |
q <= "1" & tx_parity_bit & tx_data & "0"; |
elsif ( (m1_state = m1_rx_falling_edge_marker) or |
(m1_state = m1_tx_rising_edge_marker) ) then |
q <= ps2_data_s & q((TOTAL_BITS-1) downto 1); |
end if; |
end if; |
|
-- Create the signals which indicate special scan codes received. |
-- These are the "unlatched versions." |
if (q(8 downto 1) = EXTEND_CODE) and (rx_shifting_done = '1') then |
extended <= '1'; |
else |
extended <= '0'; |
end if; |
if (q(8 downto 1) = RELEASE_CODE) and (rx_shifting_done = '1') then |
released <= '1'; |
else |
released <= '0'; |
end if; |
end process; |
|
-- |
|
-- This is the 60usec timer counter |
-- |
timer60usec: process(clk, enable_timer_60usec, timer_60usec_count) |
begin |
if clk'event and clk = '0' then |
if (enable_timer_60usec = '0') then |
timer_60usec_count <= (others => '0'); |
elsif (timer_60usec_done = '0') then |
timer_60usec_count <= timer_60usec_count + 1; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (enable_timer_60usec = '0') then |
timer_60usec_count <= (others => '0'); |
elsif (timer_60usec_done = '0') then |
timer_60usec_count <= timer_60usec_count + 1; |
end if; |
end if; |
|
if (timer_60usec_count = (TIMER_60USEC_VALUE_PP - 1)) then |
timer_60usec_done <= '1'; |
else |
timer_60usec_done <= '0'; |
end if; |
if (timer_60usec_count = (TIMER_60USEC_VALUE_PP - 1)) then |
timer_60usec_done <= '1'; |
else |
timer_60usec_done <= '0'; |
end if; |
end process; |
|
-- |
|
-- This is the 5usec timer counter |
-- |
timer5usec : process(clk, enable_timer_5usec, timer_5usec_count ) |
begin |
if clk'event and clk = '0' then |
if (enable_timer_5usec = '0') then |
timer_5usec_count <= (others => '0'); |
elsif (timer_5usec_done = '0') then |
timer_5usec_count <= timer_5usec_count + 1; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (enable_timer_5usec = '0') then |
timer_5usec_count <= (others => '0'); |
elsif (timer_5usec_done = '0') then |
timer_5usec_count <= timer_5usec_count + 1; |
end if; |
end if; |
|
if( timer_5usec_count = (TIMER_5USEC_VALUE_PP - 1)) then |
timer_5usec_done <= '1'; |
else |
timer_5usec_done <= '0'; |
end if; |
if( timer_5usec_count = (TIMER_5USEC_VALUE_PP - 1)) then |
timer_5usec_done <= '1'; |
else |
timer_5usec_done <= '0'; |
end if; |
end process; |
|
-- |
-- Create the signals which indicate special scan codes received. |
-- These are the "unlatched versions." |
-- |
extend_release_decode : process( q, rx_shifting_done, extended, released ) |
begin |
if (q(8 downto 1) = EXTEND_CODE) and (rx_shifting_done = '1') then |
extended <= '1'; |
else |
extended <= '0'; |
end if; |
|
if (q(8 downto 1) = RELEASE_CODE) and (rx_shifting_done = '1') then |
released <= '1'; |
else |
released <= '0'; |
end if; |
|
if (rx_shifting_done = '1') and (extended = '0') and (released = '0') then |
rx_output_event <= '1'; |
else |
rx_output_event <= '0'; |
end if; |
|
end process; |
|
-- |
|
-- Store the special scan code status bits |
-- Not the final output, but an intermediate storage place, |
-- until the entire set of output data can be assembled. |
-- |
special_scan : process(clk, reset, rx_output_event, rx_shifting_done, extended, released ) |
begin |
if clk'event and clk='0' then |
if (reset = '1') or (rx_output_event = '1') then |
hold_extended <= '0'; |
hold_released <= '0'; |
else |
if (rx_shifting_done = '1') and (extended = '1') then |
hold_extended <= '1'; |
end if; |
if (rx_shifting_done = '1') and (released = '1') then |
hold_released <= '1'; |
end if; |
end if; |
end if; |
|
if clk'event and clk='0' then |
if (reset = '1') or (rx_output_event = '1') then |
hold_extended <= '0'; |
hold_released <= '0'; |
else |
if (rx_shifting_done = '1') and (extended = '1') then |
hold_extended <= '1'; |
end if; |
if (rx_shifting_done = '1') and (released = '1') then |
hold_released <= '1'; |
end if; |
end if; |
end if; |
end process; |
|
-- |
-- convert scan code to ascii code |
-- |
scan_to_ascii : process( shift_key_on, caps_key_on, q ) |
begin |
shift_key_plus_code <= shift_key_on & caps_key_on & q(7 downto 1); |
end process; |
|
-- |
|
-- These bits contain the status of the two shift keys |
-- |
left_shift_proc : process(clk, reset, q, rx_shifting_done, hold_released ) |
begin |
if clk'event and clk = '0' then |
if (reset = '1') then |
left_shift_key <= '0'; |
elsif (q(8 downto 1) = LEFT_SHIFT) and (rx_shifting_done = '1') then |
left_shift_key <= not hold_released; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (reset = '1') then |
left_shift_key <= '0'; |
elsif (q(8 downto 1) = LEFT_SHIFT) and |
(rx_shifting_done = '1') and |
(hold_released = '0') then |
left_shift_key <= '1'; |
elsif (q(8 downto 1) = LEFT_SHIFT) and |
(rx_shifting_done = '1') and |
(hold_released = '1') then |
left_shift_key <= '0'; |
end if; |
end if; |
end process; |
|
right_shift_proc : process(clk, reset, q, rx_shifting_done, hold_released ) |
begin |
if clk'event and clk = '0' then |
if (reset = '1') then |
right_shift_key <= '0'; |
elsif (q(8 downto 1) = RIGHT_SHIFT) and (rx_shifting_done = '1') then |
right_shift_key <= not hold_released; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (reset = '1') then |
right_shift_key <= '0'; |
elsif (q(8 downto 1) = RIGHT_SHIFT) and |
(rx_shifting_done = '1') and |
(hold_released = '0') then |
right_shift_key <= '1'; |
elsif (q(8 downto 1) = RIGHT_SHIFT) and |
(rx_shifting_done = '1') and |
(hold_released = '1') then |
right_shift_key <= '0'; |
end if; |
end if; |
end process; |
|
shift_proc : process( left_shift_key, right_shift_key, shift_key_on, caps_key_on, q ) |
begin |
shift_key_on <= left_shift_key or right_shift_key; |
rx_shift_on <= shift_key_on; |
end process; |
|
shift_key_on <= left_shift_key or right_shift_key; |
rx_shift_on <= shift_key_on; |
|
-- |
-- Control keys |
-- |
ctrl_proc : process(clk, reset, q, rx_shifting_done, hold_released ) |
begin |
if clk'event and clk = '0' then |
if (reset = '1') then |
ctrl_key_on <= '0'; |
elsif (q(8 downto 1) = CTRL_CODE) and (rx_shifting_done = '1') then |
ctrl_key_on <= not hold_released; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (reset = '1') then |
ctrl_key_on <= '0'; |
elsif (q(8 downto 1) = CTRL_CODE) and |
(rx_shifting_done = '1') and |
(hold_released = '0') then |
ctrl_key_on <= '1'; |
elsif (q(8 downto 1) = CTRL_CODE) and |
(rx_shifting_done = '1') and |
(hold_released = '1') then |
ctrl_key_on <= '0'; |
end if; |
end if; |
end process; |
|
-- |
734,79 → 708,85
-- |
caps_proc : process(clk, reset, q, rx_shifting_done, hold_released, caps_key_on ) |
begin |
if clk'event and clk = '0' then |
if (reset = '1') then |
caps_key_on <= '0'; |
elsif (q(8 downto 1) = CAPS_CODE) and (rx_shifting_done = '1') then |
if (hold_released = '0') then |
caps_key_on <= not caps_key_on; |
end if; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (reset = '1') then |
caps_key_on <= '0'; |
elsif (q(8 downto 1) = CAPS_CODE) and |
(rx_shifting_done = '1') and |
(hold_released = '0') then |
caps_key_on <= not caps_key_on; |
end if; |
end if; |
end process; |
|
-- |
|
-- Output the special scan code flags, the scan code and the ascii |
-- |
special_scan_proc : process(clk, reset, rx_output_strobe, |
hold_extended, hold_released, |
ascii, ctrl_key_on ) |
special_scan_proc : process(clk, reset, |
hold_extended, hold_released, |
q, ascii, ctrl_key_on ) |
begin |
if clk'event and clk = '0' then |
if (reset = '1') then |
rx_extended <= '0'; |
rx_released <= '0'; |
rx_data <= (others=>'0'); |
elsif (rx_output_strobe = '1') then |
rx_extended <= hold_extended; |
rx_released <= hold_released; |
if ctrl_key_on = '1' then |
rx_data <= ascii and x"1f"; |
else |
rx_data <= ascii; |
end if; |
end if; |
end if; |
if clk'event and clk = '0' then |
if (reset = '1') then |
rx_extended <= '0'; |
rx_released <= '0'; |
-- rx_scan_code <= "00000000"; |
rx_data <= "00000000"; |
elsif (rx_output_strobe = '1') then |
rx_extended <= hold_extended; |
rx_released <= hold_released; |
-- rx_scan_code <= q(8 downto 1); |
elsif ctrl_key_on = '1' then |
rx_data <= ascii and x"1f"; |
else |
rx_data <= ascii; |
end if; |
end if; |
end process; |
|
-- |
|
-- Store the final rx output data only when all extend and release codes |
-- are received and the next (actual key) scan code is also ready. |
-- (the presence of rx_extended or rx_released refers to the |
-- the current latest scan code received, not the previously latched flags.) |
-- |
|
rx_output_proc : process( clk, reset, |
rx_shifting_done, rx_output_strobe, |
extended, released, |
hold_extended, hold_released, |
q, ascii, rx_read ) |
begin |
if clk'event and clk = '0' then |
if reset = '1' then |
rx_output_strobe <= '0'; |
elsif (rx_shifting_done = '1') and (rx_output_strobe = '0') and |
(extended = '0') and (released = '0') and |
(hold_released = '0' ) and |
(ascii /= "00000000" ) then |
-- ((TRAP_SHIFT_KEYS_PP = 0) or |
-- ( (q(8 downto 1) /= RIGHT_SHIFT) and |
-- (q(8 downto 1) /= LEFT_SHIFT) and |
-- (q(8 downto 1) /= CTRL_CODE) ) )then |
rx_output_strobe <= '1'; |
elsif rx_read = '1' then |
rx_output_strobe <= '0'; |
end if; |
end if; |
rx_data_ready <= rx_output_strobe; |
extended, released, |
q, ascii, rx_read ) |
begin |
if (rx_shifting_done = '1') and (extended = '0') and (released = '0') then |
rx_output_event <= '1'; |
else |
rx_output_event <= '0'; |
end if; |
|
if clk'event and clk = '0' then |
if reset = '1' then |
rx_output_strobe <= '0'; |
elsif (rx_shifting_done = '1') and |
(rx_output_strobe = '0') and |
(extended = '0') and |
(released = '0') and |
(hold_released = '0' ) and |
(ascii /= x"00" ) then |
-- ((TRAP_SHIFT_KEYS_PP = 0) or |
-- ( (q(8 downto 1) /= RIGHT_SHIFT) and |
-- (q(8 downto 1) /= LEFT_SHIFT) and |
-- (q(8 downto 1) /= CTRL_CODE) ) )then |
rx_output_strobe <= '1'; |
elsif rx_read = '1' then |
rx_output_strobe <= '0'; |
end if; |
end if; |
rx_data_ready <= rx_output_strobe; |
end process; |
|
-- |
-- This part translates the scan code into an ASCII value... |
-- Only the ASCII codes which I considered important have been included. |
-- if you want more, just add the appropriate case statement lines... |
-- (You will need to know the keyboard scan codes you wish to assign.) |
-- The entries are listed in ascending order of ASCII value. |
-- |
|
|
-- This part translates the scan code into an ASCII value... |
-- Only the ASCII codes which I considered important have been included. |
-- if you want more, just add the appropriate case statement lines... |
-- (You will need to know the keyboard scan codes you wish to assign.) |
-- The entries are listed in ascending order of ASCII value. |
shift_key_plus_code <= shift_key_on & caps_key_on & q(7 downto 1); |
|
--shift_map : process( shift_key_plus_code ) |
--begin |
-- case shift_key_plus_code is |
916,9 → 896,8
-- when x"10e" => ascii <= x"7e"; -- ~ |
-- when x"071" => ascii <= x"7f"; -- (Delete OR DEL on numeric keypad) |
-- when x"171" => ascii <= x"7f"; -- (Delete OR DEL on numeric keypad) |
-- when others => ascii <= x"00"; -- 0xff used for unlisted characters. |
-- when others => ascii <= x"ff"; -- 0xff used for unlisted characters. |
-- end case; |
--end process; |
|
|
end rtl; |
/vdu8.vhd
15,7 → 15,9
-- Supports 2 x 8 chunky graphics character mode. |
-- Uses Generic arguments for setting the video synchronization timing. |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.numeric_std |
-- |
-- Uses : ram_2k (ram2k_b16.vhd) 2KByte Character & Attribute buffer |
131,8 → 133,8
Library IEEE; |
use IEEE.std_logic_1164.all; |
use IEEE.numeric_std.all; |
--Library unisim; |
-- use unisim.vcomponents.all; |
Library unisim; |
use unisim.vcomponents.all; |
|
Entity vdu8 is |
generic( |
/pia6821.vhd
61,8 → 61,8
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity pia6821 is |
port ( |
/keyboard.vhd
14,6 → 14,7
-- ieee.std_logic_arith |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Uses : ps2_keyboard_interface |
-- |
87,8 → 88,8
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use ieee.numeric_std.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity keyboard is |
generic ( |
248,7 → 249,7
-- |
keyboard_status : process( kbd_data_ready, kbd_data_empty, |
kbd_extended, kbd_released, kbd_shift_on, kbd_error, |
kbd_control, kbd_status ) |
kbd_control) |
begin |
kbd_status(0) <= kbd_data_ready; |
kbd_status(1) <= kbd_data_empty; |
/pia_timer.vhd
122,7 → 122,7
signal ca1_rise : std_logic; |
signal ca1_fall : std_logic; |
signal ca1_edge : std_logic; |
signal irqa1 : std_logic := '0'; |
signal irqa1 : std_logic; |
|
signal ca2 : std_logic; |
signal ca2_del : std_logic; |
129,7 → 129,7
signal ca2_rise : std_logic; |
signal ca2_fall : std_logic; |
signal ca2_edge : std_logic; |
signal irqa2 : std_logic := '0'; |
signal irqa2 : std_logic; |
signal ca2_out : std_logic; |
|
signal cb1 : std_logic; |
137,7 → 137,7
signal cb1_rise : std_logic; |
signal cb1_fall : std_logic; |
signal cb1_edge : std_logic; |
signal irqb1 : std_logic := '0'; |
signal irqb1 : std_logic; |
|
signal cb2 : std_logic; |
signal cb2_del : std_logic; |
144,7 → 144,7
signal cb2_rise : std_logic; |
signal cb2_fall : std_logic; |
signal cb2_edge : std_logic; |
signal irqb2 : std_logic := '0'; |
signal irqb2 : std_logic; |
signal cb2_out : std_logic; |
|
-- 74193 down counter |
166,57 → 166,55
pa, pb ) |
variable count : integer; |
begin |
data_out <= "00000000"; |
porta_read <= '0'; |
portb_read <= '0'; |
|
case addr is |
when "00" => |
for count in 0 to 7 loop |
if porta_ctrl(2) = '0' then |
data_out(count) <= porta_ddr(count); |
porta_read <= '0'; |
else |
if porta_ddr(count) = '1' then |
data_out(count) <= porta_data(count); |
case addr is |
when "00" => |
for count in 0 to 7 loop |
if porta_ctrl(2) = '0' then |
data_out(count) <= porta_ddr(count); |
porta_read <= '0'; |
else |
data_out(count) <= pa(count); |
if porta_ddr(count) = '1' then |
data_out(count) <= porta_data(count); |
else |
data_out(count) <= pa(count); |
end if; |
porta_read <= cs; |
end if; |
porta_read <= cs; |
end if; |
end loop; |
portb_read <= '0'; |
end loop; |
portb_read <= '0'; |
|
when "01" => |
data_out <= irqa1 & irqa2 & porta_ctrl; |
porta_read <= '0'; |
portb_read <= '0'; |
when "01" => |
data_out <= irqa1 & irqa2 & porta_ctrl; |
porta_read <= '0'; |
portb_read <= '0'; |
|
when "10" => |
for count in 0 to 7 loop |
if portb_ctrl(2) = '0' then |
data_out(count) <= portb_ddr(count); |
portb_read <= '0'; |
else |
if portb_ddr(count) = '1' then |
when "10" => |
for count in 0 to 7 loop |
if portb_ctrl(2) = '0' then |
data_out(count) <= portb_ddr(count); |
portb_read <= '0'; |
else |
if portb_ddr(count) = '1' then |
data_out(count) <= portb_data(count); |
else |
else |
data_out(count) <= pb(count); |
end if; |
portb_read <= cs; |
end if; |
end loop; |
porta_read <= '0'; |
end if; |
portb_read <= cs; |
end if; |
end loop; |
porta_read <= '0'; |
|
when "11" => |
data_out <= irqb1 & irqb2 & portb_ctrl; |
porta_read <= '0'; |
portb_read <= '0'; |
when "11" => |
data_out <= irqb1 & irqb2 & portb_ctrl; |
porta_read <= '0'; |
portb_read <= '0'; |
|
when others => |
null; |
end case; |
when others => |
data_out <= "00000000"; |
porta_read <= '0'; |
portb_read <= '0'; |
|
end case; |
end process; |
|
--------------------------------- |
/ioport.vhd
55,8 → 55,8
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity ioport is |
port ( |
/vdu8_new.vhd
1,141 → 1,27
--===========================================================================-- |
-- -- |
-- vdu8_new.vhd - Synthesizable Colour Video Display Unit for System09 -- |
-- -- |
--===========================================================================-- |
-- --------------------------------------------------- |
-- Video Display terminal |
-- --------------------------------------------------- |
-- John Kent |
-- 3th September 2004 |
-- Assumes a pixel clock input of 25 MHz |
-- |
-- File name : vdu8_new.vhd |
-- Display Format is: |
-- 80 characters across by 25 characters down. |
-- 8 horizontal pixels / character |
-- 16 vertical scan lines / character (2 scan lines/row) |
-- |
-- Purpose : Implements a text based Colour Video Display Unit for System09 |
-- Supports 2KByte Text buffer and 2KByte Attribute memory |
-- Displays 80 characters across by 25 character rows |
-- Characters are 8 pixels across x 16 lines down. |
-- Character attribute bita for foreground and backgrond colour |
-- 1 bit for each Blue Green and Red signal |
-- Supports 2 x 8 chunky graphics character mode. |
-- Uses Generic arguments for setting the video synchronization timing. |
-- (I'm not sure what is "new" about this version.) |
-- |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_arith |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- Modified by Bert Cuzeau for compliance and code cleanliness |
-- The effort is not over. |
-- There are still signal initialized, which is BAD.\ |
-- |
-- Uses : ram_2k (ram2k_b16.vhd) 2KByte Character & Attribute buffer |
-- char_rom (char_rom2k_b16.vhd) 2KByte Character Generator ROM |
-- |
-- Author : John E. Kent |
-- |
-- Email : dilbert57@opencores.org |
-- |
-- Web : http://opencores.org/project,system09 |
-- |
-- Description : Display Timing: |
-- 800 pixels / line |
-- 446 lines / frame |
-- None interlaced |
-- 25MHz pixel clock implies |
-- 31.25 KHz line rate |
-- 70.067 Hz frame rate |
-- Timing settable by generics. |
-- |
-- Display Size: |
-- 80 characters across |
-- 25 characters down. |
-- |
-- Character Size: |
-- 8 horizontal pixels across |
-- 16 vertical scan lines down (2 scan lines/row) |
-- |
-- Registers: |
-- Base + 0 ASCII character register |
-- Writing to this register writes an 8 bit byte |
-- into the text buffer at the specified cursor position |
-- Text Mode: ASCII Character (0 to 127) |
-- Chunky Graphics Mode: B0 B1 (0 to 255) |
-- B2 B3 |
-- B4 B5 |
-- B6 B7 |
-- Base + 1 Attibute bit (0 to 255) |
-- Writing to the register writes an 8 bit byte |
-- into the attribute buffer at the specified cursor position |
-- B7 - 0 => Text Mode / 1 => Chunky Graphics Mode |
-- B6 - 1 => Character Background Blue |
-- B5 - 1 => Character Background Green |
-- B4 - 1 => Character Background Red |
-- B3 - 1 => Character Background & Foreground Alternates |
-- B2 - 1 => Character Foreground Blue |
-- B1 - 1 => Character Foreground Green |
-- B0 - 1 => Character Foreground Red |
-- Base + 2 Cursor Horizontal Position (0 to 79) |
-- Base + 3 Cusror Vertical Position (0 to 24) |
-- Base + 4 Vertical Scroll Offset (0 to 24) |
-- Scrolls the display up by the specified number of character rows |
-- |
-- |
-- Video Timing : |
-- |
-- Horizontal 800 Pixels/ 25MHz Pixel Clock = 32usec Line period = 31.25 KHz Line Frequency |
-- /--------------------------\_____________/---------------\______________/ |
-- 640 Pixels Display 16 Pixel FP 96 Pixel HS 48 Pixel BP |
-- |
-- VGA_CLK_FREQ : integer := 25000000; -- HZ |
-- VGA_HOR_FRONT_PORCH : integer := 16; -- PIXELS 0.64us (0.94us) |
-- VGA_HOR_SYNC : integer := 96; -- PIXELS 3.84us (3.77us) |
-- VGA_HOR_BACK_PORCH : integer := 48; -- PIXELS 1.92us (1.89us) |
-- VGA_PIX_PER_CHAR : integer := 8; -- PIXELS 0.32us |
-- VGA_HOR_CHARS : integer := 80; -- CHARACTERS 25.6us |
-- |
-- Vertical 446 Lines * 32 usec Line rate = 14.272ms Frame Period = 70.07Hz Frame frequency |
-- /---------------------------\____________/---------------\______________/ |
-- 400 Line Display 10 Line FP 2 Line VS 34 Line BP |
-- |
-- VGA_VER_FRONT_PORCH : integer := 10; -- LINES 0.320ms |
-- VGA_VER_SYNC : integer := 2; -- LINES 0.064ms |
-- VGA_VER_BACK_PORCH : integer := 34; -- LINES 1.088ms |
-- VGA_LIN_PER_CHAR : integer := 16; -- LINES 0.512ms |
-- VGA_VER_CHARS : integer := 25; -- CHARACTERS 12.8ms |
-- |
-- Copyright (C) 2003 - 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--===========================================================================-- |
-- -- |
-- Revision History -- |
-- -- |
--===========================================================================-- |
-- |
-- Version Author Date Changes |
-- 7th Februaury 2007 - John Kent |
-- Added generics for VGA Timing |
-- |
-- 0.1 John Kent 2004-09-03 Initial release |
-- |
-- 0.2 Bert Cuzeau 2007-01-16 Modified by for compliance and code cleanliness |
-- The effort is not over. |
-- There are still signal initialized, which is BAD. |
-- |
-- 0.3 John Kent 2007-02-07 Added generics for VGA Timing |
-- |
-- 0.4 John Kent 2010-06-16 Added GPL notice. Updated description |
-- I'm not sure what is "new" about this version |
-- |
|
Library IEEE; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
use ieee.numeric_std.all; |
library unisim; |
use unisim.vcomponents.all; |
142,17 → 28,18
|
Entity vdu8 is |
generic( |
VGA_CLK_FREQ : integer := 25000000; -- HZ |
VGA_HOR_CHARS : integer := 80; -- CHARACTERS 25.6us |
VGA_HOR_CHAR_PIXELS : integer := 8; -- PIXELS 0.32us |
VGA_HOR_FRONT_PORCH : integer := 16; -- PIXELS 0.64us |
VGA_HOR_SYNC : integer := 96; -- PIXELS 3.84us |
VGA_HOR_BACK_PORCH : integer := 48; -- PIXELS 1.92us |
VGA_VER_CHARS : integer := 25; -- CHARACTERS 12.8ms |
VGA_VER_CHAR_LINES : integer := 16; -- LINES 0.512ms |
VGA_VER_FRONT_PORCH : integer := 10; -- LINES 0.320ms |
VGA_VER_SYNC : integer := 2; -- LINES 0.064ms |
VGA_VER_BACK_PORCH : integer := 34 -- LINES 1.088ms |
VDU_CLOCK_FREQUENCY : integer := 25000000; -- HZ |
VGA_CLOCK_FREQUENCY : integer := 25000000; -- HZ |
VGA_HOR_CHARS : integer := 80; -- CHARACTERS |
VGA_VER_CHARS : integer := 25; -- CHARACTERS |
VGA_PIXELS_PER_CHAR : integer := 8; -- PIXELS |
VGA_LINES_PER_CHAR : integer := 16; -- LINES |
VGA_HOR_BACK_PORCH : integer := 40; -- PIXELS |
VGA_HOR_SYNC : integer := 96; -- PIXELS |
VGA_HOR_FRONT_PORCH : integer := 24; -- PIXELS |
VGA_VER_BACK_PORCH : integer := 13; -- LINES |
VGA_VER_SYNC : integer := 2; -- LINES |
VGA_VER_FRONT_PORCH : integer := 36 -- LINES |
); |
port( |
-- control register interface |
181,26 → 68,30
-- Displayed Characters per row |
constant HOR_DISP_CHR : integer := VGA_HOR_CHARS; |
-- Last horizontal pixel displayed |
constant HOR_DISP_END : integer := HOR_DISP_CHR * VGA_HOR_CHAR_PIXELS - 1; |
constant HOR_DISP_END : integer := HOR_DISP_CHR * VGA_PIXELS_PER_CHAR; |
-- Start of horizontal synch pulse |
constant HOR_SYNC_BEG : integer := HOR_DISP_END + VGA_HOR_FRONT_PORCH; |
constant HOR_SYNC_BEG : integer := HOR_DISP_END + VGA_HOR_BACK_PORCH; |
-- End of Horizontal Synch pulse |
constant HOR_SYNC_END : integer := HOR_SYNC_BEG + VGA_HOR_SYNC; |
-- Last pixel in scan line |
constant HOR_SCAN_END : integer := HOR_SYNC_END + VGA_HOR_BACK_PORCH; |
constant HOR_SCAN_END : integer := HOR_SYNC_END + VGA_HOR_FRONT_PORCH; |
-- Total Characters across the screen |
constant HOR_TOTAL_CHAR : integer := HOR_SCAN_END/VGA_PIXELS_PER_CHAR; |
|
-- Displayed Characters per Column |
constant VER_DISP_CHR : integer := VGA_VER_CHARS; |
-- last row displayed |
constant VER_DISP_END : integer := VER_DISP_CHR * VGA_VER_CHAR_LINES - 1; |
constant VER_DISP_END : integer := VER_DISP_CHR * VGA_LINES_PER_CHAR; |
-- start of vertical synch pulse |
constant VER_SYNC_BEG : integer := VER_DISP_END + VGA_VER_FRONT_PORCH; |
constant VER_SYNC_BEG : integer := VER_DISP_END + VGA_VER_BACK_PORCH; |
-- end of vertical synch pulse |
constant VER_SYNC_END : integer := VER_SYNC_BEG + VGA_VER_SYNC; |
-- Last scan row in the frame |
constant VER_SCAN_END : integer := VER_SYNC_END + VGA_VER_BACK_PORCH; |
|
constant BLINK_PERIOD : integer := 500; -- Blink Rate in msec |
constant VER_SCAN_END : integer := VER_SYNC_END + VGA_VER_FRONT_PORCH; |
-- Total Characters down the screen |
constant VER_TOTAL_CHAR : integer := VER_SCAN_END/VGA_LINES_PER_CHAR; |
|
constant BLINK_PERIOD : integer := 500; -- Blink Rate in msec |
constant BLINK_RATE : integer := BLINK_PERIOD * (VGA_CLOCK_FREQUENCY/1000); |
|
signal vga_rst : std_logic; |
211,11 → 102,11
signal video_on_v : std_logic := '0'; |
signal video_on_h : std_logic := '0'; |
signal h_count : natural range 0 to HOR_SCAN_END := 0; |
signal v_count : natural range 0 to VER_SCAN_END := 0; |
signal v_count : natural range 0 to VER_SCAN_END := 0; |
signal p_count : natural range 0 to VGA_PIXELS_PER_CHAR-1 := 0; |
signal l_count : std_logic_vector(3 downto 0) := "0000"; |
signal c_count : std_logic_vector(6 downto 0) := "0000000"; |
signal r_count : std_logic_vector(5 downto 0) := "000000"; |
signal r_count : std_logic_vector(5 downto 0) := "000000"; |
signal blink_count : natural range 0 to BLINK_RATE := 0; |
-- |
-- Character generator ROM |
262,7 → 153,7
signal vga_addr : std_logic_vector(10 downto 0) := (others=>'0'); -- 2K byte character buffer |
signal vga_data_out : std_logic_vector(7 downto 0); |
signal attr_data_out : std_logic_vector(7 downto 0); |
|
|
-- |
-- Character write handshake signals |
-- |
439,13 → 330,13
vga0_rw <= '1'; |
col_addr <= c_count; |
row_addr <= r_count + ("0" & reg_voffset(4 downto 0)); |
end case; |
end case; |
|
-- |
-- on vga_clk + 1 round off row address |
-- |
vga1_cs <= vga0_cs; |
vga1_rw <= vga0_rw; |
vga1_rw <= vga0_rw; |
if row_addr < VER_DISP_CHR then |
row1_addr <= row_addr; |
else |
485,9 → 376,9
vga_blue_o <= '0'; |
-- Put all video signals through DFFs to elminate any delays that cause a blurry image |
|
elsif falling_edge(vga_clk) then |
elsif falling_edge(vga_clk) then |
-- |
-- p_count = 0 load pixel shift register |
-- p_count = 0 load pixel shift register |
-- |
if p_count = 0 then |
if (req_write = '1') and (ack_write = '0') then |
496,31 → 387,31
ack_write <= '0'; |
else |
ack_write <= ack_write; |
end if; |
|
-- |
-- Pipeline video enable |
end if; |
|
-- |
-- Pipeline video enable |
-- |
video_on2 <= video_on1; |
video_on <= video_on2; |
-- |
-- Blink Cursor |
-- |
video_on <= video_on2; |
-- |
-- Blink Cursor |
-- |
if blink_count > (BLINK_RATE/2) then |
cursor_on <= cursor_on1 or attr_data_out(3); |
else |
cursor_on <= '0'; |
end if; |
-- |
-- Set forground and background colours |
cursor_on <= cursor_on1 or attr_data_out(3); |
else |
cursor_on <= '0'; |
end if; |
-- |
-- Set forground and background colours |
-- |
vga_fg_colour <= attr_data_out(2 downto 0); |
vga_bg_colour <= attr_data_out(6 downto 4); |
-- |
-- Attribute bit 7 |
vga_bg_colour <= attr_data_out(6 downto 4); |
-- |
-- Attribute bit 7 |
-- 0 => text |
-- 1 => chunky graphics |
-- |
-- 1 => chunky graphics |
-- |
if attr_data_out(7) = '0' then |
vga_shift <= char_data_out; |
else |
539,10 → 430,10
vga_shift(3 downto 0) <= vga_data_out(7) & vga_data_out(7) & vga_data_out(7) & vga_data_out(7); |
end case; |
end if; |
else |
-- |
-- p_count /= 0 shift out pixel shift register |
else |
-- |
-- p_count /= 0 shift out pixel shift register |
-- |
vga_shift <= vga_shift(6 downto 0) & '0'; |
end if; |
|
569,13 → 460,13
-- Generate Horizontal and Vertical Timing Signals for Video Signal |
-- |
vga_sync : process(vga_clk, vga_rst) |
begin |
if vga_rst = '1' then |
h_count <= 0; |
c_count <= "0000000"; |
begin |
if vga_rst = '1' then |
h_count <= 0; |
c_count <= "0000000"; |
p_count <= 0; |
v_count <= 0; |
l_count <= "0000"; |
v_count <= 0; |
l_count <= "0000"; |
r_count <= "000000"; |
horiz_sync <= '0'; |
vert_sync <= '0'; |
583,7 → 474,7
video_on_v <= '0'; |
cursor_on_h <= '0'; |
cursor_on_v <= '0'; |
blink_count <= BLINK_RATE; |
blink_count <= BLINK_RATE; |
elsif falling_edge(vga_clk) then |
-- |
-- H_count counts pixels (640 + extra time for sync signals) |
592,17 → 483,17
-- H_count 0 640 659 755 799 |
-- |
if h_count = HOR_SCAN_END then |
h_count <= 0; |
c_count <= "0000000"; |
h_count <= 0; |
c_count <= "0000000"; |
p_count <= 0; |
else |
h_count <= h_count + 1; |
p_count <= p_count + 1; |
if p_count = VGA_PIXELS_PER_CHAR-1 then |
p_count <= 0; |
c_count <= c_count + "0000001"; |
h_count <= h_count + 1; |
p_count <= p_count + 1; |
if p_count = VGA_PIXELS_PER_CHAR-1 then |
p_count <= 0; |
c_count <= c_count + "0000001"; |
end if; |
end if; |
end if; |
|
-- |
-- V_count counts rows of pixels |
613,17 → 504,17
-- V_count 0 400 413 414 444 |
-- |
if (v_count = VER_SCAN_END) and (h_count = HOR_SCAN_END) then |
v_count <= 0; |
l_count <= "0000"; |
v_count <= 0; |
l_count <= "0000"; |
r_count <= "000000"; |
elsif h_count = HOR_SYNC_END then |
v_count <= v_count + 1; |
l_count <= l_count + "0001"; |
if l_count = VGA_LINES_PER_CHAR-1 then |
l_count <= "0000"; |
r_count <= r_count + "000001"; |
l_count <= l_count + "0001"; |
if l_count = VGA_LINES_PER_CHAR-1 then |
l_count <= "0000"; |
r_count <= r_count + "000001"; |
end if; |
end if; |
end if; |
|
-- |
-- Generate Horizontal Sync Signal |
633,7 → 524,7
elsif h_count = HOR_SYNC_END then |
horiz_sync <= '0'; |
end if; |
|
|
-- |
-- Generate Vertical Sync Signal |
-- |
641,10 → 532,10
vert_sync <= '1'; |
elsif v_count = VER_SYNC_END then |
vert_sync <= '0'; |
end if; |
end if; |
|
-- |
-- Horizontal display enable |
-- Horizontal display enable |
-- |
if h_count = 0 then |
video_on_h <= '1'; |
653,7 → 544,7
end if; |
|
-- |
-- Verical display enable |
-- Verical display enable |
-- |
if v_count = 0 then |
video_on_v <= '1'; |
661,18 → 552,18
video_on_v <= '0'; |
end if; |
|
-- |
-- Horizontal cursor on |
-- |
-- Horizontal cursor on |
-- |
if c_count = reg_hcursor(6 downto 0) then |
cursor_on_h <= '1'; |
else |
cursor_on_h <= '0'; |
end if; |
|
-- |
-- Vertical cursor on |
|
-- |
-- Vertical cursor on |
-- |
if r_count = ("0" & reg_vcursor(4 downto 0)) then |
cursor_on_v <= '1'; |
else |
679,30 → 570,30
cursor_on_v <= '0'; |
end if; |
|
-- cursor_on is only active when on selected character |
if blink_count = 0 then |
blink_count <= BLINK_RATE; |
-- cursor_on is only active when on selected character |
if blink_count = 0 then |
blink_count <= BLINK_RATE; |
else |
blink_count <= blink_count - 1; |
blink_count <= blink_count - 1; |
end if; |
end if; |
|
end process; |
-- |
-- VGA reset = VDU reset |
-- VGA = timing section |
-- VDU = CPU registers |
-- |
end process; |
-- |
-- VGA reset = VDU reset |
-- VGA = timing section |
-- VDU = CPU registers |
-- |
vga_rst <= vdu_rst; |
-- |
-- VGA Sync for 640 pixels x 400 lines |
-- negative horizonal sync |
-- positive verical sync |
-- |
-- |
-- VGA Sync for 640 pixels x 400 lines |
-- negative horizonal sync |
-- positive verical sync |
-- |
vga_hsync_o <= not horiz_sync; |
vga_vsync_o <= vert_sync; |
-- |
-- video_on is high only when RGB data is displayed |
-- video_on is high only when RGB data is displayed |
-- |
video_on1 <= video_on_H and video_on_V; |
cursor_on1 <= cursor_on_h and cursor_on_v; |
/clock_dll.vhd
1,125 → 1,103
--===========================================================================-- |
-- -- |
-- clock_dll.vhd - Synthesible System Clock Divider for Xilinx Spartan 3 -- |
-- -- |
--===========================================================================-- |
--===========================================================================---- |
-- |
-- File name : clock_dll.vhd |
-- S Y N T H E Z I A B L E Clock_dll for System09 - SOC. |
-- |
-- Purpose : Implements a a system clock divider for System09. |
-- For Xilinx Spartan 3 and 3E FPGA boards |
-- Assumes a 12.5 MHz system clock input |
-- Generates a x1 (12.5 MHz) CPU clock |
-- Generates a x2 (25.0 MHz) VGA clock |
-- Generates a x4 (50.0 MHz) MEM clock |
-- |
-- Dependencies : ieee.std_logic_1164 |
--===========================================================================---- |
-- |
-- This core adheres to the GNU public license |
-- No responsibility is taken for this design. |
-- Use at own risk. |
-- |
-- File name : Clock_dll.vhd |
-- |
-- Purpose : Generates Clocks for System09 |
-- For BurchED B3-Spartan2+ and B5-X300 |
-- Assumes a 12.5 MHz system clock input |
-- Generates a x1 (12.5 MHz) CPU clock |
-- Generates a x2 (25.0 MHz) VGA clock |
-- Generates a x4 (50.0 MHz) MEM clock |
-- |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.std_logic_unsigned |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Author : John E. Kent |
-- |
-- Email : dilbert57@opencores.org |
-- |
-- Web : http://opencores.org/project,system09 |
-- |
-- clock_dll.vhd is a system clock divider for system09. |
-- |
-- Copyright (C) 2003 - 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--===========================================================================-- |
-- -- |
-- Revision History -- |
-- -- |
--===========================================================================-- |
-- |
-- Revision Name Date Description |
-- 0.1 John E. Kent 7th September 2008 Initial version |
-- 1.0 John E. Kent 30th May 2010 Added GPL Header |
-- |
-- ieee.numeric_std |
-- |
-- |
-- Revision History : |
-- |
-- Rev : 0.1 |
-- Date : 7th September 2008 |
-- Description : Initial version. |
-- |
-- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
use ieee.numeric_std.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity clock_dll is |
entity clock_dll is |
port( |
clk_in : in std_Logic; -- System Clock input |
clk_cpu : out std_logic; -- CPU Clock Out (x1) |
clk_vga : out std_logic; -- VGA Pixel Clock Out (x2) |
clk_mem : out std_logic; -- Memory Clock Out (x4) |
locked : out std_logic -- DLL in lock |
); |
end entity; |
|
clk_cpu : out std_logic; -- CPU Clock Out (x1) |
clk_vga : out std_logic; -- VGA Pixel Clock Out (x2) |
clk_mem : out std_logic; -- Memory Clock Out (x4) |
locked : out std_logic -- DLL in lock |
); |
end entity; |
|
architecture RTL of clock_dll is |
|
signal CPU_CLK0 : std_ulogic; |
signal CPU_CLK90 : std_ulogic; |
signal CPU_CLK180 : std_ulogic; |
signal CPU_CLK270 : std_ulogic; |
signal CPU_CLK2X : std_ulogic; |
signal CPU_CLKDV : std_ulogic; |
signal CPU_LOCKED : std_ulogic; |
signal CPU_CLKFB : std_ulogic; |
signal CPU_CLKIN : std_ulogic; |
signal CPU_RESET : std_ulogic; |
|
signal VGA_CLK0 : std_ulogic; |
signal VGA_CLK90 : std_ulogic; |
signal VGA_CLK180 : std_ulogic; |
signal VGA_CLK270 : std_ulogic; |
signal VGA_CLK2X : std_ulogic; |
signal VGA_CLKDV : std_ulogic; |
signal VGA_LOCKED : std_ulogic; |
|
signal CPU_CLK0 : std_ulogic; |
signal CPU_CLK90 : std_ulogic; |
signal CPU_CLK180 : std_ulogic; |
signal CPU_CLK270 : std_ulogic; |
signal CPU_CLK2X : std_ulogic; |
signal CPU_CLKDV : std_ulogic; |
signal CPU_LOCKED : std_ulogic; |
signal CPU_CLKFB : std_ulogic; |
signal CPU_CLKIN : std_ulogic; |
signal CPU_RESET : std_ulogic; |
|
signal VGA_CLK0 : std_ulogic; |
signal VGA_CLK90 : std_ulogic; |
signal VGA_CLK180 : std_ulogic; |
signal VGA_CLK270 : std_ulogic; |
signal VGA_CLK2X : std_ulogic; |
signal VGA_CLKDV : std_ulogic; |
signal VGA_LOCKED : std_ulogic; |
signal VGA_CLKFB : std_ulogic; |
signal VGA_CLKIN : std_ulogic; |
signal VGA_CLKIN : std_ulogic; |
signal VGA_RESET : std_ulogic; |
signal VGA_RESET_N : std_ulogic; |
|
-- Component Declaration for CLKDLL should be placed |
-- after architecture statement but before begin keyword |
|
component CLKDLL |
-- synthesis translate_off |
generic ( |
CLKDV_DIVIDE : real := 2.0; -- (1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 8.0, 16.0) |
DUTY_CYCLE_CORRECTION : Boolean := TRUE; -- (TRUE, FALSE) |
STARTUP_WAIT : boolean := FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port ( |
CLK0 : out STD_ULOGIC; |
CLK180 : out STD_ULOGIC; |
CLK270 : out STD_ULOGIC; |
CLK2X : out STD_ULOGIC; |
CLK90 : out STD_ULOGIC; |
CLKDV : out STD_ULOGIC; |
LOCKED : out STD_ULOGIC; |
CLKFB : in STD_ULOGIC; |
CLKIN : in STD_ULOGIC; |
RST : in STD_ULOGIC |
); |
end component; |
|
|
-- Component Declaration for CLKDLL should be placed |
-- after architecture statement but before begin keyword |
|
component CLKDLL |
-- synthesis translate_off |
generic ( |
CLKDV_DIVIDE : real := 2.0; -- (1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 8.0, 16.0) |
DUTY_CYCLE_CORRECTION : Boolean := TRUE; -- (TRUE, FALSE) |
STARTUP_WAIT : boolean := FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port ( |
CLK0 : out STD_ULOGIC; |
CLK180 : out STD_ULOGIC; |
CLK270 : out STD_ULOGIC; |
CLK2X : out STD_ULOGIC; |
CLK90 : out STD_ULOGIC; |
CLKDV : out STD_ULOGIC; |
LOCKED : out STD_ULOGIC; |
CLKFB : in STD_ULOGIC; |
CLKIN : in STD_ULOGIC; |
RST : in STD_ULOGIC |
); |
end component; |
|
component IBUFG |
port ( |
i: in std_logic; |
133,122 → 111,122
o: out std_logic |
); |
end component; |
|
component SRL16 |
port ( |
Q : out std_logic; |
D : in std_logic; |
CLK : in std_logic; |
A0 : in std_logic; |
A1 : in std_logic; |
A2 : in std_logic; |
A3 : in std_logic |
); |
end component; |
|
-- |
-- Start instantiation |
-- |
begin |
|
|
component SRL16 |
port ( |
Q : out std_logic; |
D : in std_logic; |
CLK : in std_logic; |
A0 : in std_logic; |
A1 : in std_logic; |
A2 : in std_logic; |
A3 : in std_logic |
); |
end component; |
|
-- |
-- Start instantiation |
-- |
begin |
|
-- |
-- 12.5MHz CPU clock input |
-- |
cpu_clkin_buffer : IBUFG |
cpu_clkin_buffer : IBUFG |
port map( |
i => clk_in, |
o => CPU_CLKIN |
); |
|
|
-- |
-- 12.5MHz CPU clock input |
-- |
cpu_clkout_buffer : BUFG |
cpu_clkout_buffer : BUFG |
port map( |
i => CPU_CLKIN, |
o => clk_cpu |
); |
|
|
-- |
-- 25 MHz VGA clock input |
-- |
cpu_clkfb_buffer : BUFG |
cpu_clkfb_buffer : BUFG |
port map( |
i => CPU_CLK2X, |
o => CPU_CLKFB |
); |
|
CLKDLL_CPU : CLKDLL |
-- synthesis translate_off |
generic map ( |
CLKDV_DIVIDE => 2.0, -- (1.5,2,2.5,3,4,5,8,16) |
DUTY_CYCLE_CORRECTION => TRUE, -- (TRUE, FALSE) |
STARTUP_WAIT => FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port map ( |
CLK0 => CPU_CLK0, |
CLK90 => CPU_CLK90, |
CLK180 => CPU_CLK180, |
CLK270 => CPU_CLK270, |
CLK2X => CPU_CLK2X, |
CLKDV => CPU_CLKDV, |
LOCKED => CPU_LOCKED, |
CLKFB => CPU_CLKFB, |
CLKIN => CPU_CLKIN, |
RST => CPU_RESET |
); |
|
|
CLKDLL_CPU : CLKDLL |
-- synthesis translate_off |
generic map ( |
CLKDV_DIVIDE => 2.0, -- (1.5,2,2.5,3,4,5,8,16) |
DUTY_CYCLE_CORRECTION => TRUE, -- (TRUE, FALSE) |
STARTUP_WAIT => FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port map ( |
CLK0 => CPU_CLK0, |
CLK90 => CPU_CLK90, |
CLK180 => CPU_CLK180, |
CLK270 => CPU_CLK270, |
CLK2X => CPU_CLK2X, |
CLKDV => CPU_CLKDV, |
LOCKED => CPU_LOCKED, |
CLKFB => CPU_CLKFB, |
CLKIN => CPU_CLKIN, |
RST => CPU_RESET |
); |
|
-- |
-- 25 MHz VGA clock output |
-- |
vga_clkfb_buffer : BUFG |
vga_clkfb_buffer : BUFG |
port map( |
i => VGA_CLK2X, |
o => VGA_CLKFB |
); |
|
CLKDLL_VGA : CLKDLL |
-- synthesis translate_off |
generic map ( |
CLKDV_DIVIDE => 2.0, -- (1.5,2,2.5,3,4,5,8,16) |
DUTY_CYCLE_CORRECTION => TRUE, -- (TRUE, FALSE) |
STARTUP_WAIT => FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port map ( |
CLK0 => VGA_CLK0, |
CLK90 => VGA_CLK90, |
CLK180 => VGA_CLK180, |
CLK270 => VGA_CLK270, |
CLK2X => VGA_CLK2X, |
CLKDV => VGA_CLKDV, |
LOCKED => VGA_LOCKED, |
CLKFB => VGA_CLKFB, |
CLKIN => VGA_CLKIN, |
RST => VGA_RESET |
); |
|
my_srl16 : SRL16 port map ( |
Q => VGA_RESET_N, |
D => CPU_LOCKED, |
CLK => CPU_CLKFB, |
A0 => '1', |
A1 => '1', |
A2 => '1', |
A3 => '1' |
); |
|
clock_dll_assign : process( VGA_RESET_N, VGA_LOCKED, |
clk_in, CPU_CLKFB, VGA_CLKFB ) |
begin |
VGA_RESET <= not VGA_RESET_N; |
VGA_CLKIN <= CPU_CLKFB; |
CPU_RESET <= '0'; |
clk_vga <= CPU_CLKFB; |
clk_mem <= VGA_CLKFB; |
locked <= VGA_LOCKED; |
end process; |
|
end architecture; |
|
CLKDLL_VGA : CLKDLL |
-- synthesis translate_off |
generic map ( |
CLKDV_DIVIDE => 2.0, -- (1.5,2,2.5,3,4,5,8,16) |
DUTY_CYCLE_CORRECTION => TRUE, -- (TRUE, FALSE) |
STARTUP_WAIT => FALSE -- (TRUE, FALSE) |
); |
-- synthesis translate_on |
port map ( |
CLK0 => VGA_CLK0, |
CLK90 => VGA_CLK90, |
CLK180 => VGA_CLK180, |
CLK270 => VGA_CLK270, |
CLK2X => VGA_CLK2X, |
CLKDV => VGA_CLKDV, |
LOCKED => VGA_LOCKED, |
CLKFB => VGA_CLKFB, |
CLKIN => VGA_CLKIN, |
RST => VGA_RESET |
); |
|
my_srl16 : SRL16 port map ( |
Q => VGA_RESET_N, |
D => CPU_LOCKED, |
CLK => CPU_CLKFB, |
A0 => '1', |
A1 => '1', |
A2 => '1', |
A3 => '1' |
); |
|
clock_dll_assign : process( VGA_RESET_N, VGA_LOCKED, |
clk_in, CPU_CLKFB, VGA_CLKFB ) |
begin |
VGA_RESET <= not VGA_RESET_N; |
VGA_CLKIN <= CPU_CLKFB; |
CPU_RESET <= '0'; |
clk_vga <= CPU_CLKFB; |
clk_mem <= VGA_CLKFB; |
locked <= VGA_LOCKED; |
end process; |
|
end architecture; |
|
/clock_div.vhd
1,65 → 1,42
--=========================================================================== |
--===========================================================================---- |
-- |
-- clock_div.vhd - Clock divider for System09 |
-- S Y N T H E Z I A B L E Clock_dll for System09 - SOC. |
-- |
--=========================================================================== |
-- |
-- File name : clock_div.vhd |
-- |
-- Entity name : clock_div |
--===========================================================================---- |
-- |
-- Purpose : Generates Clocks for System09 |
-- For BurchED B3-Spartan2+ and B5-X300 |
-- Divides the input clock which is normally 50MHz |
-- Generates a 1/1 (50.0 MHz) SYS clock |
-- Generates a 1/2 (25.0 MHz) VGA clock |
-- Generates a 1/4 (12.5 MHz) CPU clock |
-- This core adheres to the GNU public license |
-- No responsibility is taken for this design. |
-- Use at own risk. |
-- |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.numeric_std |
-- File name : Clock_dll.vhd |
-- |
-- Uses : IBUFG |
-- BUFG |
-- Purpose : Generates Clocks for System09 |
-- For BurchED B3-Spartan2+ and B5-X300 |
-- Assumes a 12.5 MHz system clock input |
-- Generates a x1 (12.5 MHz) CPU clock |
-- Generates a x2 (25.0 MHz) VGA clock |
-- Generates a x4 (50.0 MHz) MEM clock |
-- |
-- Author : John E. Kent |
-- dilbert57@opencores.org |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.numeric_std |
-- |
-- Copyright (C) 2003 - 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--=========================================================================== |
-- |
-- Revision History: |
-- |
--=========================================================================== |
-- Revision History : |
-- |
-- Rev: Date: Author: Description: |
-- |
-- 0.1 2008-09-07 John Kent Initial version |
-- 0.2 2010-09-14 John Kent Updated header |
-- Rev : 0.1 |
-- Date : 7th September 2008 |
-- Description : Initial version. |
-- |
-- |
-- |
library ieee; |
use ieee.std_logic_1164.all; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
use ieee.numeric_std.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity clock_div is |
port( |
72,8 → 49,16
|
architecture RTL of clock_div is |
|
signal div_clk : std_logic; |
signal div_count : std_logic_vector(1 downto 0); |
|
|
component IBUFG |
port ( |
i: in std_logic; |
o: out std_logic |
); |
end component; |
|
component BUFG |
port ( |
i: in std_logic; |
81,6 → 66,7
); |
end component; |
|
|
-- |
-- Start instantiation |
-- |
87,12 → 73,12
begin |
|
-- |
-- 50 MHz SYS clock output |
-- 50.0MHz system clock |
-- |
sys_clk_buffer : BUFG |
sys_clk_buffer : IBUFG |
port map( |
i => clk_in, |
o => sys_clk |
o => div_clk |
); |
|
-- |
116,11 → 102,12
-- |
-- Clock divider |
-- |
clock_div : process( clk_in ) |
clock_div : process( div_clk ) |
begin |
if rising_edge( clk_in ) then |
if rising_edge( div_clk) then |
div_count <= div_count + "01"; |
end if; |
sys_clk <= div_clk; |
end process; |
|
end architecture; |
/vdu8_bert.vhd
1,133 → 1,19
--===========================================================================-- |
-- -- |
-- vdu8_bert.vhd - Synthesizable Colour Video Display Unit for System09 -- |
-- -- |
--===========================================================================-- |
-- --------------------------------------------------- |
-- Video Display terminal |
-- --------------------------------------------------- |
-- John Kent |
-- 3th September 2004 |
-- Assumes a pixel clock input of 50 MHz |
-- Generates a 12.5MHz CPU Clock output |
-- |
-- File name : vdu8_bert.vhd |
-- Display Format is: |
-- 80 characters across by 25 characters down. |
-- 8 horizontal pixels / character |
-- 16 vertical scan lines / character (2 scan lines/row) |
-- |
-- Purpose : Implements a text based Colour Video Display Unit for System09 |
-- Supports 2KByte Text buffer and 2KByte Attribute memory |
-- Displays 80 characters across by 25 character rows |
-- Characters are 8 pixels across x 16 lines down. |
-- Character attribute bita for foreground and backgrond colour |
-- 1 bit for each Blue Green and Red signal |
-- Supports 2 x 8 chunky graphics character mode. |
-- Assumes a pixel clock input of 50 MHz |
-- Generates a 12.5MHz CPU Clock output for old Spartan 2 boards. |
-- Partially cleaned up by Bertrand Cuzeau |
-- |
-- Dependencies : ieee.Std_Logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- ieee.numeric_std |
-- |
-- Uses : ram_2k (ram2k_b16.vhd) 2KByte Character & Attribute buffer |
-- char_rom (char_rom2k_b16.vhd) 2KByte Character Generator ROM |
-- |
-- Author : John E. Kent |
-- |
-- Email : dilbert57@opencores.org |
-- |
-- Web : http://opencores.org/project,system09 |
-- |
-- Description : Display Timing: |
-- 800 pixels / line |
-- 446 lines / frame |
-- None interlaced |
-- 25MHz pixel clock implies |
-- 31.25 KHz line rate |
-- 70.067 Hz frame rate |
-- Timing settable by generics. |
-- |
-- Display Size: |
-- 80 characters across |
-- 25 characters down. |
-- |
-- Character Size: |
-- 8 horizontal pixels across |
-- 16 vertical scan lines down (2 scan lines/row) |
-- |
-- Registers: |
-- Base + 0 ASCII character register |
-- Writing to this register writes an 8 bit byte |
-- into the text buffer at the specified cursor position |
-- Text Mode: ASCII Character (0 to 127) |
-- Chunky Graphics Mode: B0 B1 (0 to 255) |
-- B2 B3 |
-- B4 B5 |
-- B6 B7 |
-- Base + 1 Attibute bit (0 to 255) |
-- Writing to the register writes an 8 bit byte |
-- into the attribute buffer at the specified cursor position |
-- B7 - 0 => Text Mode / 1 => Chunky Graphics Mode |
-- B6 - 1 => Character Background Blue |
-- B5 - 1 => Character Background Green |
-- B4 - 1 => Character Background Red |
-- B3 - 1 => Character Background & Foreground Alternates |
-- B2 - 1 => Character Foreground Blue |
-- B1 - 1 => Character Foreground Green |
-- B0 - 1 => Character Foreground Red |
-- Base + 2 Cursor Horizontal Position (0 to 79) |
-- Base + 3 Cusror Vertical Position (0 to 24) |
-- Base + 4 Vertical Scroll Offset (0 to 24) |
-- Scrolls the display up by the specified number of character rows |
-- |
-- Video Timing : |
-- |
-- Horizontal 800 Pixels/ 25MHz Pixel Clock = 32usec Line period = 31.25 KHz Line Frequency |
-- /--------------------------\_____________/---------------\______________/ |
-- 640 Pixels Display 16 Pixel FP 96 Pixel HS 48 Pixel BP |
-- |
-- VGA_CLK_FREQ : integer := 25000000; -- HZ |
-- VGA_HOR_FRONT_PORCH : integer := 16; -- PIXELS 0.64us (0.94us) |
-- VGA_HOR_SYNC : integer := 96; -- PIXELS 3.84us (3.77us) |
-- VGA_HOR_BACK_PORCH : integer := 48; -- PIXELS 1.92us (1.89us) |
-- VGA_PIX_PER_CHAR : integer := 8; -- PIXELS 0.32us |
-- VGA_HOR_CHARS : integer := 80; -- CHARACTERS 25.6us |
-- |
-- Vertical 446 Lines * 32 usec Line rate = 14.272ms Frame Period = 70.07Hz Frame frequency |
-- /---------------------------\____________/---------------\______________/ |
-- 400 Line Display 10 Line FP 2 Line VS 34 Line BP |
-- |
-- VGA_VER_FRONT_PORCH : integer := 10; -- LINES 0.320ms |
-- VGA_VER_SYNC : integer := 2; -- LINES 0.064ms |
-- VGA_VER_BACK_PORCH : integer := 34; -- LINES 1.088ms |
-- VGA_LIN_PER_CHAR : integer := 16; -- LINES 0.512ms |
-- VGA_VER_CHARS : integer := 25; -- CHARACTERS 12.8ms |
-- |
-- |
-- Copyright (C) 2003 - 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--===========================================================================-- |
-- -- |
-- Revision History -- |
-- -- |
--===========================================================================-- |
-- |
-- Version Author Date Changes |
-- |
-- 0.1 John Kent 2004-09-03 Initial release |
-- |
-- 0.2 Bert Cuzeau 2007-01-16 Modified by for compliance and code cleanliness |
-- The effort is not over. |
-- There are still signal initialized, which is BAD. |
-- |
-- 0.3 John Kent 2010-06-16 Added GPL notice. Updated description |
-- |
-- Modified by Bert Cuzeau for compliance and code cleanliness |
-- The effort is not over. |
-- There are still signal initialized, which is BAD. |
|
Library IEEE; |
use IEEE.std_logic_1164.all; |
134,19 → 20,6
use IEEE.numeric_std.all; |
|
Entity vdu8 is |
generic( |
VGA_CLK_FREQ : integer := 25000000; -- HZ |
VGA_HOR_CHARS : integer := 80; -- CHARACTERS 25.6us |
VGA_HOR_CHAR_PIXELS : integer := 8; -- PIXELS 0.32us |
VGA_HOR_FRONT_PORCH : integer := 16; -- PIXELS 0.64us |
VGA_HOR_SYNC : integer := 96; -- PIXELS 3.84us |
VGA_HOR_BACK_PORCH : integer := 48; -- PIXELS 1.92us |
VGA_VER_CHARS : integer := 25; -- CHARACTERS 12.8ms |
VGA_VER_CHAR_LINES : integer := 16; -- LINES 0.512ms |
VGA_VER_FRONT_PORCH : integer := 10; -- LINES 0.320ms |
VGA_VER_SYNC : integer := 2; -- LINES 0.064ms |
VGA_VER_BACK_PORCH : integer := 34 -- LINES 1.088ms |
); |
port( |
-- control register interface |
vdu_clk_in : in std_logic; -- 50MHz System clock |
172,31 → 45,18
-- |
-- Synchronisation constants |
-- |
-- |
-- Synchronisation constants |
-- |
-- Displayed Characters per row |
constant HOR_DISP_CHR : integer := VGA_HOR_CHARS; |
-- Last horizontal pixel displayed |
constant HOR_DISP_END : integer := (HOR_DISP_CHR * VGA_HOR_CHAR_PIXELS) - 1; |
-- Start of horizontal synch pulse |
constant HOR_SYNC_BEG : integer := HOR_DISP_END + VGA_HOR_FRONT_PORCH; |
-- End of Horizontal Synch pulse |
constant HOR_SYNC_END : integer := HOR_SYNC_BEG + VGA_HOR_SYNC; |
-- Last pixel in scan line |
constant HOR_SCAN_END : integer := HOR_SYNC_END + VGA_HOR_BACK_PORCH; |
|
-- Number of displayed characters rows |
constant VER_DISP_CHR : integer := VGA_VER_CHARS; |
-- last row displayed |
constant VER_DISP_END : integer := (VER_DISP_CHR * VGA_VER_CHAR_LINES) - 1; |
-- start of vertical synch pulse |
constant VER_SYNC_BEG : integer := VER_DISP_END + VGA_VER_FRONT_PORCH; |
-- end of vertical synch pulse |
constant VER_SYNC_END : integer := VER_SYNC_BEG + VGA_VER_SYNC; |
-- Last scan row in the frame |
constant VER_SCAN_END : integer := VER_SYNC_END + VGA_VER_BACK_PORCH; |
constant HOR_DISP_END : integer := 639; -- Last horizontal pixel displayed |
constant HOR_SYNC_BEG : integer := 679; -- Start of horizontal synch pulse |
constant HOR_SYNC_END : integer := 775; -- End of Horizontal Synch pulse |
constant HOR_SCAN_END : integer := 799; -- Last pixel in scan line |
constant HOR_DISP_CHR : integer := 80; -- Number of characters displayed per row |
|
constant VER_DISP_END : integer := 399; -- last row displayed |
constant VER_SYNC_BEG : integer := 413; -- start of vertical synch pulse |
constant VER_SYNC_END : integer := 414; -- end of vertical synch pulse |
constant VER_SCAN_END : integer := 450; -- Last scan row in the frame |
constant VER_DISP_CHR : integer := 25; -- Number of character rows displayed |
|
signal horiz_sync : std_logic := '1'; |
signal vert_sync : std_logic := '1'; |
signal cursor_on_v : std_logic; |
/ACIA_RX.vhd
0,0 → 1,380
--===========================================================================-- |
-- |
-- S Y N T H E Z I A B L E ACIA 6850 C O R E |
-- |
-- www.OpenCores.Org - January 2007 |
-- This core adheres to the GNU public license |
-- |
-- Design units : 6850 ACIA core for the System68/09 |
-- |
-- File name : ACIA_RX.vhd |
-- |
-- Purpose : Implements a 6850 ACIA device for communication purposes |
-- between the cpu68/09 cpu and the Host computer through |
-- an RS-232 communication protocol. |
-- |
-- Dependencies : ieee.std_logic_1164.all; |
-- ieee.numeric_std.all; |
-- ieee.std_logic_unsigned.all; |
-- unisim.vcomponents.all; |
-- |
--===========================================================================-- |
------------------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas 15 January 2000 New model |
-- 2.0 Ovidiu Lupas 17 April 2000 samples counter cleared for bit 0 |
-- olupas@opencores.org |
-- |
-- 3.0 John Kent 5 January 2003 Added 6850 word format control |
-- 3.1 John Kent 12 January 2003 Significantly revamped receive code. |
-- 3.2 John Kent 10 January 2004 Rewrite of code. |
-- 4.0 John Kent 3 February 2007 Renamed to ACIA 6850 |
-- Removed input debounce |
-- 4.1 John Kent 4 February 2007 Cleaned up Rx state machine |
-- 4.2 John Kent 25 February 2007 Modified sensitivity lists |
-- |
-- dilbert57@opencores.org |
------------------------------------------------------------------------------- |
-- |
-- Description : Implements the receive unit of the ACIA_6850 core. |
-- Samples 16 times the RxD line and retain the value |
-- in the middle of the time interval. |
-- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
--library unisim; |
-- use unisim.vcomponents.all; |
|
------------------------------------------------------------------------------- |
-- Entity for the ACIA Receiver |
------------------------------------------------------------------------------- |
entity ACIA_RX is |
port ( |
Clk : in Std_Logic; -- Clock signal |
RxRst : in Std_Logic; -- Reset input |
RxRd : in Std_Logic; -- Read data strobe |
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format |
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format |
RxClk : in Std_Logic; -- RS-232 clock input |
RxDat : in Std_Logic; -- RS-232 data input |
RxFErr : out Std_Logic; -- Framing Error status |
RxOErr : out Std_Logic; -- Over Run Error Status |
RxPErr : out Std_logic; -- Parity Error Status |
RxRdy : out Std_Logic; -- Data Ready Status |
RxDout : out Std_Logic_Vector(7 downto 0) |
); |
end ACIA_RX; --================== End of entity ==============================-- |
|
------------------------------------------------------------------------------- |
-- Architecture for ACIA receiver |
------------------------------------------------------------------------------- |
|
architecture rtl of ACIA_RX is |
|
type RxStateType is ( RxStart_State, RxData_state, |
RxParity_state, RxStop_state ); |
|
----------------------------------------------------------------------------- |
-- Signals |
----------------------------------------------------------------------------- |
signal RxDatDel0 : Std_Logic := '0'; -- Delayed Rx Data |
signal RxDatDel1 : Std_Logic := '0'; -- Delayed Rx Data |
signal RxDatDel2 : Std_Logic := '0'; -- Delayed Rx Data |
signal RxDatEdge : Std_Logic := '0'; -- Rx Data Edge pulse |
signal RxClkDel : Std_Logic := '0'; -- Delayed Rx Input Clock |
signal RxClkEdge : Std_Logic := '0'; -- Rx Input Clock Edge pulse |
signal RxStart : Std_Logic := '0'; -- Rx Start request |
signal RxEnable : Std_Logic := '0'; -- Rx Enabled |
signal RxClkCnt : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Rx Baud Clock Counter |
signal RxBdClk : Std_Logic := '0'; -- Rx Baud Clock |
signal RxBdDel : Std_Logic := '0'; -- Delayed Rx Baud Clock |
signal RxBdEdge : Std_Logic := '0'; -- Rx Baud Clock Edge pulse |
|
signal RxReady : Std_Logic := '0'; -- Data Ready flag |
signal RxReq : Std_Logic := '0'; -- Rx Data Valid |
signal RxAck : Std_Logic := '0'; -- Rx Data Valid |
signal RxParity : Std_Logic := '0'; -- Calculated RX parity bit |
signal RxState : RxStateType; -- receive bit state |
signal RxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Rx Bit counter |
signal RxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Shift Register |
|
begin |
|
--------------------------------------------------------------------- |
-- Receiver Clock Edge Detection |
--------------------------------------------------------------------- |
-- A rising edge will produce a one clock cycle pulse |
-- |
-- acia_rx_clock_edge : process( Clk, RxRst, RxClk, RxClkDel ) |
acia_rx_clock_edge : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxClkDel <= '0'; |
RxClkEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
RxClkDel <= RxClk; |
RxClkEdge <= (not RxClkDel) and RxClk; |
end if; |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Data Edge Detection |
--------------------------------------------------------------------- |
-- A falling edge will produce a pulse on RxClk wide |
-- |
-- acia_rx_data_edge : process(Clk, RxRst, RxClkEdge, RxDat, RxDatDel0, RxDatDel1, RxDatDel2 ) |
acia_rx_data_edge : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxDatDel0 <= '0'; |
RxDatDel1 <= '0'; |
RxDatDel2 <= '0'; |
RxDatEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
-- if RxClkEdge = '1' then |
RxDatDel0 <= RxDat; |
RxDatDel1 <= RxDatDel0; |
RxDatDel2 <= RxDatDel1; |
RxDatEdge <= RxDatDel0 and (not RxDat); |
-- end if; |
end if; |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Start / Stop |
--------------------------------------------------------------------- |
-- Enable the receive clock on detection of a start bit |
-- Disable the receive clock after a byte is received. |
-- |
-- acia_rx_start_stop : process( Clk, RxRst, RxDatEdge, RxAck, RxStart, RxEnable ) |
acia_rx_start_stop : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxEnable <= '0'; |
RxStart <= '0'; |
elsif Clk'event and Clk='0' then |
if (RxEnable = '0') and (RxDatEdge = '1') then |
-- Data Edge detected |
-- Request Start and Enable Receive Clock. |
RxEnable <= '1'; |
RxStart <= '1'; |
else |
if (RxStart = '1') and (RxAck = '1') then |
-- Data is being received |
-- reset start request |
RxStart <= '0'; |
else |
-- Data has now been received |
-- Disable Receiver until next start bit |
if (RxStart = '0') and (RxAck = '0') then |
RxEnable <= '0'; |
end if; |
end if; -- RxStart |
end if; -- RxDatEdge |
end if; -- clk / RxRst |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Clock Divider |
--------------------------------------------------------------------- |
-- Hold the Rx Clock divider in reset when the receiver is disabled |
-- Advance the count only on a rising Rx clock edge |
-- |
-- acia_rx_clock_divide : process( Clk, RxRst, RxEnable, RxClkEdge, RxClkCnt ) |
acia_rx_clock_divide : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxClkCnt <= (others => '0'); |
elsif Clk'event and Clk = '0' then |
-- if RxEnable = '0' then |
if RxDatEdge = '1' then |
RxClkCnt <= (others => '0'); -- reset on falling data edge |
else |
if RxClkEdge = '1' then -- increment count on Clock edge |
RxClkCnt <= RxClkCnt + "000001"; |
end if; -- RxClkEdge |
end if; -- RxState |
end if; -- clk / RxRst |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Baud Clock Selector |
--------------------------------------------------------------------- |
-- BdFmt |
-- 0 0 - Baud Clk divide by 1 |
-- 0 1 - Baud Clk divide by 16 |
-- 1 0 - Baud Clk divide by 64 |
-- 1 1 - Reset |
-- |
acia_rx_baud_clock_select : process( BdFmt, RxClk, RxClkCnt ) |
begin |
case BdFmt is |
when "00" => -- Div by 1 |
RxBdClk <= RxClk; |
when "01" => -- Div by 16 |
RxBdClk <= RxClkCnt(3); |
when "10" => -- Div by 64 |
RxBdClk <= RxClkCnt(5); |
when others => -- RxRst |
RxBdClk <= '0'; |
end case; |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Baud Clock Edge Detect |
--------------------------------------------------------------------- |
-- |
-- Generate one clock strobe on rising baud clock edge |
-- |
-- acia_rx_baud_clock_edge : process( Clk, RxRst, RxBdClk, RxBdDel ) |
acia_rx_baud_clock_edge : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxBdDel <= '0'; |
RxBdEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
RxBdDel <= RxBdClk; |
RxBdEdge <= RxBdClk and (not RxBdDel); |
end if; |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver process |
--------------------------------------------------------------------- |
-- WdFmt - Bits[4..2] |
-- 0 0 0 - 7 data, even parity, 2 stop |
-- 0 0 1 - 7 data, odd parity, 2 stop |
-- 0 1 0 - 7 data, even parity, 1 stop |
-- 0 1 1 - 7 data, odd parity, 1 stop |
-- 1 0 0 - 8 data, no parity, 2 stop |
-- 1 0 1 - 8 data, no parity, 1 stop |
-- 1 1 0 - 8 data, even parity, 1 stop |
-- 1 1 1 - 8 data, odd parity, 1 stop |
-- acia_rx_receive : process( Clk, RxRst, RxState, RxBdEdge, RxDatDel2, RxBitCount, RxReady, RxShiftReg ) |
acia_rx_receive : process( RxRst, Clk ) |
begin |
if RxRst = '1' then |
RxFErr <= '0'; |
RxOErr <= '0'; |
RxPErr <= '0'; |
RxShiftReg <= (others => '0'); -- Resert Shift register |
RxDOut <= (others => '0'); |
RxParity <= '0'; -- reset Parity bit |
RxAck <= '0'; -- Receiving data |
RxBitCount <= (others => '0'); |
RxState <= RxStart_state; |
elsif Clk'event and Clk='0' then |
if RxBdEdge = '1' then |
case RxState is |
when RxStart_state => |
RxShiftReg <= (others => '0'); -- Reset Shift register |
RxParity <= '0'; -- Parity bit |
if WdFmt(2) = '0' then |
-- WdFmt(2) = '0' => 7 data |
RxBitCount <= "110"; |
else |
-- WdFmt(2) = '1' => 8 data |
RxBitCount <= "111"; |
end if; |
if RxDatDel2 = '0' then -- look for start request |
RxState <= RxData_state; -- yes, read data |
end if; |
|
when RxData_state => -- data bits 0 to 6 |
RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); |
RxParity <= RxParity xor RxDatDel2; |
RxAck <= '1'; -- Flag receive in progress |
RxBitCount <= RxBitCount - "001"; |
if RxBitCount = "000" then |
if WdFmt(2) = '0' then -- WdFmt(2) = '0' => 7 data |
RxState <= RxParity_state; -- 7 bits always has parity |
else -- WdFmt(2) = '1' => 8 data |
if WdFmt(1) = '0' then |
RxState <= RxStop_state; -- WdFmt(1) = '0' no parity |
else |
RxState <= RxParity_state; -- WdFmt(1) = '1' parity |
end if; -- WdFmt(1) |
end if; -- WdFmt(2) |
end if; -- RxBitCount |
|
when RxParity_state => -- parity bit |
if WdFmt(2) = '0' then -- 7 data, shift right |
RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); -- 7 data + parity |
end if; |
if WdFmt(0) = '0' then -- parity polarity ? |
if RxParity = RxDatDel2 then -- check even parity |
RxPErr <= '1'; |
else |
RxPErr <= '0'; |
end if; |
else |
if RxParity = RxDatDel2 then -- check for odd parity |
RxPErr <= '0'; |
else |
RxPErr <= '1'; |
end if; |
end if; |
RxState <= RxStop_state; |
|
when RxStop_state => -- stop bit (Only one required for RX) |
RxAck <= '0'; -- Flag Receive Complete |
RxDOut <= RxShiftReg; |
if RxDatDel2 = '1' then -- stop bit expected |
RxFErr <= '0'; -- yes, no framing error |
else |
RxFErr <= '1'; -- no, framing error |
end if; |
if RxReady = '1' then -- Has previous data been read ? |
RxOErr <= '1'; -- no, overrun error |
else |
RxOErr <= '0'; -- yes, no over run error |
end if; |
RxState <= RxStart_state; |
|
when others => |
RxAck <= '0'; -- Flag Receive Complete |
RxState <= RxStart_state; |
end case; -- RxState |
|
end if; -- RxBdEdge |
end if; -- clk / RxRst |
|
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Read process |
--------------------------------------------------------------------- |
-- acia_rx_read : process(Clk, RxRst, RxRd, RxReq, RxAck, RxReady ) |
acia_rx_read : process( RxRst, Clk, RxReady ) |
begin |
if RxRst = '1' then |
RxReady <= '0'; |
RxReq <= '0'; |
elsif Clk'event and Clk='0' then |
if RxRd = '1' then |
-- Data was read, Reset data ready |
-- Request more data |
RxReady <= '0'; |
RxReq <= '1'; |
else |
if RxReq = '1' and RxAck = '1' then |
-- Data is being received |
-- reset receive request |
RxReq <= '0'; |
else |
-- Data now received |
-- Flag RxReady and read Shift Register |
if RxReq = '0' and RxAck = '0' then |
RxReady <= '1'; |
end if; |
end if; -- RxReq |
end if; -- RxRd |
end if; -- clk / RxRst |
RxRdy <= RxReady; |
end process; |
|
end rtl; --==================== End of architecture ====================-- |
/ACIA_TX.vhd
0,0 → 1,284
--===========================================================================-- |
-- |
-- S Y N T H E Z I A B L E ACIA 6850 C O R E |
-- |
-- www.OpenCores.Org - January 2007 |
-- This core adheres to the GNU public license |
-- |
-- Design units : 6850 ACIA core for the System68/09 |
-- |
-- File name : ACIA_TX.vhd |
-- |
-- Purpose : Implements an ACIA device for communication purposes |
-- between the FPGA processor and the Host computer through |
-- a RS-232 communication protocol. |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- ieee.numeric_std |
-- ieee.std_logic_unsigned |
-- |
--===========================================================================-- |
------------------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas 15 January 2000 New model |
-- 2.0 Ovidiu Lupas 17 April 2000 unnecessary variable removed |
-- |
-- 3.0 John Kent 5 January 2003 added 6850 word format control |
-- 3.1 John Kent 12 January 2003 Rearranged state machine code |
-- 3.2 John Kent 30 March 2003 Revamped State machine |
-- 3.3 John Kent 16 January 2004 Major re-write - added baud rate gen |
-- 4.0 John Kent 3 February 2007 renamed txunit to ACIA_TX |
-- 4.1 John Kent 4 February 2007 Cleaned up transmiter |
-- 4.2 John Kent 25 Februauy 2007 Modify sensitivity lists and |
-- split Tx Baud Clock select |
-- and edge detection. |
-- dilbert57@opencores.org |
-- |
------------------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
|
------------------------------------------------------------------------------- |
-- Entity for the ACIA Transmitter |
------------------------------------------------------------------------------- |
entity ACIA_TX is |
port ( |
Clk : in Std_Logic; -- CPU Clock signal |
TxRst : in Std_Logic; -- Reset input |
TxWr : in Std_Logic; -- Load transmit data |
TxDin : in Std_Logic_Vector(7 downto 0); -- Transmit data input. |
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format |
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format |
TxClk : in Std_Logic; -- Enable input |
TxDat : out Std_Logic; -- RS-232 data bit output |
TxEmp : out Std_Logic ); -- Tx buffer empty |
end ACIA_TX; --================== End of entity ==============================-- |
|
------------------------------------------------------------------------------- |
-- Architecture for ACIA_TX |
------------------------------------------------------------------------------- |
|
architecture rtl of ACIA_TX is |
|
type TxStateType is ( Tx1Stop_State, TxStart_State, |
TxData_State, TxParity_State, Tx2Stop_State ); |
|
----------------------------------------------------------------------------- |
-- Signals |
----------------------------------------------------------------------------- |
|
signal TxClkDel : Std_Logic := '0'; -- Delayed Tx Input Clock |
signal TxClkEdge : Std_Logic := '0'; -- Tx Input Clock Edge pulse |
signal TxClkCnt : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Tx Baud Clock Counter |
signal TxBdDel : Std_Logic := '0'; -- Delayed Tx Baud Clock |
signal TxBdEdge : Std_Logic := '0'; -- Tx Baud Clock Edge pulse |
signal TxBdClk : Std_Logic := '0'; -- Tx Baud Clock |
signal TxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Transmit shift register |
signal TxParity : Std_logic := '0'; -- Parity Bit |
signal TxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Data Bit Counter |
signal TxReq : Std_Logic := '0'; -- Request Transmit |
signal TxAck : Std_Logic := '0'; -- Transmit Commenced |
signal TxState : TxStateType; -- Transmitter state |
|
begin |
|
--------------------------------------------------------------------- |
-- Transmit Clock Edge Detection |
-- A falling edge will produce a one clock cycle pulse |
--------------------------------------------------------------------- |
|
-- acia_tx_clock_edge : process(Clk, TxRst, TxClk, TxClkDel ) |
acia_tx_clock_edge : process( TxRst, Clk ) |
begin |
if TxRst = '1' then |
TxClkDel <= '0'; |
TxClkEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
TxClkDel <= TxClk; |
TxClkEdge <= TxClkDel and (not TxClk); |
end if; |
end process; |
|
|
--------------------------------------------------------------------- |
-- Transmit Clock Divider |
-- Advance the count only on an input clock pulse |
--------------------------------------------------------------------- |
|
-- acia_tx_clock_divide : process( Clk, TxRst, TxClkEdge, TxClkCnt ) |
acia_tx_clock_divide : process( TxRst, Clk ) |
begin |
if TxRst = '1' then |
TxClkCnt <= "000000"; |
elsif Clk'event and Clk = '0' then |
if TxClkEdge = '1' then |
TxClkCnt <= TxClkCnt + "000001"; |
end if; -- TxClkEdge |
end if; -- reset / clk |
end process; |
|
--------------------------------------------------------------------- |
-- Transmit Baud Clock Selector |
--------------------------------------------------------------------- |
acia_tx_baud_clock_select : process( BdFmt, TxClk, TxClkCnt ) |
begin |
-- BdFmt |
-- 0 0 - Baud Clk divide by 1 |
-- 0 1 - Baud Clk divide by 16 |
-- 1 0 - Baud Clk divide by 64 |
-- 1 1 - reset |
case BdFmt is |
when "00" => -- Div by 1 |
TxBdClk <= TxClk; |
when "01" => -- Div by 16 |
TxBdClk <= TxClkCnt(3); |
when "10" => -- Div by 64 |
TxBdClk <= TxClkCnt(5); |
when others => -- reset |
TxBdClk <= '0'; |
end case; |
end process; |
|
--------------------------------------------------------------------- |
-- Transmit Baud Clock Edge Detector |
--------------------------------------------------------------------- |
-- |
-- Generate one clock pulse strobe on falling edge of Tx Baud Clock |
-- |
-- acia_tx_baud_clock_edge : process(Clk, TxRst, TxBdClk, TxBdDel ) |
acia_tx_baud_clock_edge : process( TxRst, Clk ) |
begin |
if TxRst = '1' then |
TxBdDel <= '0'; |
TxBdEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
TxBdDel <= TxBdClk; |
TxBdEdge <= (not TxBdClk) and TxBdDel; |
end if; |
end process; |
|
|
--------------------------------------------------------------------- |
-- Transmitter activation process |
--------------------------------------------------------------------- |
-- acia_tx_write : process(Clk, TxRst, TxWr, TxReq, TxAck ) |
acia_tx_write : process( TxRst, Clk ) |
begin |
if TxRst = '1' then |
TxReq <= '0'; |
TxEmp <= '1'; |
elsif Clk'event and Clk = '0' then |
if TxWr = '1' then |
-- Write requests transmit |
-- and clears the Empty Flag |
TxReq <= '1'; |
TxEmp <= '0'; |
else |
if (TxReq = '1') and (TxAck = '1') then |
-- Once the transmitter is started |
-- We can clear request. |
TxReq <= '0'; |
elsif (TxReq = '0') and (TxAck = '0') then |
-- When the transmitter is finished |
-- We can flag transmit empty |
TxEmp <= '1'; |
end if; |
end if; |
end if; -- clk / reset |
end process; |
|
----------------------------------------------------------------------------- |
-- Implements the Tx unit |
----------------------------------------------------------------------------- |
-- WdFmt - Bits[4..2] |
-- 0 0 0 - 7 data, even parity, 2 stop |
-- 0 0 1 - 7 data, odd parity, 2 stop |
-- 0 1 0 - 7 data, even parity, 1 stop |
-- 0 1 1 - 7 data, odd parity, 1 stop |
-- 1 0 0 - 8 data, no parity, 2 stop |
-- 1 0 1 - 8 data, no parity, 1 stop |
-- 1 1 0 - 8 data, even parity, 1 stop |
-- 1 1 1 - 8 data, odd parity, 1 stop |
-- acia_tx_transmit : process(TxRst, Clk, TxState, TxDin, WdFmt, |
-- TxShiftReg, TxBdEdge, TxParity, TxBitCount, |
-- TxReq, TxAck ) |
acia_tx_transmit : process( TxRst, Clk ) |
begin |
if TxRst = '1' then |
TxDat <= '1'; |
TxShiftReg <= "00000000"; |
TxParity <= '0'; |
TxBitCount <= "000"; |
TxAck <= '0'; |
TxState <= Tx1Stop_State; |
elsif Clk'event and Clk = '0' then |
if TxBdEdge = '1' then |
case TxState is |
when Tx1Stop_State => -- Last Stop bit state |
TxDat <= '1'; |
TxAck <= '0'; -- Transmitter halted |
if TxReq = '1' then |
TxState <= TxStart_State; |
end if; |
|
when TxStart_State => |
TxDat <= '0'; -- Start bit |
TxShiftReg <= TxDin; -- Load Shift reg with Tx Data |
TxParity <= '0'; |
if WdFmt(2) = '0' then |
TxBitCount <= "110"; -- 7 data + parity |
else |
TxBitCount <= "111"; -- 8 data |
end if; |
TxAck <= '1'; -- Flag transmit started |
TxState <= TxData_State; |
|
when TxData_State => |
TxDat <= TxShiftReg(0); |
TxShiftReg <= '1' & TxShiftReg(7 downto 1); |
TxParity <= TxParity xor TxShiftReg(0); |
TxBitCount <= TxBitCount - "001"; |
if TxBitCount = "000" then |
if (WdFmt(2) = '1') and (WdFmt(1) = '0') then |
if WdFmt(0) = '0' then -- 8 data bits |
TxState <= Tx2Stop_State; -- 2 stops |
else |
TxState <= Tx1Stop_State; -- 1 stop |
end if; |
else |
TxState <= TxParity_State; -- parity |
end if; |
end if; |
|
when TxParity_State => -- 7/8 data + parity bit |
if WdFmt(0) = '0' then |
TxDat <= not( TxParity ); -- even parity |
else |
TxDat <= TxParity; -- odd parity |
end if; |
if WdFmt(1) = '0' then |
TxState <= Tx2Stop_State; -- 2 stops |
else |
TxState <= Tx1Stop_State; -- 1 stop |
end if; |
|
when Tx2Stop_State => -- first of two stop bits |
TxDat <= '1'; |
TxState <= Tx1Stop_State; |
|
when others => -- Undefined |
TxDat <= '1'; |
TxState <= Tx1Stop_State; |
|
end case; -- TxState |
|
end if; -- TxBdEdge |
end if; -- clk / reset |
|
end process; |
|
end rtl; --=================== End of architecture ====================-- |