📄 top_lc2.vhd
字号:
-- TOP_LC2 module
--
-- Cyclone - LC2 Implementation
-- Uses VGA to Display Data
-- SW7 is clock for LC2 - several clocks needed for each instruction
-- SW8 is reset for LC2
--
-- This Module uses UP1core functions and they must be in the user library path
-- or current project directory
-- VHDL synthesis and simulation model of LC-2 machine
-- as described in Appendix C of Introduction to Computing Systems
-- by Yale Patt and Sanjay Patel
--
-- Registers contain register address on reset. Data memory
-- is initialized to 5555 AAaa for program on reset
-- Use lc2 module to simulate LC2 without video display hardware
--
--
-- UP1PACK - UP1core package
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_ARITH.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
LIBRARY lpm;
USE lpm.lpm_components.ALL;
PACKAGE up1core IS
COMPONENT dec_7seg
PORT( hex_digit: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
segment_a, segment_b, segment_c, segment_d,
segment_e, segment_f, segment_g : OUT STD_LOGIC);
END COMPONENT;
COMPONENT debounce
PORT(pb, clock_100Hz : IN STD_LOGIC;
pb_debounced : OUT STD_LOGIC);
END COMPONENT;
COMPONENT onepulse
PORT(pb_debounced, clock: IN STD_LOGIC;
pb_single_pulse : OUT STD_LOGIC);
END COMPONENT;
COMPONENT clk_div
PORT(clock_25Mhz : IN STD_LOGIC;
clock_1MHz : OUT STD_LOGIC;
clock_100KHz : OUT STD_LOGIC;
clock_10KHz : OUT STD_LOGIC;
clock_1KHz : OUT STD_LOGIC;
clock_100Hz : OUT STD_LOGIC;
clock_10Hz : OUT STD_LOGIC;
clock_1Hz : OUT STD_LOGIC);
END COMPONENT;
COMPONENT vga_sync
PORT(clock_25Mhz, red, green, blue : IN STD_LOGIC;
red_out, green_out, blue_out : OUT STD_LOGIC;
horiz_sync_out, vert_sync_out : OUT STD_LOGIC;
pixel_row, pixel_column : OUT STD_LOGIC_VECTOR(9 DOWNTO 0));
END COMPONENT;
COMPONENT char_rom
PORT( clock : IN STD_LOGIC;
character_address : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
font_row, font_col : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
rom_mux_output : OUT STD_LOGIC);
END COMPONENT;
COMPONENT keyboard
PORT( keyboard_clk, keyboard_data, clock_25Mhz ,
reset, read : IN STD_LOGIC;
scan_code : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
scan_ready : OUT STD_LOGIC);
END COMPONENT;
COMPONENT mouse
PORT( clock_25Mhz, reset : IN std_logic;
mouse_data : INOUT std_logic;
mouse_clk : INOUT std_logic;
left_button, right_button : OUT std_logic;
mouse_cursor_row, mouse_cursor_column : OUT std_logic_vector(9 DOWNTO 0));
END COMPONENT;
END up1core;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_ARITH.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
LIBRARY lpm;
USE lpm.lpm_components.ALL;
LIBRARY work;
USE work.up1core.all;
ENTITY top_lc2 IS
GENERIC(ADDR_WIDTH: integer := 12; DATA_WIDTH: integer := 1);
PORT( PB1, PB2, Clock_48Mhz, Switch : IN std_logic;
Red,Green,Blue : OUT std_logic;
Horiz_sync,Vert_sync : OUT std_logic);
END top_lc2;
ARCHITECTURE behavior OF top_lc2 IS
COMPONENT lc2
PORT( clock, reset : IN STD_LOGIC;
PC_out, IR_out : OUT STD_LOGIC_VECTOR( 15 DOWNTO 0 );
MAR_out : OUT STD_LOGIC_VECTOR(15 DOWNTO 0 );
MDR_out : OUT STD_LOGIC_VECTOR(15 DOWNTO 0 );
SR1_out : OUT STD_LOGIC_VECTOR(15 DOWNTO 0 );
SR2_out : OUT STD_LOGIC_VECTOR(15 DOWNTO 0 );
LC2_BUS_out : OUT STD_LOGIC_VECTOR(15 DOWNTO 0 );
BEN_out, WRITE_out : OUT STD_LOGIC;
CC_out : OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COMPONENT;
--Force LC2 clock signal on low skew global clock bus line
COMPONENT GLOBAL
PORT (a_in : IN STD_LOGIC;
a_out: OUT STD_LOGIC);
END COMPONENT;
SIGNAL Reset, LC2_clock, clock, Vert_sync_in, BEN_out, WRITE_out : STD_LOGIC;
SIGNAL PC, IR_out, MAR_out, MDR_out, SR1_out, SR2_out,
LC2_BUS_out : std_logic_vector(15 DOWNTO 0);
SIGNAL CC_out : std_logic_vector(2 DOWNTO 0);
-- Video Display Signals
SIGNAL Red_Data, Green_Data, Blue_Data, Power_On, Rev_video : std_logic;
-- Signals for Video ROM Memory for Pixel Data
SIGNAL char_address : std_logic_vector(5 DOWNTO 0);
SIGNAL sum_address : std_logic_vector(6 DOWNTO 0);
SIGNAL col_address, row_address : std_logic_vector(5 DOWNTO 0);
SIGNAL pixel_col, pixel_row : std_logic_vector(9 DOWNTO 0);
SIGNAL rom_mux_output : std_logic;
SIGNAL format_address : std_logic_vector(5 DOWNTO 0);
SIGNAL format_data : std_logic_vector(5 DOWNTO 0);
-- Signals for Push buttons
SIGNAL PB1_sync, PB2_sync : std_logic;
SIGNAL PB2_debounced, PB1_debounced, PB2_debounced_Sync,
PB1_debounced_Sync : std_logic;
SIGNAL PB1_single_pulse : std_logic;
SIGNAL switch_sync : std_logic;
BEGIN
-- Character Format ROM for Video Display
-- Displays constant format character data
-- on left side of Display area
format_rom: lpm_rom
GENERIC MAP ( lpm_widthad => 6,
lpm_numwords => 60,
lpm_outdata => "UNREGISTERED",
lpm_address_control => "REGISTERED",
-- Reads in mif file for data display format
lpm_file => "format.mif",
lpm_width => 6)
PORT MAP ( inclock => clock_48Mhz, address => format_address, q => format_data);
---------------------------------------------------------------------------------------
-- MIPS structural model - contains processor module interconnections
-- Code for each module is in *.VHD files
--
-- connect the LC2 to other components
LC2_1 : LC2
PORT MAP ( clock => LC2_clock,
reset => reset,
PC_out => PC,
IR_out => IR_out,
MAR_out => MAR_out,
MDR_out => MDR_out,
SR1_out => SR1_out,
SR2_out => SR2_out,
LC2_BUS_out => LC2_BUS_out,
BEN_out => BEN_out,
WRITE_out => WRITE_out,
CC_out => CC_out );
--Force LC2 clock signal on low skew global clock bus line
GBUF: GLOBAL
PORT MAP ( a_in => PB1_Single_Pulse,
a_out => LC2_clock);
-- Generate VGA sync signals for display
SYNC: vga_sync
PORT MAP(clock_25Mhz => clock,
red => red_data, green => green_data, blue => blue_data,
red_out => red, green_out => green, blue_out => blue,
horiz_sync_out => horiz_sync, vert_sync_out => vert_sync_in,
pixel_row => pixel_row, pixel_column => pixel_col);
-- Character Font ROM for Video Display
CGROM: char_rom
PORT MAP(clock => clock_48Mhz, character_address => char_address,
font_row => pixel_row(3 DOWNTO 1), font_col => pixel_col(3 DOWNTO 1),
rom_mux_output => rom_mux_output);
-- Debounce Button: Filters out mechanical bounce for around 64Ms.
-- Debounce clock uses Vert_Sync timing signal (16Ms) to save hardware
-- needed for a clock prescaler
DB1: debounce
PORT MAP(pb => pb1, clock_100Hz => vert_sync_in , pb_debounced => pb1_debounced);
-- Debounce reset pushbutton
DB2: debounce
PORT MAP(pb => pb2, clock_100Hz => vert_sync_in , pb_debounced => pb2_debounced);
-- Output Pushbutton Pulse for 1 25Mhz clock cycle
SP1: onepulse
PORT MAP(pb_debounced => pb1_debounced_sync, clock => clock,
pb_single_pulse => pb1_single_pulse);
------------------------------------------------------------------------------
-- Reset signal for LC2 processor
Reset <= PB2_Debounced_Sync;
Vert_sync <= vert_sync_in;
-- Colors for pixel data on video signal
-- address video_rom for pixel color data
-- Switch 2 xor Rev_Video will reverse video
Red_Data <= not ((rom_mux_output xor Switch_Sync) xor Rev_video);
Green_Data <= not ((rom_mux_output xor Switch_Sync) xor Rev_video);
Blue_Data <= '1';
-- current character row and column being displayed
row_address(5 DOWNTO 0) <= pixel_row(9 DOWNTO 4);
col_address(5 DOWNTO 0) <= pixel_col(9 DOWNTO 4);
-- Address for Constant Character Data Format ROM
format_address(1 DOWNTO 0) <= Col_address(1 DOWNTO 0);
format_address(5 DOWNTO 2) <= Row_address(4 DOWNTO 1);
-- This Process makes a 24Mhz clock using the 48Mhz USB clock
Divide_Clock: PROCESS
BEGIN
WAIT UNTIL (clock_48Mhz'event) AND (clock_48Mhz='1');
clock <= not clock;
END PROCESS Divide_Clock;
-- This Process Provides Character Data for Video Display
-- by generating addresses for the Character Generator ROM
-- using the character row address and col address provided by the Video
-- Sync process - 40 characters by 30 lines of display area
VIDEO_DISPLAY_DATA: PROCESS
BEGIN
WAIT UNTIL (clock'event) AND (clock='1');
-- Reverse Video for Title at top of screen
IF (row_address <= "00011") THEN rev_video <= '1';
ELSE rev_video <= '0';
END IF;
-- Blank characters on edge of screen and on alternating lines
IF (row_address(0)='0') OR
(col_address < "001000") OR (col_address >"010101")
THEN char_address <= "100000";
ELSE
-- Constant Character Area - use data from format ROM
IF ((col_address >= "001000") AND (col_address <= "001011")) THEN
char_address <= format_data;
ELSE
-- Couple of Spaces
IF (col_address = "001100") OR (col_address = "001101")
-- Blanks on Top and Bottom line of Display Area
OR (row_address < "00010") OR (row_address > "11011")
THEN char_address <= "100000";
ELSE
-- Numeric Data From Simulation
-- Display Values in Hex
CASE row_address(4 DOWNTO 1) IS
WHEN "0001" =>
CASE col_address IS
-- Print "Computer" on first line of data display area
WHEN "001110" =>
char_address <= "000011";
WHEN "001111" =>
char_address <= "001111" ;
WHEN "010000" =>
char_address <= "001101" ;
WHEN "010001" =>
char_address <= "010000" ;
WHEN "010010" =>
char_address <= "010101" ;
WHEN "010011" =>
char_address <= "010100" ;
WHEN "010100" =>
char_address <= "000101" ;
WHEN "010101" =>
char_address <= "010010" ;
WHEN OTHERS =>
char_address <= char_address;
END CASE;
WHEN "0010" =>
CASE col_address IS
WHEN "010100" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "11" & PC(7 DOWNTO 4);
WHEN "010101" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "11" & PC(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "110000";
END CASE;
WHEN "0011" =>
-- Selects Hex Character Address with 4-bit value from signal
CASE col_address IS
WHEN "001110" =>
char_address <= "11" & IR_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & IR_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & IR_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & IR_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "0100" =>
-- Selects Hex Character Address with 4-bit value from signal
CASE col_address IS
WHEN "001110" =>
char_address <= "11" & MAR_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & MAR_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & MAR_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & MAR_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "0101" =>
CASE col_address IS
-- Selects Hex Character Address with 4-bit value from signal
WHEN "001110" =>
char_address <= "11" & MDR_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & MDR_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & MDR_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & MDR_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "0110" =>
CASE col_address IS
WHEN "001110" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "11" & LC2_BUS_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & LC2_BUS_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & LC2_BUS_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & LC2_BUS_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "0111" =>
CASE col_address IS
WHEN "001110" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "110" & CC_out(2 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "1000" =>
CASE col_address IS
WHEN "001110" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "11" & SR1_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & SR1_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & SR1_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & SR1_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "1001" =>
CASE col_address IS
WHEN "001110" =>
-- Selects Hex Character Address with 4-bit value from signal
char_address <= "11" & SR2_out(15 DOWNTO 12);
WHEN "001111" =>
char_address <= "11" & SR2_out(11 DOWNTO 8);
WHEN "010000" =>
char_address <= "11" & SR2_out(7 DOWNTO 4);
WHEN "010001" =>
char_address <= "11" & SR2_out(3 DOWNTO 0);
WHEN OTHERS =>
char_address <= "100000";
END CASE;
WHEN "1010" =>
IF col_address = "001110"
-- Select "0" OR "1" character address
THEN char_address <= "11000" & WRITE_out;
ELSE
char_address <= "100000";
END IF;
WHEN "1011" =>
IF col_address = "001110"
-- Select "0" OR "1" character address
THEN char_address <= "11000" & BEN_out;
ELSE
char_address <= "100000";
END IF;
WHEN "1100" =>
IF col_address = "001110"
-- Select Up arrow or Down arrow character address
THEN char_address <= "0111" & LC2_Clock & "0";
ELSE
char_address <= "100000";
END IF;
WHEN "1101" =>
IF col_address = "001110"
-- Select Up arrow or Down arrow character address
THEN char_address <= "0111" & Reset & "0";
ELSE
char_address <= "100000";
END IF;
WHEN OTHERS =>
char_address <= "100000";
END CASE;
END IF;
END IF;
END IF;
END PROCESS VIDEO_DISPLAY_DATA;
-- Sync extenal pushbutton inputs to chip clock
PUSH_BUTTON_SYNC: PROCESS
BEGIN
WAIT UNTIL (clock'event) AND (clock='1');
PB1_Sync <= PB1;
PB2_Sync <= PB2;
Switch_Sync <= Switch;
PB1_DEBOUNCED_SYNC <= PB1_DEBOUNCED;
PB2_DEBOUNCED_SYNC <= PB2_DEBOUNCED;
END PROCESS PUSH_BUTTON_SYNC;
END behavior;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -