📄 piccpu.vhd
字号:
--*** SYNTHETIC PIC V1.1 ***
--
-- SYNTHETIC PIC GENERAL PUBLIC LICENSE
-- Version 1, March 1996
--
-- Copyright (C) 1996. Thomas A. Coonan. All Rights Reserved.
-- 356 Dixie Court, Lawrenceville, GA 30245, USA
-- email: tcoonan@mindspring.com
--
-- Everyone is permitted to copy and distribute verbatim copies
-- of the Synthetic PIC package, but changing it is not allowed
-- for commercial purposes without the written consent of the author.
-- The Synthetic PIC may be used freely for all educational and
-- evaluation purposes.
--
-- BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-- FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-- OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-- PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-- OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-- TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-- PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-- REPAIR OR CORRECTION.
--
-- If you like the Synthetic PIC, please express your satisfaction with a
-- donation, especially if your purposes are commercial: send me and this
-- project what you feel the Synthetic PIC has been worth to you. Your
-- donations will help to support the development of more useful software
-- to be distributed on the same basis as this software. As a registered
-- user, you will receive future updates, fixes, and other additional
-- software and documention related to the project.
--
-- Thomas A. Coonan
--
-- Entity: PICCPU
-- VIEWLOGIC library, suitable for both simulation and synthesis.
--
library synth;
use synth.stdsynth.ALL;
entity PICCPU is
port (
-- Oscillator input. This will be divided into the 4 phases inside the model
Clk : in vlbit;
-- Reset
MRST : in vlbit;
-- *** partially implemented.. TRIS is not implemented. *YOU* must figure out
-- what kind of I/O configuration you want ahead of time. Stay tuned for
-- improvements on this. Better yet, tell me a good way to handle I/O!
--
-- Current I/O Configuration is:
-- PortA All Inputs
-- PortB All Output
-- PortC All Output
PortA : in vlbit_1d(7 downto 0);
PortB : out vlbit_1d(7 downto 0);
PortC : out vlbit_1d(7 downto 0));
end PICCPU;
-- To understand this model, I suggest the following key steps.
-- 1) Study the PIC Data sheet's INSTRUCTION SET SUMMARY and the
-- PIC Data Sheet's PIC16C5X SERIES BLOCK DIAGRAM.
-- 2) Considering the BLOCK DIAGRAM, consider one level deeper by
-- considering the ALU as having a MUX into its A and B inputs.
-- Also, consider what ALU operations would be considered per
-- PIC instruction. I discuss this more below..
--
-- I use a lot of Concurrent assignments, which I find easier to treat
-- in a data-driven manner, plus I hope synthesize more efficiently..
--
architecture first of PICCPU is
-- Instantiate subcomponents
--
-- This is the internal register bank.
--
component PICREGS
port (
Clk : in vlbit;
WriteEnable : in vlbit;
-- File Select
FSel : in vlbit_1d(4 downto 0);
-- Input busses
Din : in vlbit_1d(7 downto 0);
-- Output busses
Dout : out vlbit_1d(7 downto 0));
end component;
-- And this, is the ALU
--
component PICALU
port (
Op : in vlbit_1d(3 downto 0);
A : in vlbit_1d(7 downto 0);
B : in vlbit_1d(7 downto 0);
Q : out vlbit_1d(7 downto 0);
CIN : in vlbit;
COUT : out vlbit;
ZERO : out vlbit);
end component;
-- This is the Program ROM. The ROM must be encoded with the program to be run.
--
component PICROM
port (
Addr : in vlbit_1d(10 downto 0);
Data : out vlbit_1d(11 downto 0));
end component;
signal RomAddr : vlbit_1d(10 downto 0);
signal RomData : vlbit_1d(11 downto 0);
-- Clock Phases
signal Q1 : vlbit := '0';
signal Q2 : vlbit := '0';
signal Q3 : vlbit := '0';
signal Q4 : vlbit := '0';
-- This should be set to the ROM location where our restart vector is.
--
constant RESET_VECTOR : vlbit_1d(10 downto 0) := "11111111111";
-- Special internal registers
--
signal INST : vlbit_1d(11 downto 0) := "000000000000";
signal PC : vlbit_1d(10 downto 0) := "00000000000";
signal W : vlbit_1d(7 downto 0) := "00000000";
signal STATUS : vlbit_1d(7 downto 0) := "00000000";
signal STACKLEVEL : vlbit_1d(1 downto 0) := "00";
signal STACK1 : vlbit_1d(10 downto 0) := "00000000000";
signal STACK2 : vlbit_1d(10 downto 0) := "00000000000";
signal RTCC : vlbit_1d(7 downto 0);
signal FSR : vlbit_1d(7 downto 0);
-- Input signals leading into the W register
signal WIN : vlbit_1d(7 downto 0);
-- These will be driven by an incrementer and +2 incrementer attached
-- to the PC outputs
--
signal PCPLUS1 : vlbit_1d(11 downto 0);
-- Derive special sub signals from INST register
signal K : vlbit_1d(7 downto 0);
signal FSEL : vlbit_1d(4 downto 0);
signal LONGK : vlbit_1d(8 downto 0);
signal D : vlbit;
signal B : vlbit_1d(2 downto 0);
-- Signals for output ports, which are regsitered. For input ports, we'll
-- simply sample the ports directly.
-- signal PortARegister : vlbit_1d(7 downto 0); -- An input in this configuration
signal PortBRegister : vlbit_1d(7 downto 0);
signal PortCRegister : vlbit_1d(7 downto 0);
-- There will be a signal for every instruction/opcode. These signals
-- will be decoded from the INST register.
--
-- Byte-Oriented File Register Operations
signal OPCODE_NOP : vlbit;
signal OPCODE_MOVWF : vlbit;
signal OPCODE_CLRW : vlbit;
signal OPCODE_CLRF : vlbit;
signal OPCODE_SUBWF : vlbit;
signal OPCODE_DECF : vlbit;
signal OPCODE_IORWF : vlbit;
signal OPCODE_ANDWF : vlbit;
signal OPCODE_XORWF : vlbit;
signal OPCODE_ADDWF : vlbit;
signal OPCODE_MOVF : vlbit;
signal OPCODE_COMF : vlbit;
signal OPCODE_INCF : vlbit;
signal OPCODE_DECFSZ : vlbit;
signal OPCODE_RRF : vlbit;
signal OPCODE_RLF : vlbit;
signal OPCODE_SWAPF : vlbit;
signal OPCODE_INCFSZ : vlbit;
-- Bit-Oriented File Register Operations
signal OPCODE_BCF : vlbit;
signal OPCODE_BSF : vlbit;
signal OPCODE_BTFSC : vlbit;
signal OPCODE_BTFSS : vlbit;
-- Literal and Control Operations
signal OPCODE_OPTION : vlbit;
signal OPCODE_SLEEP : vlbit;
signal OPCODE_CLRWDT : vlbit;
signal OPCODE_TRIS : vlbit;
signal OPCODE_RETLW : vlbit;
signal OPCODE_CALL : vlbit;
signal OPCODE_GOTO : vlbit;
signal OPCODE_MOVLW : vlbit;
signal OPCODE_IORLW : vlbit;
signal OPCODE_ANDLW : vlbit;
signal OPCODE_XORLW : vlbit;
-- Signal true whenever a K operand is used. Conveniently, this
-- is any instruction with MSB set.
--
signal OPCODE_USE_K_OPERAND : vlbit;
-- ALU Signals
--
signal ALUOP : vlbit_1d(3 downto 0);
signal ALUA : vlbit_1d(7 downto 0);
signal ALUB : vlbit_1d(7 downto 0);
signal ALUOUT : vlbit_1d(7 downto 0);
signal ALUCIN : vlbit;
signal ALUCOUT : vlbit;
signal ALUZ : vlbit;
-- Write enable for the actual ZERO and CARRY bits within the status register
--
signal STATUS_Z_WRITE : vlbit;
signal STATUS_C_WRITE : vlbit;
-- Signals in and out of the register file
--
-- The two are directly connected to the register file.
signal REG_FIN : vlbit_1d(7 downto 0);
signal REG_FOUT : vlbit_1d(7 downto 0);
-- The two are input and output of any additional multiplexors
-- and are connected to the ALU, etc.
signal FIN : vlbit_1d(7 downto 0);
signal FOUT : vlbit_1d(7 downto 0);
signal FWE : vlbit;
constant ALUOP_ADD : vlbit_1d (3 downto 0) := "0000";
constant ALUOP_SUB : vlbit_1d (3 downto 0) := "0001";
constant ALUOP_AND : vlbit_1d (3 downto 0) := "0010";
constant ALUOP_OR : vlbit_1d (3 downto 0) := "0011";
constant ALUOP_XOR : vlbit_1d (3 downto 0) := "0100";
constant ALUOP_COM : vlbit_1d (3 downto 0) := "0101";
constant ALUOP_ROR : vlbit_1d (3 downto 0) := "0110";
constant ALUOP_ROL : vlbit_1d (3 downto 0) := "0111";
constant ALUOP_SWAP : vlbit_1d (3 downto 0) := "1000";
constant ALUOP_BITCLR : vlbit_1d (3 downto 0) := "1001";
constant ALUOP_BITSET : vlbit_1d (3 downto 0) := "1010";
constant ALUOP_BITTESTCLR : vlbit_1d (3 downto 0) := "1011";
constant ALUOP_BITTESTSET : vlbit_1d (3 downto 0) := "1100";
constant NOP : vlbit_1d (11 downto 0) := "000000000000";
constant MOVWF : vlbit_1d (6 downto 0) := "0000001";
constant CLRW : vlbit_1d (6 downto 0) := "0000010";
constant CLRF : vlbit_1d (6 downto 0) := "0000011";
constant SUBWF : vlbit_1d (5 downto 0) := "000010";
constant DECF : vlbit_1d (5 downto 0) := "000011";
constant IORWF : vlbit_1d (5 downto 0) := "000100";
constant ANDWF : vlbit_1d (5 downto 0) := "000101";
constant XORWF : vlbit_1d (5 downto 0) := "000110";
constant ADDWF : vlbit_1d (5 downto 0) := "000111";
constant MOVF : vlbit_1d (5 downto 0) := "001000";
constant COMF : vlbit_1d (5 downto 0) := "001001";
constant INCF : vlbit_1d (5 downto 0) := "001010";
constant DECFSZ : vlbit_1d (5 downto 0) := "001011";
constant RRF : vlbit_1d (5 downto 0) := "001100";
constant RLF : vlbit_1d (5 downto 0) := "001101";
constant SWAPF : vlbit_1d (5 downto 0) := "001110";
constant INCFSZ : vlbit_1d (5 downto 0) := "001111";
-- Bit-Oriented File Register Operations
constant BCF : vlbit_1d (3 downto 0) := "0100";
constant BSF : vlbit_1d (3 downto 0) := "0101";
constant BTFSC : vlbit_1d (3 downto 0) := "0110";
constant BTFSS : vlbit_1d (3 downto 0) := "0111";
-- Literal and Control Operations
constant OPTION : vlbit_1d (11 downto 0) := "000000000010";
constant SLEEP : vlbit_1d (11 downto 0) := "000000000011";
constant CLRWDT : vlbit_1d (11 downto 0) := "000000000100";
constant TRIS : vlbit_1d (11 downto 0) := "000000000111";
constant RETLW : vlbit_1d (3 downto 0) := "1000";
constant CALL : vlbit_1d (3 downto 0) := "1001";
constant GOTO : vlbit_1d (2 downto 0) := "101";
constant MOVLW : vlbit_1d (3 downto 0) := "1100";
constant IORLW : vlbit_1d (3 downto 0) := "1101";
constant ANDLW : vlbit_1d (3 downto 0) := "1110";
constant XORLW : vlbit_1d (3 downto 0) := "1111";
begin
-- Instantiate each of our subcomponents
--
REGS : PICREGS port map (Q1, FWE, FSEL, REG_FIN, REG_FOUT);
ALU : PICALU port map (ALUOP, ALUA, ALUB, ALUOUT, STATUS(0), ALUCOUT, ALUZ);
ROM : PICROM port map (RomAddr, RomData);
-- No additional mux input the register file.
REG_FIN <= FIN;
-- The FOUT is the output of the Register File plus any special register
-- signals. So, FOUT is the output of the MUX whose inputs are FOUT plus
-- any other special registers inputs.
--
FOUT <= FSR When (v1d2int(FSEL) = 0) Else
RTCC When (v1d2int(FSEL) = 1) Else
PC(7 downto 0) When (v1d2int(FSEL) = 2) Else
STATUS When (v1d2int(FSEL) = 3) Else
FSR When (v1d2int(FSEL) = 4) Else
PortA When (v1d2int(FSEL) = 5) Else -- Can always read Port
PortBRegister When (v1d2int(FSEL) = 6) Else -- Can always read Port
PortCRegister When (v1d2int(FSEL) = 7) Else -- Can always read Port
REG_FOUT;
-- I/O Ports
PortB <= PortBRegister;
PortC <= PortCRegister;
-- Drive the ROM Address bus straight from the PC
--
RomAddr <= PC;
-- PC Incrementor. This doesn't mean that the PC is always incremented, just
-- that we do generate the signal and make it available.
--
PCPLUS1 <= addum (PC(10 downto 0), "00000000001");
-- Define sub-signals out of INSTR
--
K <= INST(7 downto 0);
FSEL <= INST(4 downto 0);
LONGK <= INST(8 downto 0);
D <= INST(5);
B <= INST(7 downto 5);
OPCODE_USE_K_OPERAND <= INST(11);
-- Figure out the exact instruction. A single bit is decoded
-- from the INST
--
OPCODE_NOP <= '1' when INST(11 downto 0) = NOP else '0';
OPCODE_MOVWF <= '1' when INST(11 downto 5) = MOVWF else '0';
OPCODE_CLRW <= '1' when INST(11 downto 5) = CLRW else '0';
OPCODE_CLRF <= '1' when INST(11 downto 5) = CLRF else '0';
OPCODE_SUBWF <= '1' when INST(11 downto 6) = SUBWF else '0';
OPCODE_DECF <= '1' when INST(11 downto 6) = DECF else '0';
OPCODE_ANDWF <= '1' when INST(11 downto 6) = ANDWF else '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -