📄 cpu_core.txt
字号:
-- Behavioural model of a simple 8-bit CPU
-- download from: www.fpga.com.cn & www.pld.com.cn
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.bv_math.ALL;
USE work.cpu8pac.ALL;
ENTITY cpu IS
GENERIC(cycle_time : TIME := 200 ns); --must be divisible by 8
PORT(reset : IN std_logic;
memrd, memwr : OUT std_logic;
address : OUT std_logic_vector(11 DOWNTO 0);
data : INOUT std_logic_vector(7 DOWNTO 0));
END cpu;
ARCHITECTURE version1 OF cpu IS
--internal clock signal
SIGNAL clock : std_logic;
BEGIN
clock_gen : PROCESS
BEGIN
clock <= '1','0' AFTER cycle_time/2;
WAIT FOR cycle_time;
END PROCESS;
main_sequence : PROCESS
VARIABLE inst_reg : BIT_VECTOR(3 DOWNTO 0);
VARIABLE mar : BIT_VECTOR(11 DOWNTO 0);
VARIABLE acca, accb : BIT_VECTOR(7 DOWNTO 0);
VARIABLE pc : BIT_VECTOR(11 DOWNTO 0);
BEGIN
IF reset = '1' THEN
--initialisation
memrd <= '1';
memwr <= '1';
pc := (OTHERS => '0');
address <= (OTHERS => 'Z');
data <= (OTHERS => 'Z');
WAIT UNTIL rising_edge(clock);
ELSE
--fetch phase
address <= To_StdlogicVector(pc);
WAIT FOR cycle_time/4;
memrd <= '0';
WAIT FOR cycle_time/2;
memrd <= '1';
--read instruction
inst_reg := To_bitvector(data(7 DOWNTO 4));
--load page address
mar(11 DOWNTO 8) := To_bitvector(data(3 DOWNTO 0));
--increment program counter
pc := inc_bv(pc);
--wait until end of cycle
WAIT UNTIL rising_edge(clock);
--execute
CASE inst_reg IS
WHEN add =>
--add and sub use overloaded functions from bv_math package
acca := acca + accb;
WHEN subr =>
acca := acca - accb;
WHEN inc =>
acca := inc_bv(acca);
WHEN dec =>
acca := dec_bv(acca);
WHEN land =>
acca := acca AND accb;
WHEN lor =>
acca := acca OR accb;
WHEN cmp =>
acca := NOT acca;
WHEN lxor =>
acca := acca XOR accb;
WHEN lita =>
acca := acca;
WHEN litb =>
acca := accb;
WHEN clra =>
acca := (OTHERS => '0');
WHEN lda|ldb|sta|stb =>
address <= To_StdlogicVector(pc);
WAIT FOR cycle_time/4;
memrd <= '0';
WAIT FOR cycle_time/2;
memrd <= '1';
--read page offset address
mar(7 DOWNTO 0) := To_bitvector(data);
--increment program counter
pc := inc_bv(pc);
--wait until end of cycle
WAIT UNTIL rising_edge(clock);
--output address of operand
address <= To_StdlogicVector(mar);
IF ((inst_reg = lda) OR (inst_reg = ldb)) THEN
WAIT FOR cycle_time/4;
memrd <= '0';
WAIT FOR cycle_time/2;
memrd <= '1';
IF inst_reg = lda THEN
--load accumulator a from bus
acca := To_bitvector(data);
ELSE
--load accumulator b from bus
accb := To_bitvector(data);
END IF;
--wait until end of cycle
WAIT UNTIL rising_edge(clock);
ELSE
WAIT FOR cycle_time/8;
IF inst_reg = sta THEN
--ouput data
data <= To_StdlogicVector(acca);
ELSE
--ouput data
data <= To_StdlogicVector(accb);
END IF;
WAIT FOR cycle_time/8;
memwr <= '0';
WAIT FOR cycle_time/2;
memwr <= '1';
WAIT FOR cycle_time/8;
data <= (OTHERS => 'Z');
--wait until end of cycle
WAIT UNTIL rising_edge(clock);
END IF;
WHEN jmp =>
address <= To_StdlogicVector(pc);
--transfer page address to pc from mar
pc(11 DOWNTO 8) := mar(11 DOWNTO 8);
--read in offset address
WAIT FOR cycle_time/4;
memrd <= '0';
WAIT FOR cycle_time/2;
memrd <= '1';
pc(7 DOWNTO 0) := To_bitvector(data);
--wait until end of cycle
WAIT UNTIL rising_edge(clock);
END CASE;
END IF;
END PROCESS main_sequence;
END version1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -