Skocz do zawartości

PIC18F4550 w fpga 1


kroszkanorber

Pomocna odpowiedź

Witam.

Próbuję  napisać implementację kodu mikrokontrolera 8 bit PIC18f4550. Nie chcę przepisywać wszystkich kodów. Mam zamiar napisać uproszczoną wersję kompatybilną z tym kontrolerem. 

Dlaczego to robię?

Z kontrolerami pic 8 bit zacząłem swoją przygodę programowania i uważam, że są relatywnie proste w zrozumieniu.

Posiadam program MPASMWIN który generuje gotowe kody maszynowe do zaimplementowania w tym kontrolerze.

Zdjęcieaplikacji:image.png.3f394d18e82ad53b58be11c2e3ed2e8d.png

Otwarta aplikacja:

image.thumb.png.695ba0332309a032b15c83daafed8690.png

Prosty program napisany w asemblerze w edytorze tekstu:

image.thumb.png.ffe5fa24b9ee6c9d626f8e82e3e725bb.png

Kompilacja programu w MPASMWIN:

image.thumb.png.4e2674ca3fe9263ea536a2afa753034e.png

Program po kompilacji generuje plik HEX:

image.thumb.png.b631bb93580200500739eeebb78dd67d.png

W przykładowym kodzie tym poleceniem przepisujemy zawartość rejestru W(work) do rejestru F(file). w tym poleceniu zmienna ' a ' = 0: RAM location in Access RAM (BSR register is ignored) lub  'a' = 1: RAM bank is specified by BSR register.

MOVWF        f, a        Move WREG to f    b'0110 111a ffff ffff'  czyli ( h'6E' - a = '0') lub ( h'6F' - a = '1') ,a drugi bajt jest rejestrem f. 

 Rejestr F zadeklarowany jest pod adresem h'21'  przykład:  D      EQU     H'0021'

Wygenerowany kod jest w postaci dwubajtowej, czyli w naszym przypadku powinien wyglądać : MOVWF D , 1 (MOVWF "rejestr f", "zmienna a") = '6F21',

ale tak nie jest i z nieznanych mi przyczyn kod generowany jest nieintuicyjnie  i na początku mamy podany rejestr f a w drugiej kolejności polecenie czli '216F'.

Wszystkie polecenia mają postać dwubajtową i wyglądają w plikach HEX analogicznie jak w przykłądzie po wyżej.

Musimy usunąć z wygenerowanego pliku HEX początek i koniec plików nie bedących programem  by wyodrębnić program dla naszego kontrolera. 

Początek i koniec programu jest zawsze tej samiej długości... (Prawdopodobnie są to pliki konfiguracyjne. nie sprawdzałem..)

:020000040000FA
:02000000(216F)6E
:00000001FF

W nawiasie znajduje się nasz właściwy plik czyli program przetłumaczony z assembler do kodu maszynowego. Plik ten zaczyna się zawsze w tym samym miejscu, dlatego można go łatwo wyodrębnić.

Posiadając gotowe narzędzie do generowania kodów maszynowych zostaje implemetacja mikrokontrolera z poleceniami zgodnymi z wygenerowanymi kodami.

Zaczynam od licznika programu z rejestrem stosu:

Licznik programu jest licznikiem binarnym 19 bit z ładowaniem danych zsynchronizowanym z taktem Clk i asynchronicznym zerowaniem Reset. Stos programu zaimplementowany jest w pamięci wewnętrznej RAM i jest rejetrem o 32 poziomach.

Wyjście licznika ADDR zamierzam podłączyć do zewnętrznej pamięci programu (SRAM 512k X 16 bit).

Wejście danych z pamięci programu to szyna 'A' 12 bit  .

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    17:51:06 12/09/2023 
-- Design Name: 
-- Module Name:    program_counter - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
-- instrukcje mikrokontrolera PIC18F4550
--
--	k 		Literal field, constant data or label (may be either an 8-bit, 12-bit or a 20-bit value).
--
--	n 		The relative address (2's complement number) for relative branch instructions or the direct address for 
--			Call/Branch and Return instructions
--
--	s 		Fast Call/Return mode select bit
--	s 		= 0: do not update into/from shadow registers
--	s 		= 1: certain registers loaded into/from shadow registers (Fast mode)
-- ten bit zostanie pominięty ze względu na pełny dostęp do adresu stack.
-- i ustawiony na stałe '0'.
--
--	16	RETURN	s			Return from Subroutine				0000 0000 0001 001s	None
--
--	72	CALL		n, s		Call Subroutine 1st word			1110 110s kkkk kkkk	None
--								 2nd word								1111 kkkk kkkk kkkk	
--	73	GOTO		n			Go to Address 1st word				1110 1111 kkkk kkkk	None
--								 2nd word								1111 kkkk kkkk kkkk
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity program_counter is
    Port ( Clk : in  STD_LOGIC ;
           Reset : in  STD_LOGIC ;
           ADDR : out  STD_LOGIC_VECTOR (19 downto 0) ;
           A : in  STD_LOGIC_VECTOR (11 downto 0) ;
           GOTO : in  STD_LOGIC ;
           CALL : in  STD_LOGIC ;
           RET : in  STD_LOGIC
			  );
end program_counter;

architecture Behavioral of program_counter is
	
	type PC_STACK_TYPE is array (31 downto 0) of std_logic_vector (19 downto 0);
	signal PC_STACK: PC_STACK_TYPE;
	
	signal STACK_ADDR : std_logic_vector (4 downto 0) ;
	signal REG_PC : std_logic_vector (19 downto 0) ;
	signal SkipEn : std_logic ;
	signal RetEn : std_logic ;

	signal PC_ADDR: std_logic_vector (19 downto 0) := "00000000000000000000";
	signal ADDR_PC: std_logic_vector (19 downto 0) ;
	signal SEL: std_logic_vector (1 downto 0) ;
	signal EN_PC: std_logic;

begin

-----------------------------------------------------------------------------
    process (Clk, Reset, CALL, RET, PC_ADDR)				--pc_stack
    begin
		if Reset = '0' then
			STACK_ADDR <= (others => '0') ;
		else
        if Clk'event and Clk = '0' then
			 if (CALL = '1') then
				 PC_STACK(conv_integer(STACK_ADDR)) <= (PC_ADDR + 2) ;
				 STACK_ADDR <= STACK_ADDR +  1 ;
			 elsif (RET = '1') then
				 ADDR_PC <= PC_STACK(conv_integer(STACK_ADDR)) ;
				 STACK_ADDR <= STACK_ADDR - 1 ;
			 end if;
        end if;
		end if;
    end process;
-----------------------------------------------------------------------------
	process(Reset, Clk, GOTO, CALL, RET, A(7 downto 0))	--skip_dekoder
	begin
		if Reset = '0' then
			SkipEn <= '0';
			RetEn <= '0';
		else
			if Clk'event and CLk = '0' then
				if ((SkipEn = '1') or (RetEn = '1')) then
					SkipEn <= '0';
					RetEn <= '0';
				elsif ((GOTO = '1') or (CALL = '1')) then
					REG_PC(7 downto 0) <= A(7 downto 0);
					SkipEn <= '1';
				elsif RET = '1' then
					RetEn <= '1';
				end if;
			end if;
		end if;
	end process;
	
	REG_PC(19 downto 8) <= A(11 downto 0);
	EN_PC <= GOTO or CALL  or SEL(1);
------------------------------------------------------------------------------
	process(Clk, Reset)												--program prescaller
	begin
		if Reset = '0' then
			SEL <= "01";
		else
			if Clk'event and Clk = '0' then
				SEL(0) <= not SEL(0) ;
				SEL(1) <= not SEL(1) ;
			end if;
		end if;
	end process;
			
	process(Clk, Reset, ADDR_PC, SkipEN, RetEN, EN_PC)		--program counter
	begin
		if Reset = '0' then
			PC_ADDR <= (others => '0');
		else
			if Clk'event and Clk = '0' then	
				if SkipEn = '1' then
					PC_ADDR <= REG_PC;
				elsif RetEn = '1' then
					PC_ADDR <= ADDR_PC;
				elsif EN_PC = '1' then
					PC_ADDR <= PC_ADDR + 1;
				end if;
			end if;
		end if;
	end process;
	
	ADDR <= PC_ADDR;
------------------------------------------------------------------------------

end Behavioral;

W następnych postach bedę wstawiać kolejne kody (jeszcze nie napisałem🙂).

Pozdrawiam.

 

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Cześć,

ciekawy problem. Nie znam listy rozkazów dla PIC18f4550 czy wszystkie rozkazy mają taką samą długość? (przypuszczam, że nie bo pewnie jest tryb adresowania 'immediate' - gdzie mozna podać stałą w rozkazie assemblera. Przede wszystkim nalezy ustalić jakie są dopuszczalne tryby adresowania, oraz jak wyglądają opcodes (czy mają stałą długość - to ułatwia dekodowanie rozkazów). Przewaznie dekoder rozkazów pisze się jako FSM (gdzie jeden stan to obsługa jednego rozkazu). Fajnie to wszystko jest opisane w tym kursie z udemy (skończyłem go jakiś czas temu):

https://www.udemy.com/course/fpga-embedded-design-cpu/

Podaj jakieś linki do listy rozkazów tego MCU i jakie z jego rozkazów chcesz zaimplementować? Z chęcią włączę się do takiego projketu (np. w Verilogu), bo już od jakiegoś czasu myślę o implementacji prostego sofcore-cpu 🙂 Na początek bez pipelining'u i innych zaawansowanych usprawnień.

Jeśli masz jakieś wyniki wklej je do postu - z chęcią się z nimi zapoznam.

BTW: sama obsługa flag typu: zero, carry, overflow jest trochę 'tricky' - są one potrzebne do rozkazów skoków warunkowych i instrukcji warunkowych (np. warunkowy move jeśli CPU taki obsługuje).

Bootloader - też jest pewnym problemem, dlatgo na początek pamięć programu może być w BRAM lub zwykłej tablicy Verilog/VHDL ...

Trzeba też zdecydować czy architektura to "Von Neumann" czy "Harward" - ale podejrzewam, że dla tego MCU PIC18f4550 architektura jest harwardzka (osobne magistrale rozkazów i danych).

Znalzłem link do ISA tego MCU - wklejam do postu:

http://technology.niagarac.on.ca/staff/mboldin/18F_Instruction_Set/

https://ww1.microchip.com/downloads/en/DeviceDoc/31029a.pdf

Pozdrawiam

Edytowano przez FlyingDutch
  • Lubię! 1
Link do komentarza
Share on other sites

@FlyingDutch

Hej.

Narazie wstrzymałem się z rozwijaniem projektu. Próbuję zaimplementować programator na i2c. Ten pic ma 16 bit instrukcje. A instrukcje skoku mają 32 bity co umożliwia skoki do adresu o szerokości 21 bit. W instrukcjach są adresy ram z użyciem banków adresu. Instrukcje charakteryzują się powtarzalnością kodów powiązanych ze sobą, co może uprościć strukturę wewnętrzną dekodera rozkazów. 

Instrukcje PIC18F4550I-PT (1).pdf są w nocie katalogowej szczegółowo opisane . 

Brotlader można uprościć do automatycznego ładowania danych z zewnętrznej pamięci do bram przy użyciu maszyny stanów i zewnętrznego przycisku lub naprzyklad przyciskiem F1 na klawiaturze PS2. ( Na potrzeby testów)

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

@FlyingDutch witam

Przepisałem kody kontrolera. Przepisałem kolejność kodów by je usystematyzować według wielkości od liczby binarnej najmniejszej w kodzie do maksymalnej.

Polecenia  mają zaimplementowaną w kodzie zmienną "a" i "d" w bitach nr.8 i nr.9. Ma to znaczenie przy dekodowaniu rozkazów z użyciem pamięci RAM i aktywacji banków tej pamięci. Zrobione jest to w ten sposób by uzyskać maksymalnie szybki dostęp do pamięci z pominięciem inicjowania (wyższego adresu banku co nie mieści się w 16 bitowym kodzie). Gdy zmienna a = 1 adres pamięci RAM adresowany jest uwzględniając BSR(Bank Select Register) i gdy a = 0, BSR = "0000". BSR to adres RAM bit 8,9,10,11. Reszta adresów RAM (7 downto 0) podajemy w kodzie. Zmienna d informuje nas gdzie zapisujemy wynik operacji. Gdy d = 0 wynik operacji zapisany zostanie w rejestrze work (rejestr operacyjny, "akumulator"),w przeciwnym przypadku, gdy d = 1 we wskazanym w kodzie rejestrze RAM lub innym.

Nad kontrolerem PIC nasz FPGA ma przewagę w szybkości przetwarzania i możliwości manipulacji bitami co sprawia, że teoretycznie można uzyskać kontroler o wydajności ok 20ns na 1 instrukcję w spartan3. Mamy też możliwość stworzenia własnej architektury dostosowanej do własnych potrzeb. Brzmi kusząco.

 Najwięcej pracy sprawia napisanie dekodera poleceń.  Reszta nie jest problemem ponieważ jest aktywowana tym dekoderem i nie wpływa na timing. Implementacja dekodera w moim zamyśle powinna się opierać o FSM i dekoder select.

-----------------------------------------------------------------------------------------

--    a         = 0: RAM location in Access RAM (BSR register is ignored)
--    a         = 1: RAM bank is specified by BSR register

--    d         = 0: store result in WREG
--    d         = 1: store result in file register f

--    f         8-bit register file address (00h to FFh) or 2-bit FSR designator (0h to 3h).

--    n         The relative address (2's complement number) for relative branch instructions or the direct address for 
--            Call/Branch and Return instructions

--    k         Literal field, constant data or label (may be either an 8-bit, 12-bit or a 20-bit value).

--    fs     12-bit register file address (000h to FFFh). This is the source address. 

--    fd     12-bit register file address (000h to FFFh). This is the destination address. 

--    bbb     Bit address within an 8-bit file register (0 to 7).

--    s         Fast Call/Return mode select bit
--    s         = 0: do not update into/from shadow registers
--    s         = 1: certain registers loaded into/from shadow registers (Fast mode)

-----------------------------------------------------------------------------------------

-----------------------------------------------------------------------------
--dekoder poleceń

-----------------------------------------------------------------------------
--    1    NOP            -            No Operation                                   0000 0000 0000 0000    None
--    2    SLEEP        -            Go into Standby mode                    0000 0000 0000 0011     TO, PD
--    3    CLRWDT    -            Clear Watchdog Timer                    0000 0000 0000 0100    TO, PD
--    4    PUSH         -            Push Top of Return Stack (TOS)    0000 0000 0000 0101      None
--    5    POP            -            Pop Top of Return Stack (TOS)     0000 0000 0000 0110       None
--    6    DAW           -            Decimal Adjust WREG                     0000 0000 0000 0111       C

-----------------------------------------------------------------------------
--    7    TBLRD*                  Table Read                                         0000 0000 0000 1000    None
--    8    TBLRD*+               Table Read with Post-Increment      0000 0000 0000 1001     None
--    9    TBLRD*-                Table Read with Post-Decrement    0000 0000 0000 1010     None
--    10    TBLRD+*             Table Read with Pre-Increment        0000 0000 0000 1011      None
--    11    TBLWT*                Table Write                                        0000 0000 0000 1100      None
--    12    TBLWT*+             Table Write with Post-Increment     0000 0000 0000 1101      None
--    13    TBLWT*-             Table Write with Post-Decrement    0000 0000 0000 1110      None
--    14    TBLWT+*             Table Write with Pre-Increment       0000 0000 0000 1111      None

-----------------------------------------------------------------------------
--    15    RETFIE    s            Return from Interrupt Enable          0000 0000 0001 000s       GIE/GIEH,PEIE/GIEL
--    16    RETURN    s         Return from Subroutine                    0000 0000 0001 001s       None

-----------------------------------------------------------------------------
--    17    MOVLB        k            Move Literal to BSR<3:0>            0000 0001 0000 kkkk      None
--    18    MULWF        f, a        Multiply WREG with f                    0000 001a ffff ffff            None
--    19    DECF        f, d, a       Decrement f                                   0000 01da ffff ffff            C, DC, Z, OV, N

-----------------------------------------------------------------------------
--    20    SUBLW        k            Subtract WREG from Literal            0000 1000 kkkk kkkk    C, DC, Z, OV, N
--    21    IORLW          k            Inclusive OR Literal with WREG      0000 1001 kkkk kkkk     Z, N
--    22    XORLW        k            Exclusive OR Literal with WREG      0000 1010 kkkk kkkk     Z, N
--    23    ANDLW        k            AND Literal with WREG                   0000 1011 kkkk kkkk     Z, N
--    24    RETLW         k            Return with Literal in WREG           0000 1100 kkkk kkkk     None
--    25    MULLW        k            Multiply Literal with WREG             0000 1101 kkkk kkkk     None
--    26    MOVLW        k            Move Literal to WREG                    0000 1110 kkkk kkkk     None
--    27    ADDLW        k            Add Literal and WREG                     0000 1111 kkkk kkkk     C, DC, Z, OV, N
    
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
--    28    IORWF        f, d, a    Inclusive OR WREG with f                0001 00da ffff ffff          Z, N
--    29    ANDWF      f, d, a    AND WREG with f                             0001 01da ffff ffff           Z, N
--    30    XORWF      f, d, a    Exclusive OR WREG with f               0001 10da ffff ffff           Z, N
--    31    COMF         f, d, a    Complement f                                   0001 11da ffff ffff           Z, N
-----------------------------------------------------------------------------
--    32    ADDWFC    f, d, a    Add WREG and Carry bit to f           0010 00da ffff ffff         C, DC, Z, OV, N
--    33    ADDWF      f, d, a    Add WREG and f                               0010 01da ffff ffff          C, DC, Z, OV, N
--    34    INCF           f, d, a    Increment f                                       0010 10da ffff ffff           C, DC, Z, OV, N
--    35    DECFSZ     f, d, a    Decrement f, Skip if 0                       0010 11da ffff ffff           None

-----------------------------------------------------------------------------
--    36    RRCF        f, d, a    Rotate Right f through Carry            0011 00da ffff ffff          C, Z, N
--    37    RLCF        f, d, a    Rotate Left f through Carry               0011 01da ffff ffff          C, Z, N
--    38    SWAPF    f, d, a    Swap Nibbles in f                                0011 10da ffff ffff         None
--    39    INCFSZ    f, d, a    Increment f, Skip if 0                          0011 11da ffff ffff          None

-----------------------------------------------------------------------------
--    40    RRNCF        f, d, a    Rotate Right f (No Carry)              0100 00da ffff ffff         Z, N
--    41    RLNCF        f, d, a    Rotate Left f (No Carry)                 0100 01da ffff ffff          Z, NN
--    42    INFSNZ      f, d, a    Increment f, Skip if Not 0               0100 10da ffff ffff          NoneN
--    43    DCFSNZ    f, d, a    Decrement f, Skip if Not 0              0100 11da ffff ffff          None

-----------------------------------------------------------------------------
--    44    MOVF        f, d, a    Move f                                             0101 00da ffff ffff         Z, N
--    45    SUBFWB    f, d, a    Subtract f from WREG with           0101 01da ffff ffff         C, DC, Z, OV, N
--                             Borrow                                                             
--    46    SUBWFB    f, d, a    Subtract WREG from f with            0101 10da ffff ffff         C, DC, Z, OV, N
--    47    SUBWF       f, d, a    Subtract WREG from f                    0101 11da ffff ffff         C, DC, Z, OV, N

-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
--    48    CPFSLT    f, a        Compare f with WREG, Skip <        0110 000a ffff ffff         None
--    49    CPFSEQ   f, a        Compare f with WREG, Skip =        0110 001a ffff ffff          None
--    50    CPFSGT   f, a        Compare f with WREG, Skip >        0110 010a ffff ffff          None
--    51    TSTFSZ    f, a        Test f, Skip if 0                                 0110 011a ffff ffff           None

--    52    SETF        f, a        Set f                                                  0110 100a ffff ffff           None
--    53    CLRF        f, a        Clear f                                              0110 101a ffff ffff            Z
--    54    NEGF       f, a        Negate f                                           0110 110a ffff ffff            C, DC, Z, OV, N
--    55    MOVWF   f, a        Move WREG to f                              0110 111a ffff ffff             None

-----------------------------------------------------------------------------
--    56    BTG        f, d, a    Bit Toggle f                            0111 bbba ffff ffff    None

-----------------------------------------------------------------------------
--    57    BSF        f, b, a    Bit Set f                                1000 bbba ffff ffff    None
--    58    BCF        f, b, a    Bit Clear f                                1001 bbba ffff ffff    None
--    59    BTFSS        f, b, a    Bit Test f, Skip if Set                1010 bbba ffff ffff    None
--    60    BTFSC        f, b, a    Bit Test f, Skip if Clear            1011 bbba ffff ffff    None

--    61    MOVFF        fs, fd    Move fs (source) to 1st word        1100 ffff ffff ffff    None
--                                fd (destination) 2nd word            1111 ffff ffff ffff
    
--    62    BRA        n            Branch Unconditionally                 1101 0nnn nnnn nnnn    None
--    63    RCALL        n            Relative Call                            1101 1nnn nnnn nnnn    None

-----------------------------------------------------------------------------
--    64    BZ            n            Branch if Zero                            1110 0000 nnnn nnnn    None
--    65    BNZ        n            Branch if Not Zero                    1110 0001 nnnn nnnn    None
--    66    BC            n            Branch if Carry                        1110 0010 nnnn nnnn    None
--    67    BNC        n            Branch if Not Carry                    1110 0011 nnnn nnnn    None
--    68    BOV        n            Branch if Overflow                    1110 0100 nnnn nnnn    None
--    69    BNOV        n            Branch if Not Overflow                1110 0101 nnnn nnnn    None
--    70    BN            n            Branch if Negative                    1110 0110 nnnn nnnn    None
--    71    BNN        n            Branch if Not Negative                1110 0111 nnnn nnnn    None

--    72    CALL        n, s        Call Subroutine 1st word            1110 110s kkkk kkkk    None
--                                 2nd word                                1111 kkkk kkkk kkkk    
--    73    GOTO        n            Go to Address 1st word                1110 1111 kkkk kkkk    None
--                                 2nd word                                1111 kkkk kkkk kkkk

---------------------------------------------------------------------------------------

Bity d i a na które zwróciłem uwagę podłączył bym na stałe do odpowiednio adresów i kierunku danych wynikowych.

Na przykład w ten sposób ( PROGRAM_DATA(8) = zmienna 'a' )

    RAM_ADDR(11)     <= PROGRAM_DATA(8) and BSR(3) ;
    RAM_ADDR(10)     <= PROGRAM_DATA(8) and BSR(2) ;
    RAM_ADDR(9)      <= PROGRAM_DATA(8) and BSR(1) ;
    RAM_ADDR(8)      <= PROGRAM_DATA(8) and BSR(0) ;
    
    RAM_ADDR(7)     <= PROGRAM_DATA(7) ;
    RAM_ADDR(6)     <= PROGRAM_DATA(6) ;
    RAM_ADDR(5)     <= PROGRAM_DATA(5) ;
    RAM_ADDR(4)     <= PROGRAM_DATA(4) ;
    RAM_ADDR(3)     <= PROGRAM_DATA(3) ;
    RAM_ADDR(2)     <= PROGRAM_DATA(2) ;
    RAM_ADDR(1)     <= PROGRAM_DATA(1) ;
    RAM_ADDR(0)     <= PROGRAM_DATA(0) ;

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Witam

Postanowiłem implementację kontrolera opisać w blokach. Każdy dekoder rozkazu opisać  w oddzielnym module. 

Polecenie GOTO:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity GOTO is
    Port ( Clk : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
           EN_GOTO : inout  STD_LOGIC;
           DI_ROM : in  STD_LOGIC_VECTOR (15 downto 0);
           PC_ADDR : out  STD_LOGIC_VECTOR (19 downto 0));
end GOTO;

architecture Behavioral of GOTO is

	signal ADDR : std_logic_vector (19 downto 0);		--rejestr pomocniczy zapisu pc (licznik programu)
	signal GOTO_EN : std_logic;							--sygnał pomocniczy zapisu pc (licznik programu)

begin

--dekoder rozkazu GOTO. Rozkaz wykonany jest w 3 taktach. 2 takty pobranie rozkazu, 3 takt wykonanie rozkazu.

	process(Clk, Reset, DI_ROM)
	begin
		if Reset = '0' then
			ADDR <= (others => '0');
			EN_GOTO <= '0';
			GOTO_EN <= '0';
		else
			if Clk'event and Clk = '0' then
				if DI_ROM(15 downto 8) = "11101111" then			--dekoder rozkazu GOTO
					ADDR( 7 downto 0) <= DI_ROM(7 downto 0);		--wpis danych do rejestru
					GOTO_EN <= '1';									--sygnał oczekiwania na następne dane
			elsif DI_ROM(15 downto 12) = "1111" then				--dekoder rozkazu GOTO dla drugiej połowy informacji
					if GOTO_EN = '1' then							--sygnał zezwalający na wykonanie kolejnego rozkazu
						ADDR(19 downto 8) <= DI_ROM(11 downto 0);	--wpis kolejnych danych do rejestru
						EN_GOTO <= '1';								--sygnał zezwolenia na wykonanie rozkazu zapisu danych do pc
					end if;
			elsif EN_GOTO = '1' then								--zakończenie sekwencji zapisu (po negatywnym zboczu zegara)
					EN_GOTO <= '0';									--koniec zapisu
					GOTO_EN <= '0';									--koniec odbioru następnych danych
				end if;
			end if;
		end if;
	end process;
	
	PC_ADDR <= ADDR when EN_GOTO = '1' else (others => 'Z');		--adres podany na szynę danych dla licnika programu


end Behavioral;

 

  • Lubię! 1
Link do komentarza
Share on other sites

Następny rozkaz dotyczy przerwania programowego i powrotu do programu w którym nastąpiło wywołanie podprogramu. Koniec podprogramu kończy się poleceniem RETURN a wywołanie poleceniem CALL:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CALL_RETURN is
    Port ( Clk : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
           EN_CALL : inout  STD_LOGIC;
           EN_RETURN : inout  STD_LOGIC;
           DI_ROM : in  STD_LOGIC_VECTOR (15 downto 0);
           ROM_ADDR : in  STD_LOGIC_VECTOR (19 downto 0);
           PC_ADDR : out  STD_LOGIC_VECTOR (19 downto 0));
end CALL_RETURN;

architecture Behavioral of CALL_RETURN is

	signal ADDR : std_logic_vector (19 downto 0);
	signal CALL_EN : std_logic;
	---------------------------------------------------------------------------------------------------------
   signal STACK_ADDR   : std_logic_vector(4 downto 0);
   signal DO  : std_logic_vector(19 downto 0);
			 
    type ram_type is array (0 to 31) of std_logic_vector (19 downto 0);
    signal STACK : ram_type;

begin

--dekoder rozkazu CALL. Rozkaz wykonany jest w 3 taktach. 2 takty pobranie rozkazu, 3 takt wykonanie rozkazu.
--dekoder rozkazu RETURN. Rozkaz wykonany jest w 2 taktach. 1 takt pobranie rozkazu, 2 takt wykonanie rozkazu.

	process(Clk, Reset, DI_ROM)
	begin
		if Reset = '0' then
			ADDR <= (others => '0');
			STACK_ADDR <= (others => '0');
			EN_CALL <= '0';
			CALL_EN <= '0';
		else
			if Clk'event and Clk = '0' then
				if DI_ROM(15 downto 8) = "11101100" then	--dekoder rozkazu CALL
					ADDR( 7 downto 0) <= DI_ROM(7 downto 0);--wpis danych do rejestru
					CALL_EN <= '1';							--sygnał oczekiwania na następne dane
			elsif DI_ROM(15 downto 12) = "1111" then	    --dekoder rozkazu CALL dla drugiej połowy informacji
					if CALL_EN = '1' then					--sygnał zezwalający na wykonanie kolejnego rozkazu
						ADDR(19 downto 8) <= DI_ROM(11 downto 0);	--wpis kolejnych danych do rejestru
						STACK(conv_integer(STACK_ADDR)) <= (ROM_ADDR + 1);--zapis stanu licznika programu (kolejny adres programu)
						EN_CALL <= '1';				--sygnał zezwolenia na wykonanie rozkazu zapisu danych do pc
					end if;
			elsif EN_CALL = '1' then				--zakończenie sekwencji zapisu (po negatywnym zboczu zegara)
					STACK_ADDR <= (STACK_ADDR + 1);	--zwiekszenie stanu licznika przerwań
					EN_CALL <= '0';					--koniec zapisu
					CALL_EN <= '0';					--koniec odbioru następnych danych
			elsif DI_ROM = "0000000000010010" then	--dekoder rozkazu RETURN
					EN_RETURN <= '1';
			elsif EN_RETURN = '1' then				--zakończenie sekwencji zapisu (po negatywnym zboczu zegara)
					STACK_ADDR <= (STACK_ADDR - 1);	--zmniejszanie stanu licznika przerwań
					EN_RETURN <= '0';
				end if;
			end if;
		end if;
	end process;
	
	DO <= STACK(conv_integer(STACK_ADDR));
	PC_ADDR <= ADDR when EN_CALL = '1' else (others => 'Z');
	PC_ADDR <= DO when EN_RETURN = '1' else (others => 'Z');
	

end Behavioral;

 

  • Lubię! 1
Link do komentarza
Share on other sites

Witam

Operacje na bitach w kontrolerze PIC (BCF, BSF)

Moduł w którym przeprowadza się operacje bitowe. Tym razem postanowiłem narysować schemat. Moduł posiada wejście danych A0 do A7, sygnał wejściowy SET_CLEAR którym ustawiamy bity (odpowiednio dla SET_CLEAR = 1 wybrany bit zostanie ustawiony jako logiczne 1 i odwrotnie), sygnał A B C to wybór bitu który zostanie nadpisany wartością podaną na wejście SET_CLEAR ( Demultiplekser 3 do 8 ), wejście EN jest zezwoleniem dla nadpisywania wybranego bitu ( wejście EN aktywne w stanie wysokim = 1 ). W przypadku gdy sygnał EN = 0 dane podane na wejście danych A0 do A7 zostaną przesłane bez zmian do wyjść Y0 do Y7, w przeciwnym wypadku wybrany bit będzie zmieniony zgodnie z podanym sygnałem na wejście SET_CLEAR i wejście wyboru 1 z 8 bitów A B C, a pozostałe bity zostaną przesłane bez zmian. W ten sposób zmieniamy w bajcie tylko 1 bit bez wpływu na resztę danych.

Schemat:

image.thumb.png.48aaf0bb6750f63b7b23aad15aae3325.png

wynik symulacji:

image.thumb.png.c4875bac67c4dace019a4e71b608128c.png

Pozdrawiam

  • Lubię! 2
Link do komentarza
Share on other sites

@FlyingDutch hej.

Dzięki. Ciągle się waham jak dekodować instrukcje. Mam wrażenie że instrukcje są rozbudowane o dodatkowe, a kody jakby były wepchnięte tam gdzie było jeszcze wolne miejsce. Ciężko ogarnąć to w logiczną całość. Następna instrukcja na liście to odejmowanie. Myślę, że w tym kontrolerze fizycznie taka instrukcja nie istnieje, a zamiast niej liczba odejmowana jest przekształcana w kodzie U2 i dodawana, wnioskuje po wyniku działań i wyniku przeniesienia.

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Witam.

Schemat ALU 8 bit. Funkcje : AND, OR, XOR, ADD, SUB. Detektor wyniku zerowego dodawania lub odejmowania Z. Przepełnienie C. Komparator A=B A>B A<B. Wzorowałem się na logice w układach TTL. Wynik na szynie Y. Wejścia danych szyna A i B. Wejście S dwubitowe służy do wyboru funkcji. AND = 00, XOR = 01, OR = 10, ADD/SUB = 11. Operacja odejmowania uzyskana jest przez zanegowanie danych na szynie B i dodanie A + 1  ( czyli w kodzie U2). Odejmowanie przełącza sygnał ADD_SUB = 1. Dodawanie przełącza sygnał ADD_SUB = 0.

Schemat załączony poniżej:

image.thumb.png.5e74f77b6c96c60614e9983d61f47b47.png

Symulacja:

image.thumb.png.bb45406eb07535c903506e10fcb042c7.png

Pozdrawiam

Edytowano przez kroszkanorber
  • Lubię! 2
Link do komentarza
Share on other sites

(edytowany)

Witam.

W przykładowym kodzie VHDL opisałem prostą jednostkę ALU.  Zrealizowane są funkcje dodawania i odejmowania i wejściem przeniesienia (Ci), AND, OR, XOR. Wyniki operacji odczytać można na wyjściu Y, C, DC, Z, N, OV. Użyłem przeniesienia równoległego (carry lookahead) stosowanego w układach arytmetycznych w celu przyspieszenia propagacji. Jeżeli nie chcemy dodawać bitu przeniesienia z poprzedniej operacji, wejście Ci ustawiamy na '0'. Dane wyjściowe nie są zapamiętywane, w związku z tym sygnał zegarowy nie został użyty. Wybór 1 z 4 instrukcji jest realizowany przy pomocy wejścia 2 bitowego "S", a sumator sterowany jest wejściem ADD_SUB.

Przykładowy kod VHDL

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity PIC18FAdder is
    Port ( S : in  STD_LOGIC_VECTOR (1 downto 0);	--Wejście wyboru funkcji
           A : in  STD_LOGIC_VECTOR (7 downto 0);	--Wejście A
           B : in  STD_LOGIC_VECTOR (7 downto 0); 	--Wejście B
			  Ci : in  STD_LOGIC;					--Wejście Carry in
			  ADD_SUB : in  STD_LOGIC;				--Operacja dodawanie('0'), odejmowanie('1')
			  C : out  STD_LOGIC;					--Carry dla 8 bitów
			  DC : out  STD_LOGIC;					--Carry dla 4 bitów
			  Z : out  STD_LOGIC;					--Dekoder wyniku zerowego
			  OV : out  STD_LOGIC;					--Przepełnienie dla liczb ze znakiem
			  N : out  STD_LOGIC;					--Liczb ujemna
           Y : out  STD_LOGIC_VECTOR (7 downto 0) 	-- Wyjście ALU
			  );
end PIC18FAdder;

architecture Behavioral of PIC18FAdder is

	signal P : std_logic_vector (7 downto 0);			--Propaguj (OR)
	signal G : std_logic_vector (7 downto 0);			--Generuj  (AND)
	signal X : std_logic_vector (7 downto 0);			--XOR
	signal ASxorB : std_logic_vector (7 downto 0);		--Negacja wejścia B
	signal Q : std_logic_vector (7 downto 0);			--Dane z sumatora
	signal D : std_logic_vector (7 downto 0);			--Dane wyjściowe jednostki ALU
	signal Cin : std_logic;								--Wejście Carry
	signal Cn : std_logic_vector (7 downto 0);			--Wyjścia przeniesień

begin


	Cin <= ADD_SUB xor Ci;
	ASxorB(0) <= B(0) xor ADD_SUB;
	ASxorB(1) <= B(1) xor ADD_SUB;
	ASxorB(2) <= B(2) xor ADD_SUB;
	ASxorB(3) <= B(3) xor ADD_SUB;
	ASxorB(4) <= B(4) xor ADD_SUB;
	ASxorB(5) <= B(5) xor ADD_SUB;
	ASxorB(6) <= B(6) xor ADD_SUB;
	ASxorB(7) <= B(7) xor ADD_SUB;
	P(0) <= A(0) or ASxorB(0);
	P(1) <= A(1) or ASxorB(1);
	P(2) <= A(2) or ASxorB(2);
	P(3) <= A(3) or ASxorB(3);
	P(4) <= A(4) or ASxorB(4);
	P(5) <= A(5) or ASxorB(5);
	P(6) <= A(6) or ASxorB(6);
	P(7) <= A(7) xor AxorB(7);
	X(0) <= A(0) xor AxorB(0);
	X(1) <= A(1) xor AxorB(1);
	X(2) <= A(2) xor AxorB(2);
	X(3) <= A(3) xor AxorB(3);
	X(4) <= A(4) xor AxorB(4);
	X(5) <= A(5) xor AxorB(5);
	X(6) <= A(6) xor AxorB(6);
	X(7) <= A(7) xor AxorB(7);
	G(0) <= A(0) and AxorB(0);
	G(1) <= A(1) and AxorB(1);
	G(2) <= A(2) and AxorB(2);
	G(3) <= A(3) and AxorB(3);
	G(4) <= A(4) and AxorB(4);
	G(5) <= A(5) and AxorB(5);
	G(6) <= A(6) and AxorB(6);
	G(7) <= A(7) and AxorB(7);
	
	-- Carry lookahead (przeniesienie równoległe dla operacji dodawania, odejmowania)
	Q(0) <= Cin xor P(0);
	Cn(0)  <= G(0) or (Cin and P(0));
	Q(1) <= Cn(0) xor P(1);
	Cn(1)  <= G(1) or (Cin and P(0) and P(1)) or (G(0) and P(1));
	Q(2) <= Cn(1) xor P(2);
	Cn(2)  <= G(2) or (Cin and P(0) and P(1) and P(2)) or (G(0) and P(1) and P(2)) or (G(1) and P(2));
	Q(3) <= Cn(2) xor P(3);
	Cn(3)  <= G(3) or (Cin and P(0) and P(1) and P(2) and P(3)) or (G(0) and P(1) and P(2) and P(3)) or (G(1) and P(2) and P(3)) or (G(2) and P(3));
	Q(4) <= Cn(3) xor P(4);
	Cn(4) <= G(4) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4)) or (G(0) and P(1) and P(2) and P(3) and P(4)) or (G(1) and P(2) and P(3) and P(4)) or (G(2) and P(3) and P(4)) or (G(3) and P(4));
	Q(5) <= Cn(4) xor P(5);
	Cn(5)  <= G(5) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5)) or (G(1) and P(2) and P(3) and P(4) and P(5)) or (G(2) and P(3) and P(4) and P(5)) or (G(3) and P(4) and P(5)) or (G(4) and P(5));
	Q(6) <= Cn(5) xor P(6);
	Cn(6)  <= G(6) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(2) and P(3) and P(4) and P(5) and P(6)) or (G(3) and P(4) and P(5) and P(6)) or (G(4) and P(5) and P(6)) or (G(5) and P(6));
	Q(7) <= Cn(6) xor P(7);
	Cn(7)  <= G(7) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(3) and P(4) and P(5) and P(6) and P(7)) or (G(4) and P(5) and P(6) and P(7)) or (G(5) and P(6) and P(7)) or (G(6) and P(7));

	DC <= Cn(3);
	C <= Cn(7);
	N <= D(7);
	Z <= not (D(7) or D(6) or D(5) or D(4) or D(3) or D(2) or D(1) or D(0));
	OV <= Cn(7) xor Cn(6);
	
	with S select				--Wybór
		D <= Q when "00",		--Wyjście sumatora
			  P when "01",		--OR
			  G when "10",		--AND
			  X when others;	--XOR
			  
	Y <= D;


end Behavioral;

 

Edytowano przez kroszkanorber
  • Lubię! 1
Link do komentarza
Share on other sites

Witam.

Pierwszy przykładowy kod mikrokontrolera 8 bit PIC18f4550. Ok 50 kodów. Kontroler obsługuje wszystkie operacje arytmetyczno-logiczne . Kontroler nie jest opisany w maszynie stanów ponieważ przy próbie zaimplementowania zajmował zbyt dużo zasobów. Nie znam powodów takiej sytuacji i w związku z tym postanowiłem opisać kody w modułach.

Wszystkie polecenia ALU obsługiwane są w jednym cyklu trwającym dwa takty. W pierwszym takcie są dekodowane instrukcje i pobierane dane, w drugim zapisywane wyniki do rejestrów. Skoki wykonywane są w dwóch cyklach(4 takty) ze względu na 16 bit OPCODE i 19 bit ROMADDR, rutyna skoków przetwarzana jest w dwóch słowach. Powroty z przerwań wykonywane są w jednym cyklu. Przerwanie "INTERRUPT" pobierane jest ze źródła zewnętrznego i ustawia licznik programu = X"00008". Powrót z przerwania wykonujemy poleceniem RETFIE i do tego polecenia kolejne przerwanie "INTERRUPT" nie będzie wykonane. Kontroler posiada wyjście danych 8 bitów i zapisywane jest  jak pamięć RAM pod adresem X"F80". 

Pozdrawiam.

Kody źródłowe:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PIC18F is
    Port ( Clk : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
           INTERUPT : in  STD_LOGIC;
           PORTA : out  STD_LOGIC_VECTOR (7 downto 0);
           ROM_ADDR : inout  STD_LOGIC_VECTOR (19 downto 0);
           ROM_DATA : in  STD_LOGIC_VECTOR (15 downto 0)
			  );
end PIC18F;

architecture Behavioral of PIC18F is
	
	signal Clk1 : STD_LOGIC;
	signal TSTF : STD_LOGIC_vector (7 downto 0);
	signal WREG : STD_LOGIC_vector (7 downto 0);
	signal W_WE_EN : STD_LOGIC;
	signal WREG_WE : STD_LOGIC;
	signal PORTA_WE : STD_LOGIC;
	signal BSR : STD_LOGIC_vector (3 downto 0);
	signal MOVLB : STD_LOGIC;
	signal F_WE_d_EN : STD_LOGIC;
	signal F_WE_EN : STD_LOGIC;
	signal SKIP2_AeB : STD_LOGIC;
	signal SKIP2_AgB : STD_LOGIC;
	signal SKIP2_AlB : STD_LOGIC;
	signal SKIP2_Z : STD_LOGIC;
	signal SKIP2_NZ : STD_LOGIC;
	signal LIT : STD_LOGIC_vector (7 downto 0);
	signal ALU_A : STD_LOGIC_vector (7 downto 0);
	signal ALU_B : STD_LOGIC_vector (7 downto 0);
	signal ALU_Y : STD_LOGIC_vector (7 downto 0);
	signal ALU_C : STD_LOGIC;
	signal ALU_Z : STD_LOGIC;
	signal ALU_N : STD_LOGIC;
	signal ALU_NZ : STD_LOGIC;
	
	COMPONENT INSTRUKTION_SET
	PORT(
		ROM_DATA : IN std_logic_vector(7 downto 0);          
		ADDWF : OUT std_logic;
		ADDWFC : OUT std_logic;
		ANDWF : OUT std_logic;
		CLRF : OUT std_logic;
		COMF : OUT std_logic;
		CPFSEQ : OUT std_logic;
		CPFSGT : OUT std_logic;
		CPFSLT : OUT std_logic;
		DECF : OUT std_logic;
		DECFSZ : OUT std_logic;
		DCFSNZ : OUT std_logic;
		INCF : OUT std_logic;
		INCFSZ : OUT std_logic;
		INFSNZ : OUT std_logic;
		IORWF : OUT std_logic;
		MOVF : OUT std_logic;
		MOVWF : OUT std_logic;
		MULWF : OUT std_logic;
		NEGF : OUT std_logic;
		RLCF : OUT std_logic;
		RLNCF : OUT std_logic;
		RRCF : OUT std_logic;
		RRNCF : OUT std_logic;
		SETF : OUT std_logic;
		SUBFWB : OUT std_logic;
		SUBWF : OUT std_logic;
		SUBWFB : OUT std_logic;
		SWAPF : OUT std_logic;
		TSTFSZ : OUT std_logic;
		XORWF : OUT std_logic;
		BCF : OUT std_logic;
		BSF : OUT std_logic;
		BTFSC : OUT std_logic;
		BTFSS : OUT std_logic;
		BTG : OUT std_logic;
		CALL : OUT std_logic;
		GOTO : OUT std_logic;
		RETLW : OUT std_logic;
		ADDLW : OUT std_logic;
		ANDLW : OUT std_logic;
		IORLW : OUT std_logic;
		MOVLW : OUT std_logic;
		MULLW : OUT std_logic;
		SUBLW : OUT std_logic;
		XORLW : OUT std_logic;
		NdWord : OUT std_logic
		);
	END COMPONENT;
	
		signal ADDWF : std_logic;
		signal ADDWFC : std_logic;
		signal ANDWF : std_logic;
		signal CLRF : std_logic;
		signal COMF : std_logic;
		signal CPFSEQ : std_logic;
		signal CPFSGT : std_logic;
		signal CPFSLT : std_logic;
		signal DECF : std_logic;
		signal DECFSZ : std_logic;
		signal DCFSNZ : std_logic;
		signal INCF : std_logic;
		signal INCFSZ : std_logic;
		signal INFSNZ : std_logic;
		signal IORWF : std_logic;
		signal MOVF : std_logic;
		signal MOVWF : std_logic;
		signal MULWF : std_logic;
		signal NEGF : std_logic;
		signal RLCF : std_logic;
		signal RLNCF : std_logic;
		signal RRCF : std_logic;
		signal RRNCF : std_logic;
		signal SETF : std_logic;
		signal SUBFWB : std_logic;
		signal SUBWF : std_logic;
		signal SUBWFB : std_logic;
		signal SWAPF : std_logic;
		signal TSTFSZ : std_logic;
		signal XORWF : std_logic;
		signal BCF : std_logic;
		signal BSF : std_logic;
		signal BTFSC : std_logic;
		signal BTFSS : std_logic;
		signal BTG : std_logic;
		signal CALL : std_logic;
		signal GOTO : std_logic;
		signal RETLW : std_logic;
		signal ADDLW : std_logic;
		signal ANDLW : std_logic;
		signal IORLW : std_logic;
		signal MOVLW : std_logic;
		signal MULLW : std_logic;
		signal SUBLW : std_logic;
		signal XORLW : std_logic;
		signal NdWord : std_logic;

	COMPONENT ADDER
	PORT(
		ADD_A : IN std_logic_vector(7 downto 0);
		ADD_B : IN std_logic_vector(7 downto 0);
		ADD_Ci : IN std_logic;
		ADDLW : IN std_logic;
		ADDWF : IN std_logic;
		ADDWFC : IN std_logic;
		SUBWFB : IN std_logic;
		SUBFWB : IN std_logic;
		SUBWF : IN std_logic;
		SUBLW : IN std_logic;
		DECF : IN std_logic;
		DECFSZ : IN std_logic;
		DCFSNZ : IN std_logic;
		INCF : IN std_logic;
		INCFSZ : IN std_logic;
		INFSNZ : IN std_logic;
		NEGF : IN std_logic;          
		ADD_C : OUT std_logic;
		ADD_DC : OUT std_logic;
		ADD_OV : OUT std_logic;
		ADD_Y : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;
	
signal ADD_Y : std_logic_vector(7 downto 0);
signal ADD_Ci : std_logic;
signal ADD_C : std_logic;
signal ADD_DC : std_logic;
signal ADD_OV : std_logic;

	COMPONENT LOGIC
	PORT(
		LOG_A : IN std_logic_vector(7 downto 0);
		LOG_B : IN std_logic_vector(7 downto 0);
		BSel : IN std_logic_vector(2 downto 0);
		LOG_Ci : IN std_logic;
		ANDWF : IN std_logic;
		ANDLW : IN std_logic;
		IORWF : IN std_logic;
		IORLW : IN std_logic;
		XORWF : IN std_logic;
		XORLW : IN std_logic;
		SWAPF : IN std_logic;
		RLNCF : IN std_logic;
		RLCF : IN std_logic;
		RRNCF : IN std_logic;
		RRCF : IN std_logic;
		SETF : IN std_logic;
		BSF : IN std_logic;
		BCF : IN std_logic;
		BTG : IN std_logic;
		BTFSS : IN std_logic;
		BTFSC : IN std_logic;
		COMF : IN std_logic;          
		LOG_Co : OUT std_logic;
		LOG_Y : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;
	
signal LOG_Y : std_logic_vector(7 downto 0);
signal BSel : std_logic_vector(2 downto 0);
signal LOG_Ci : std_logic;
signal LOG_C : std_logic;

	COMPONENT PC
	PORT(
		Clk : IN std_logic;
		Clk1 : IN std_logic;
		Reset : IN std_logic;
		CALL : IN std_logic;
		GOTO : IN std_logic;
		RETLW : IN std_logic;
		NdWord : IN std_logic;
		INTERUPT : IN std_logic;
		SKIP2 : IN std_logic;
		ROM_DATA : IN std_logic_vector(15 downto 0);       
		ROM_ADDR : INOUT std_logic_vector(19 downto 0)
		);
	END COMPONENT;
	
signal SKIP2 : std_logic;

	COMPONENT RAM
	PORT(
		Clk : IN std_logic;
		RAM_WE : IN std_logic;
		RAM_EN : IN std_logic;
		RAM_ADDR : IN std_logic_vector(11 downto 0);
		RAM_DI : IN std_logic_vector(7 downto 0);          
		RAM_DATA : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;

signal RAM_ADDR : STD_LOGIC_vector (11 downto 0);
signal RAM_DI : STD_LOGIC_vector (7 downto 0);
signal RAM_DATA : STD_LOGIC_vector (7 downto 0);
signal RAM_EN : STD_LOGIC;
signal RAM_WE : STD_LOGIC;

	COMPONENT STATUS
	PORT(
		Clk : IN std_logic;
		Reset : IN std_logic;
		ADD_C : IN std_logic;
		ADD_DC : IN std_logic;
		ADD_OV : IN std_logic;
		ALU_Z : IN std_logic;
		ALU_N : IN std_logic;
		ADDWF : IN std_logic;
		ADDWFC : IN std_logic;
		DECF : IN std_logic;
		INCF : IN std_logic;
		NEGF : IN std_logic;
		SUBWF : IN std_logic;
		SUBWFB : IN std_logic;
		ADDLW : IN std_logic;
		SUBLW : IN std_logic;
		ANDWF : IN std_logic;
		COMF : IN std_logic;
		IORWF : IN std_logic;
		MOVF : IN std_logic;
		RLNCF : IN std_logic;
		RLCF : IN std_logic;
		RRCF : IN std_logic;
		RRNCF : IN std_logic;
		SETF : IN std_logic;
		XORWF : IN std_logic;
		ANDLW : IN std_logic;
		IORLW : IN std_logic;
		XORLW : IN std_logic;
		STATUS_EN : IN std_logic;          
		STATUS : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;
	
signal STATUS1 : STD_LOGIC_vector (7 downto 0);
signal STATUS_EN : STD_LOGIC;

	COMPONENT MUL
	PORT(
		Clk : IN std_logic;
		Reset : IN std_logic;
		MULWF : IN std_logic;
		MULLW : IN std_logic;
		RAM_DATA : IN std_logic_vector(7 downto 0);
		WREG : IN std_logic_vector(7 downto 0);
		LIT : IN std_logic_vector(7 downto 0);
		PRODH_EN : IN std_logic;
		PRODL_EN : IN std_logic;          
		PRODH : OUT std_logic_vector(7 downto 0);
		PRODL : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;
	
signal PRODH : STD_LOGIC_vector (7 downto 0);
signal PRODL : STD_LOGIC_vector (7 downto 0);
signal PRODH_EN : STD_LOGIC;
signal PRODL_EN : STD_LOGIC;


begin
-------------------------------------------------------------------------------------------------------------------
	Inst_INSTRUKTION_SET: INSTRUKTION_SET PORT MAP(
		ADDWF => ADDWF,
		ADDWFC => ADDWFC,
		ANDWF => ANDWF,
		CLRF => CLRF,
		COMF => COMF,
		CPFSEQ => CPFSEQ,
		CPFSGT => CPFSGT,
		CPFSLT => CPFSLT,
		DECF => DECF,
		DECFSZ => DECFSZ,
		DCFSNZ => DCFSNZ,
		INCF => INCF,
		INCFSZ => INCFSZ,
		INFSNZ => INFSNZ,
		IORWF => IORWF,
		MOVF => MOVF,
		MOVWF => MOVWF,
		MULWF => MULWF,
		NEGF => NEGF,
		RLCF => RLCF,
		RLNCF => RLNCF,
		RRCF => RRCF,
		RRNCF => RRNCF,
		SETF => SETF,
		SUBFWB => SUBFWB ,
		SUBWF => SUBWF,
		SUBWFB => SUBWFB,
		SWAPF => SWAPF,
		TSTFSZ =>TSTFSZ,
		XORWF => XORWF,
		BCF => BCF,
		BSF => BSF,
		BTFSC => BTFSC,
		BTFSS => BTFSS,
		BTG => BTG,
		CALL => CALL,
		GOTO => GOTO,
		RETLW => RETLW,
		ADDLW => ADDLW,
		ANDLW => ANDLW,
		IORLW => IORLW,
		MOVLW => MOVLW,
		MULLW => MULLW,
		SUBLW => SUBLW,
		XORLW => XORLW,
		NdWord => NdWord,
		ROM_DATA => ROM_DATA(15 downto 8)
	);
-------------------------------------------------------------------------------------------------------------------
	Inst_ADDER: ADDER PORT MAP(
		ADD_A => ALU_A,
		ADD_B => ALU_B,
		ADD_Ci => ADD_Ci,
		ADD_C => ADD_C,
		ADD_DC => ADD_DC,
		ADD_OV => ADD_OV,
		ADD_Y => ADD_Y,
		ADDLW => ADDLW,
		ADDWF => ADDWF,
		ADDWFC => ADDWFC,
		SUBWFB => SUBWFB,
		SUBFWB => SUBFWB,
		SUBWF => SUBWF,
		SUBLW => SUBLW,
		DECF => DECF,
		DECFSZ => DECFSZ,
		DCFSNZ => DCFSNZ,
		INCF => INCF,
		INCFSZ => INCFSZ,
		INFSNZ => INFSNZ,
		NEGF => NEGF
	);
	ADD_Ci <= STATUS1(0);
-------------------------------------------------------------------------------------------------------------------
	Inst_LOGIC: LOGIC PORT MAP(
		LOG_A => ALU_A,
		LOG_B => ALU_B,
		BSel => BSel,
		LOG_Ci => LOG_Ci,
		ANDWF => ANDWF,
		ANDLW => ANDLW,
		IORWF => IORWF,
		IORLW => IORLW,
		XORWF => XORWF,
		XORLW => XORLW,
		SWAPF => SWAPF,
		RLNCF => RLNCF,
		RLCF => RLCF,
		RRNCF => RRNCF,
		RRCF => RRCF,
		SETF => SETF,
		BSF => BSF,
		BCF => BCF,
		BTG => BTG,
		BTFSS => BTFSS,
		BTFSC => BTFSC,
		COMF => COMF,
		LOG_Co => LOG_C,
		LOG_Y => LOG_Y
	);
	BSel <= ROM_DATA(11 downto 9);
	LOG_Ci <= STATUS1(0);
-------------------------------------------------------------------------------------------------------------------
	Inst_PC: PC PORT MAP(
		Clk => Clk,
		Clk1 => Clk1,
		Reset => Reset,
		CALL => CALL,
		GOTO => GOTO,
		RETLW => RETLW,
		NdWord => NdWord,
		INTERUPT => INTERUPT,
		SKIP2 => SKIP2,
		ROM_ADDR => ROM_ADDR,
		ROM_DATA => ROM_DATA
	);
-------------------------------------------------------------------------------------------------------------------
	Inst_RAM: RAM PORT MAP(
		Clk => Clk,
		RAM_WE => RAM_WE,
		RAM_EN => RAM_EN,
		RAM_ADDR => RAM_ADDR,
		RAM_DI => RAM_DI,
		RAM_DATA => RAM_DATA
	);
	
	F_WE_d_EN <= ADDWF or ADDWFC or ANDWF or COMF or DECF or DECFSZ or DCFSNZ or INCF or INCFSZ or INFSNZ or IORWF or MOVF or RLCF or RLNCF or RRCF or RRNCF or SUBFWB or SUBWF or SUBWFB or SWAPF or XORWF;
	F_WE_EN <= CLRF or MOVWF or MULWF or NEGF or SETF or BCF or BSF or BTG;
	
	RAM_WE <= ((F_WE_d_EN and ROM_DATA(9)) or F_WE_EN) and Clk1 ;
	
	RAM_EN <= (ROM_DATA(15) or ROM_DATA(14) or ROM_DATA(13) or ROM_DATA(12)) and (not (STATUS_EN or PRODH_EN or PRODL_EN or CLk1))  ;
	
	RAM_DI <= ALU_Y ;
	RAM_ADDR(11) <= (ROM_DATA(8) and BSR(3)) ;
	RAM_ADDR(10) <= (ROM_DATA(8) and BSR(2)) ;
	RAM_ADDR(9)  <= (ROM_DATA(8) and BSR(1)) ;
	RAM_ADDR(8)  <= (ROM_DATA(8) and BSR(0)) ;
	RAM_ADDR(7 downto 0) <= ROM_DATA(7 downto 0);
-------------------------------------------------------------------------------------------------------------------
	Inst_STATUS: STATUS PORT MAP(
		Clk => Clk,
		Reset => Reset,
		ADD_C => ALU_C,
		ADD_DC => ADD_DC,
		ADD_OV => ADD_OV,
		ALU_Z => ALU_Z,
		ALU_N => ALU_N,
		ADDWF => ADDWF,
		ADDWFC => ADDWFC,
		DECF => DECF,
		INCF => INCF,
		NEGF => NEGF,
		SUBWF => SUBWF,
		SUBWFB => SUBWFB,
		ADDLW => ADDLW,
		SUBLW => SUBLW,
		ANDWF => ANDWF,
		COMF => COMF,
		IORWF => IORWF,
		MOVF => MOVF,
		RLNCF => RLNCF,
		RLCF => RLCF,
		RRCF => RRCF,
		RRNCF => RRNCF,
		SETF => SETF,
		XORWF => XORWF,
		ANDLW => ANDLW,
		IORLW => IORLW,
		XORLW => XORLW,
		STATUS_EN => STATUS_EN,
		STATUS => STATUS1
	);
	STATUS_EN <= '1' when (RAM_ADDR = X"FD8") else '0';
	Alu_Z <= '1' when ALU_Y(7 downto 0) = 0 else '0';
	Alu_NZ <= '1' when ALU_Y(7 downto 0) > 0 else '0';
	Alu_N <= ALU_Y(7);
-------------------------------------------------------------------------------------------------------------------
	Inst_MUL: MUL PORT MAP(
		Clk => Clk,
		Reset => Reset,
		MULWF => MULWF,
		MULLW => MULLW,
		RAM_DATA => RAM_DATA,
		WREG => WREG,
		LIT => LIT,
		PRODH_EN => PRODH_EN,
		PRODL_EN => PRODL_EN,
		PRODH => PRODH,
		PRODL => PRODL 
	);
	PRODH_EN <= '1' when (RAM_ADDR = X"FF4") else '0';
	PRODL_EN <= '1' when (RAM_ADDR = X"FF3") else '0';
-------------------------------------------------------------------------------------------------------------------
	ALU_Y <= ADD_Y or LOG_Y or STATUS1 or PRODH or PRODL or LIT or TSTF;
	LIT <= ROM_DATA(7 downto 0) when (RAM_EN = '0') else (others => '0');
	ALU_A <= RAM_DATA or LIT;
	ALU_B <= WREG;
	ALU_C <= ADD_C or LOG_C;
	
	MOVLB <= '1' when (ROM_DATA(15 downto 4) = "000000010000") else '0';
    process (Clk, Reset, ROM_DATA)
    begin
		if Reset = '0' then
			BSR <= (others => '0');
		else
			if CLK'event and CLK = '0' then
				if MOVLB = '1' then
					BSR <= ROM_DATA(3 downto 0);
				end if;
			end if;
		end if;
    end process;
	 
	PORTA_WE <= '1' when ((RAM_ADDR = X"F80") and (RAM_WE = '1')) else '0';
    process (Clk, Reset, ALU_Y, PORTA_WE)
    begin
		if Reset = '0' then
			PORTA <= (others => '0');
		else
			if CLK'event and CLK = '0' then
				if PORTA_WE = '1' then
					PORTA <= ALU_Y;
				end if;
			end if;
		end if;
    end process;
	 
    process (Clk, Reset)
    begin
		if Reset = '0' then
			Clk1 <= '0';
		else
			if CLK'event and CLK = '0' then
				Clk1 <= not Clk1;
			end if;
		end if;
    end process;
	
	W_WE_EN <= RETLW or ANDLW or IORLW or MOVLW or RETLW or SUBLW or XORLW;
	WREG_WE <= ((F_WE_d_EN and (not ROM_DATA(9))) or W_WE_EN) and Clk1 ;
	 
    process (Clk, Reset, ALU_Y, WREG_WE)
    begin
		if Reset = '0' then
			WREG <= (others => '0');
		else
			if CLK'event and CLK = '0' then
				if (WREG_WE = '1') then
					WREG <= ALU_Y(7 downto 0);
				else
					null;
				end if;
			end if;
		end if;
    end process;
	
	SKIP2_AeB <= '1' when ((CPFSEQ = '1') and (RAM_DATA = WREG)) else '0';
	SKIP2_AgB <= '1' when ((CPFSGT = '1') and (RAM_DATA > WREG)) else '0';
	SKIP2_AlB <= '1' when ((CPFSLT = '1') and (RAM_DATA < WREG)) else '0';
	SKIP2_Z <= ALU_Z and (BTFSC or TSTFSZ or DECFSZ or INCFSZ);
	SKIP2_NZ <= ALU_NZ and (BTFSS or DCFSNZ or INFSNZ);
	SKIP2 <= SKIP2_AeB or SKIP2_AgB or SKIP2_AlB or SKIP2_Z or SKIP2_NZ;
	TSTF <= RAM_DATA when (TSTFSZ = '1') else (others => '0');

end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity INSTRUKTION_SET is
    Port (  ADDWF : out  STD_LOGIC;
				ADDWFC : out  STD_LOGIC;
				ANDWF : out  STD_LOGIC;
				CLRF : out  STD_LOGIC;
				COMF : out  STD_LOGIC;
				CPFSEQ : out  STD_LOGIC;
				CPFSGT : out  STD_LOGIC;
				CPFSLT : out  STD_LOGIC;
				DECF : out  STD_LOGIC;
				DECFSZ : out  STD_LOGIC;
				DCFSNZ : out  STD_LOGIC;
				INCF : out  STD_LOGIC;
				INCFSZ : out  STD_LOGIC;
				INFSNZ : out  STD_LOGIC;
				IORWF : out  STD_LOGIC;
				MOVF : out  STD_LOGIC;
--				MOVFF : out  STD_LOGIC;
				MOVWF : out  STD_LOGIC;
				MULWF : out  STD_LOGIC;
				NEGF : out  STD_LOGIC;
				RLCF : out  STD_LOGIC;
				RLNCF : out  STD_LOGIC;
				RRCF : out  STD_LOGIC;
				RRNCF : out  STD_LOGIC;
				SETF : out  STD_LOGIC;
				SUBFWB : out  STD_LOGIC;
				SUBWF : out  STD_LOGIC;
				SUBWFB : out  STD_LOGIC;
				SWAPF : out  STD_LOGIC;
				TSTFSZ : out  STD_LOGIC;
				XORWF : out  STD_LOGIC;
				BCF : out  STD_LOGIC;
				BSF : out  STD_LOGIC;
				BTFSC : out  STD_LOGIC;
				BTFSS : out  STD_LOGIC;
				BTG : out  STD_LOGIC;
				CALL : out  STD_LOGIC;
				GOTO : out  STD_LOGIC;
				RETLW : out  STD_LOGIC;
				ADDLW : out  STD_LOGIC;
				ANDLW : out  STD_LOGIC;
				IORLW : out  STD_LOGIC;
				MOVLW : out  STD_LOGIC;
				MULLW : out  STD_LOGIC;
				SUBLW : out  STD_LOGIC;
				XORLW : out  STD_LOGIC;
				NdWord : out  STD_LOGIC;
				ROM_DATA : in  STD_LOGIC_VECTOR (7 downto 0)
			  );
end INSTRUKTION_SET;

architecture Behavioral of INSTRUKTION_SET is

begin

ADDWF  <= '1' when ROM_DATA(7 downto 2) = "001001"  else '0' ; --ADDWF 	f, d, a 	C, DC, Z, OV, N
ADDWFC <= '1' when ROM_DATA(7 downto 2) = "001000"  else '0' ; --ADDWFC 	f, d, a 	C, DC, Z, OV, N
ANDWF  <= '1' when ROM_DATA(7 downto 2) = "000101"  else '0' ; --ANDWF 	f, d, a 	Z, N
CLRF   <= '1' when ROM_DATA(7 downto 1) = "0110101" else '0' ; --CLRF 	f, a 		Z
COMF   <= '1' when ROM_DATA(7 downto 2) = "000111"  else '0' ; --COMF 	f, d, a 	Z, N
CPFSEQ <= '1' when ROM_DATA(7 downto 1) = "0110001" else '0' ; --CPFSEQ 	f, a
CPFSGT <= '1' when ROM_DATA(7 downto 1) = "0110010" else '0' ; --CPFSGT 	f, a
CPFSLT <= '1' when ROM_DATA(7 downto 1) = "0110000" else '0' ; --CPFSLT 	f, a
DECF   <= '1' when ROM_DATA(7 downto 2) = "000001"  else '0' ; --DECF		f, d, a	C, DC, Z, OV, N
DECFSZ <= '1' when ROM_DATA(7 downto 2) = "001011"  else '0' ; --DECFSZ	f, d, a
DCFSNZ <= '1' when ROM_DATA(7 downto 2) = "010011"  else '0' ; --DCFSNZ	f, d, a
INCF   <= '1' when ROM_DATA(7 downto 2) = "001010"  else '0' ; --INCF		f, d, a	C, DC, Z, OV, N
INCFSZ <= '1' when ROM_DATA(7 downto 2) = "001111"  else '0' ; --INCFSZ	f, d, a
INFSNZ <= '1' when ROM_DATA(7 downto 2) = "010010"  else '0' ; --INFSNZ	f, d, a
IORWF  <= '1' when ROM_DATA(7 downto 2) = "000100"  else '0' ; --IORWF 	f, d, a 	Z, N
MOVF   <= '1' when ROM_DATA(7 downto 2) = "010100"  else '0' ; --MOVF 	f, d, a 	Z, N
--MOVFF  <= '1' when ROM_DATA(7 downto 4) = "1100"    else '0' ; --MOVFF 	fs, fd
NdWord <= '1' when ROM_DATA(7 downto 4) = "1111"    else '0' ; --NdWord
MOVWF  <= '1' when ROM_DATA(7 downto 1) = "0110111" else '0' ; --MOVWF 	f, a
MULWF  <= '1' when ROM_DATA(7 downto 1) = "0000001" else '0' ; --MULWF 	f, a
NEGF   <= '1' when ROM_DATA(7 downto 1) = "0110110" else '0' ; --NEGF 	f, a		C, DC, Z, OV, N
RLCF   <= '1' when ROM_DATA(7 downto 2) = "001101"  else '0' ; --RLCF 	f, d, a	C, Z, N
RLNCF  <= '1' when ROM_DATA(7 downto 2) = "010001"  else '0' ; --RLNCF 	f, d, a	Z, N
RRCF   <= '1' when ROM_DATA(7 downto 2) = "001100"  else '0' ; --RRCF 	f, d, a	C, Z, N
RRNCF  <= '1' when ROM_DATA(7 downto 2) = "010000"  else '0' ; --RRNCF 	f, d, a	Z, N
SETF   <= '1' when ROM_DATA(7 downto 1) = "0110100" else '0' ; --SETF		f, a
SUBFWB <= '1' when ROM_DATA(7 downto 2) = "010110"  else '0' ; --SUBFWB	f, d, a	C, DC, Z, OV, N
SUBWF  <= '1' when ROM_DATA(7 downto 2) = "010111"  else '0' ; --SUBWF	f, d, a	C, DC, Z, OV, N
SUBWFB <= '1' when ROM_DATA(7 downto 2) = "010101"  else '0' ; --SUBWFB	f, d, a	C, DC, Z, OV, N
SWAPF  <= '1' when ROM_DATA(7 downto 2) = "010101"  else '0' ; --SWAPF	f, d, a
TSTFSZ <= '1' when ROM_DATA(7 downto 1) = "0110011" else '0' ; --TSTFSZ	f, a
XORWF  <= '1' when ROM_DATA(7 downto 2) = "000110"  else '0' ; --XORWF	f, d, a	Z, N
BCF    <= '1' when ROM_DATA(7 downto 4) = "1001"    else '0' ; --BCF	f, b, a
BSF    <= '1' when ROM_DATA(7 downto 4) = "1000"    else '0' ; --BSF	f, b, a
BTFSC  <= '1' when ROM_DATA(7 downto 4) = "1011"    else '0' ; --BTFSC	f, b, a
BTFSS  <= '1' when ROM_DATA(7 downto 4) = "1010"    else '0' ; --BTFSS	f, b, a
BTG    <= '1' when ROM_DATA(7 downto 4) = "0111"    else '0' ; --BTG	f, b, a
ADDLW  <= '1' when ROM_DATA(7 downto 0) = "00001111" else '0' ; --ADDLW	k	C,DC,Z,OV,N
ANDLW  <= '1' when ROM_DATA(7 downto 0) = "00001011" else '0' ; --ANDLW 	k	Z,N
IORLW  <= '1' when ROM_DATA(7 downto 0) = "00001001" else '0' ; --IORLW 	k	Z, N		
MOVLW  <= '1' when ROM_DATA(7 downto 0) = "00001110" else '0' ; --MOVLW 	k	Z, N	
MULLW  <= '1' when ROM_DATA(7 downto 0) = "00001101" else '0' ; --MULLW 	k	Z, N	
RETLW  <= '1' when ROM_DATA(7 downto 0) = "00001100" else '0' ; --RETLW 	k
SUBLW  <= '1' when ROM_DATA(7 downto 0) = "00001000" else '0' ; --SUBLW 	k
XORLW  <= '1' when ROM_DATA(7 downto 0) = "00001010" else '0' ; --XORLW 	k	Z, N
GOTO   <= '1' when ROM_DATA(7 downto 0) = "11101111" else '0';
CALL   <= '1' when ROM_DATA(7 downto 0) = "11101100" else '0';  
RETLW	 <= '1' when ROM_DATA(7 downto 0) = "00001100" else '0'; 


end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity ADDER is
    Port ( ADD_A : in  STD_LOGIC_VECTOR (7 downto 0);	 --Wejście A
           ADD_B : in  STD_LOGIC_VECTOR (7 downto 0);  --Wejście B
			  ADD_Ci : in  STD_LOGIC;							 --Wejście Carry in
			  ADD_C : out  STD_LOGIC;							 --Carry dla 8 bitów
			  ADD_DC : out  STD_LOGIC;							 --Carry dla 4 bitów
			  ADD_OV : out  STD_LOGIC;							 --Przepełnienie dla liczb ze znakiem
           ADD_Y : out  STD_LOGIC_VECTOR (7 downto 0); -- Wyjście Adder
           ADDLW : in  STD_LOGIC;
           ADDWF : in  STD_LOGIC;
           ADDWFC : in  STD_LOGIC;
           SUBWFB : in  STD_LOGIC;
           SUBFWB : in  STD_LOGIC;
           SUBWF : in  STD_LOGIC;
           SUBLW : in  STD_LOGIC;
           DECF : in  STD_LOGIC;
           DECFSZ : in  STD_LOGIC;
			  DCFSNZ : in  STD_LOGIC;
           INCF : in  STD_LOGIC;
           INCFSZ : in  STD_LOGIC;
			  INFSNZ : in  STD_LOGIC;
			  NEGF : in  STD_LOGIC
			  );
end ADDER;

architecture Behavioral of ADDER is

	signal P : std_logic_vector (7 downto 0);			--Propaguj (OR)
	signal G : std_logic_vector (7 downto 0);			--Generuj  (AND)
	signal ASB : std_logic_vector (7 downto 0);		--Negacja wejścia B
	signal Q : std_logic_vector (7 downto 0);			--Dane z sumatora
	signal Cin : std_logic;									--Wejście Carry
	signal Cn : std_logic_vector (7 downto 0);		--Wyjścia przeniesień
	signal A : std_logic_vector (7 downto 0);
	signal B : std_logic_vector (7 downto 0);
	signal Y : std_logic_vector (7 downto 0);
	signal IN_A : std_logic_vector (7 downto 0);
	signal INCDEC : std_logic_vector (7 downto 0);
	signal Ci : std_logic;
	signal INC : std_logic;
	signal DEC : std_logic;
	signal ADD_SUB : std_logic;
	signal ADDEN : std_logic;

begin


	Cin <= ADD_SUB xor Ci;
	ASB(0) <= B(0) xor ADD_SUB;
	ASB(1) <= B(1) xor ADD_SUB;
	ASB(2) <= B(2) xor ADD_SUB;
	ASB(3) <= B(3) xor ADD_SUB;
	ASB(4) <= B(4) xor ADD_SUB;
	ASB(5) <= B(5) xor ADD_SUB;
	ASB(6) <= B(6) xor ADD_SUB;
	ASB(7) <= B(7) xor ADD_SUB;
	P(0) <= A(0) xor ASB(0);
	P(1) <= A(1) xor ASB(1);
	P(2) <= A(2) xor ASB(2);
	P(3) <= A(3) xor ASB(3);
	P(4) <= A(4) xor ASB(4);
	P(5) <= A(5) xor ASB(5);
	P(6) <= A(6) xor ASB(6);
	P(7) <= A(7) xor ASB(7);
	G(0) <= A(0) and ASB(0);
	G(1) <= A(1) and ASB(1);
	G(2) <= A(2) and ASB(2);
	G(3) <= A(3) and ASB(3);
	G(4) <= A(4) and ASB(4);
	G(5) <= A(5) and ASB(5);
	G(6) <= A(6) and ASB(6);
	G(7) <= A(7) and ASB(7);
	
	-- Carry lookahead (przeniesienie równoległe dla operacji dodawania, odejmowania)
	Q(0) <= Cin xor P(0);
	Cn(0)  <= G(0) or (Cin and P(0));
	Q(1) <= Cn(0) xor P(1);
	Cn(1)  <= G(1) or (Cin and P(0) and P(1)) or (G(0) and P(1));
	Q(2) <= Cn(1) xor P(2);
	Cn(2)  <= G(2) or (Cin and P(0) and P(1) and P(2)) or (G(0) and P(1) and P(2)) or (G(1) and P(2));
	Q(3) <= Cn(2) xor P(3);
	Cn(3)  <= G(3) or (Cin and P(0) and P(1) and P(2) and P(3)) or (G(0) and P(1) and P(2) and P(3)) or (G(1) and P(2) and P(3)) or (G(2) and P(3));
	Q(4) <= Cn(3) xor P(4);
	Cn(4) <= G(4) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4)) or (G(0) and P(1) and P(2) and P(3) and P(4)) or (G(1) and P(2) and P(3) and P(4)) or (G(2) and P(3) and P(4)) or (G(3) and P(4));
	Q(5) <= Cn(4) xor P(5);
	Cn(5)  <= G(5) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5)) or (G(1) and P(2) and P(3) and P(4) and P(5)) or (G(2) and P(3) and P(4) and P(5)) or (G(3) and P(4) and P(5)) or (G(4) and P(5));
	Q(6) <= Cn(5) xor P(6);
	Cn(6)  <= G(6) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(1) and P(2) and P(3) and P(4) and P(5) and P(6)) or (G(2) and P(3) and P(4) and P(5) and P(6)) or (G(3) and P(4) and P(5) and P(6)) or (G(4) and P(5) and P(6)) or (G(5) and P(6));
	Q(7) <= Cn(6) xor P(7);
	Cn(7)  <= G(7) or (Cin and P(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(0) and P(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(1) and P(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(2) and P(3) and P(4) and P(5) and P(6) and P(7)) or (G(3) and P(4) and P(5) and P(6) and P(7)) or (G(4) and P(5) and P(6) and P(7)) or (G(5) and P(6) and P(7)) or (G(6) and P(7));

	ADD_DC <= Cn(3);
	ADD_C <= Cn(7);
	ADD_OV <= Cn(7) xor Cn(6);
			  
	ADD_Y <= Y;
	Y <= Q when (ADDEN = '1') else (others => '0');
	ADDEN <= ADDLW or ADDWF or ADDWFC or SUBWFB or SUBFWB or SUBWF or SUBLW or DECF or DECFSZ or DCFSNZ or INCF or INCFSZ or INFSNZ or NEGF;
	
	INC <=  INCF or INCFSZ or INFSNZ;
	DEC <=  DECF or DECFSZ or DCFSNZ;
	Ci <= INC or DEC or NEGF or (ADDWFC and ADD_Ci) or (SUBWFB and ADD_Ci) or (SUBFWB and ADD_Ci);
	ADD_SUB <= DEC or SUBWFB or SUBFWB or SUBWF or SUBLW;
	
	INCDEC <=  (others => '0') when ((DEC = '1') or (INC = '1')) else (others => '1');
	IN_A <= not ADD_A when (NEGF = '1') else ADD_A;
	A <= ADD_B when (SUBFWB = '1') else IN_A;
	B <= ADD_A when (SUBFWB = '1') else (ADD_B and INCDEC);  


end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity LOGIC is
    Port (  LOG_A : in  STD_LOGIC_VECTOR (7 downto 0);
				LOG_B : in  STD_LOGIC_VECTOR (7 downto 0);
				BSel : in  STD_LOGIC_VECTOR (2 downto 0);
				LOG_Ci : in  STD_LOGIC;
				ANDWF : in  STD_LOGIC;
				ANDLW : in  STD_LOGIC;
				IORWF : in  STD_LOGIC;
				IORLW : in  STD_LOGIC;
				XORWF : in  STD_LOGIC;
				XORLW : in  STD_LOGIC;
				SWAPF : in  STD_LOGIC;
				RLNCF : in  STD_LOGIC;
				RLCF : in  STD_LOGIC;
				RRNCF : in  STD_LOGIC;
				RRCF : in  STD_LOGIC;
				SETF : in  STD_LOGIC;
				BSF : in  STD_LOGIC;
				BCF : in  STD_LOGIC;
				BTG : in  STD_LOGIC;
				BTFSS : in  STD_LOGIC;
				BTFSC : in  STD_LOGIC;
				COMF : in  STD_LOGIC;
				LOG_Co : out  STD_LOGIC;
				LOG_Y : out  STD_LOGIC_VECTOR (7 downto 0)
			  );
end LOGIC;

architecture Behavioral of LOGIC is

signal ANDAB : std_logic_vector (7 downto 0);
signal IORAB : std_logic_vector (7 downto 0);
signal XORAB : std_logic_vector (7 downto 0);
signal SETAB : std_logic_vector (7 downto 0);
signal SWAPAB : std_logic_vector (7 downto 0);
signal RLA : std_logic_vector (7 downto 0);
signal RLCA : std_logic_vector (7 downto 0);
signal RRA : std_logic_vector (7 downto 0);
signal RRCA : std_logic_vector (7 downto 0);
signal BITSP : std_logic_vector (7 downto 0);
signal BITSN : std_logic_vector (7 downto 0);
signal BSFAB : std_logic_vector (7 downto 0);
signal BCFAB : std_logic_vector (7 downto 0);
signal BTGAB : std_logic_vector (7 downto 0);
signal BTAB : std_logic_vector (7 downto 0);
signal COMAB : std_logic_vector (7 downto 0);
signal RCo : std_logic;
signal LCo : std_logic;

begin

LOG_Y <= ANDAB or IORAB or XORAB or SWAPAB or RLA or RLCA or RRA or RRA or RRCA or SETAB or BSFAB or BCFAB or BTGAB or BTAB or COMAB;
LOG_Co <= RCo or LCo;

ANDAB <= (LOG_A and LOG_B) when ((ANDWF = '1') or (ANDLW = '1')) else (others => '0');
IORAB <= (LOG_A or  LOG_B) when ((IORWF = '1') or (IORLW = '1')) else (others => '0');
XORAB <= (LOG_A xor LOG_B) when ((XORWF = '1') or (XORLW = '1')) else (others => '0');
BSFAB <= (LOG_A or  BITSP) when (BSF = '1') else (others => '0');
BCFAB <= (LOG_A and BITSN) when (BCF = '1') else (others => '0');
BTGAB <= (LOG_A xor BITSP) when (BTG = '1') else (others => '0');
BTAB <= (LOG_A and BITSP) when ((BTFSS = '1') or (BTFSC = '1')) else (others => '0');
SETAB <= (others => '1') when (SETF = '1') else (others => '0');
COMAB <= (not LOG_A) when (COMF = '1') else (others => '0');
SWAPAB <= (LOG_A(3 downto 0) & LOG_A(7 downto 4)) when (SWAPF = '1') else (others => '0');
RLA <= (LOG_A(6 downto 0) & LOG_A(7)) when (RLNCF = '1') else (others => '0');
RLCA <= (LOG_A(6 downto 0) & LOG_Ci) when (RLCF = '1') else (others => '0');
LCo <= LOG_A(7) when (RLCF = '1') else '0';
RRA <= (LOG_A(0) & LOG_A(7 downto 1)) when (RRNCF = '1') else (others => '0');
RRCA <= (LOG_Ci & LOG_A(7 downto 1)) when (RRCF = '1') else (others => '0');
RCo <= LOG_A(0) when (RRCF = '1') else '0';

with BSel select
BITSP <= "00000001" when "000",
         "00000010" when "001",
         "00000100" when "010",
         "00001000" when "011",
         "00010000" when "100",
         "00100000" when "101",
         "01000000" when "110",
         "10000000" when others;
BITSN <= not BITSP;

end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PC is
    Port ( Clk : in  STD_LOGIC;
           Clk1 : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
			  CALL : in  STD_LOGIC;
			  GOTO : in  STD_LOGIC;
			  RETLW : in  STD_LOGIC;
			  NdWord : in  STD_LOGIC;
			  INTERUPT : in  STD_LOGIC;
			  SKIP2 : in  STD_LOGIC;
			  ROM_ADDR : inout  STD_LOGIC_VECTOR(19 downto 0);
			  ROM_DATA : in  STD_LOGIC_VECTOR(15 downto 0)
			  );
end PC;

architecture Behavioral of PC is

	signal ROMAddrL : STD_LOGIC_vector (7 downto 0);
	signal TOSCnt : STD_LOGIC_vector (3 downto 0);
	signal TOS : STD_LOGIC_vector (19 downto 0);
	signal TOS0 : STD_LOGIC_vector (19 downto 0);
	signal TOS1 : STD_LOGIC_vector (19 downto 0);
	signal TOS2 : STD_LOGIC_vector (19 downto 0);
	signal TOS3 : STD_LOGIC_vector (19 downto 0);
	signal TOS4 : STD_LOGIC_vector (19 downto 0);
	signal TOS5 : STD_LOGIC_vector (19 downto 0);
	signal TOS6 : STD_LOGIC_vector (19 downto 0);
	signal TOS7 : STD_LOGIC_vector (19 downto 0);
	signal TOS8 : STD_LOGIC_vector (19 downto 0);
	signal TOS9 : STD_LOGIC_vector (19 downto 0);
	signal TOS10 : STD_LOGIC_vector (19 downto 0);
	signal TOS11 : STD_LOGIC_vector (19 downto 0);
	signal TOS12 : STD_LOGIC_vector (19 downto 0);
	signal TOS13 : STD_LOGIC_vector (19 downto 0);
	signal TOS14 : STD_LOGIC_vector (19 downto 0);
	signal TOS15 : STD_LOGIC_vector (19 downto 0);
	signal TOSINT : STD_LOGIC_vector (19 downto 0);
	signal RETURN1 : STD_LOGIC;
	signal RETFIE : STD_LOGIC;
	signal SKIPEN : STD_LOGIC;
	signal INTEN : STD_LOGIC;

begin

	RETURN1 <= '1' when ROM_DATA(15 downto 0) = "0000000000010010" else '0';
	RETFIE  <= '1' when ROM_DATA(15 downto 0) = "0000000000010000" else '0';
					
	process(Clk, Clk1, Reset,  SKIP2, ROM_DATA, TOS, TOSINT, GOTO, CALL, NdWord, RETLW, RETURN1, RETFIE)
	begin
		if Reset = '0' then
			ROM_ADDR <= (others => '0');
			ROMAddrL <= (others => '0');
			TOSCnt <= (others => '0');
			SKIPEN <=  '0';
			INTEN <=  '0';
		else
			if Clk'event and Clk = '0' then
				if Clk1 = '1' then
					if (SKIP2 = '1') then
						ROM_ADDR <= ROM_ADDR + 2;
						
				elsif GOTO = '1' then		--GOTO
						ROMAddrL <= ROM_DATA(7 downto 0);
						SKIPEN <=  '1';
						ROM_ADDR <= ROM_ADDR + 1;
				elsif CALL = '1' then		--CALL
						ROMAddrL <= ROM_DATA(7 downto 0);
						SKIPEN <=  '1';
						TOSCnt <= TOSCnt + 1;
						ROM_ADDR <= ROM_ADDR + 1;
				elsif ((INTERUPT = '1') and (INTEN = '0')) then		--INTERUPT
						TOSINT <= ROM_ADDR;
						INTEN <= '1';
						ROM_ADDR <= X"00008";
				elsif (SKIPEN = '1') and (NdWord = '1') then
						ROM_ADDR <= ROM_DATA(11 downto 0) & ROMAddrL;
						SKIPEN <=  '0';
				elsif ((RETURN1 = '1') or (RETLW = '1')) then --RETURN, RETLW,
						ROM_ADDR <= TOS + 2;
						TOSCnt <= TOSCnt - 1;
				elsif (RETFIE = '1') then --RETFIE
						ROM_ADDR <= TOSINT + 1;
						INTEN <= '0';
						TOSCnt <= TOSCnt - 1;
					else
						ROM_ADDR <= ROM_ADDR + 1;
					end if;
				end if;
			end if;
		end if;
	end process;
	
	with TOSCnt select
		TOS <= TOS1 when "0001",
				 TOS2 when "0010",
				 TOS3 when "0011",
				 TOS4 when "0100",
				 TOS5 when "0101",
				 TOS6 when "0110",
				 TOS7 when "0111",
				 TOS8 when "1000",
				 TOS9 when "1001",
				 TOS10 when "1010",
				 TOS11 when "1011",
				 TOS12 when "1100",
				 TOS13 when "1101",
				 TOS14 when "1110",
				 TOS15 when "1111",
				 TOS0 when others;
				 
	process(Clk, Clk1, Reset, TOSCnt, CALL, ROM_ADDR)
	begin
		if Reset = '0' then
			TOS0 <= (others => '0');
			TOS1 <= (others => '0');
			TOS2 <= (others => '0');
			TOS3 <= (others => '0');
			TOS4 <= (others => '0');
			TOS5 <= (others => '0');
			TOS6 <= (others => '0');
			TOS7 <= (others => '0');
			TOS8 <= (others => '0');
			TOS9 <= (others => '0');
			TOS10 <= (others => '0');
			TOS11 <= (others => '0');
			TOS12 <= (others => '0');
			TOS13 <= (others => '0');
			TOS14 <= (others => '0');
			TOS15 <= (others => '0');
		else
			if Clk'event and Clk = '0' then
				if Clk1 = '1' then
					if Call = '1' then		
					 case TOSCnt is
						when "0001" =>
							TOS1 <= ROM_ADDR;
						when "0010" =>
							TOS2 <= ROM_ADDR;
						when "0011" =>
							TOS3 <= ROM_ADDR;
						when "0100" =>
							TOS4 <= ROM_ADDR;
						when "0101" =>
							TOS5 <= ROM_ADDR;
						when "0110" =>
							TOS6 <= ROM_ADDR;
						when "0111" =>
							TOS7 <= ROM_ADDR;
						when "1000" =>
							TOS8 <= ROM_ADDR;
						when "1001" =>
							TOS9 <= ROM_ADDR;
						when "1010" =>
							TOS10 <= ROM_ADDR;
						when "1011" =>
							TOS11 <= ROM_ADDR;
						when "1100" =>
							TOS12 <= ROM_ADDR;
						when "1101" =>
							TOS13 <= ROM_ADDR;
						when "1110" =>
							TOS14 <= ROM_ADDR;
						when "1111" =>
							TOS15 <= ROM_ADDR;
						when others =>
							TOS0 <= ROM_ADDR;
						end case;
					else
						null;
					end if;
				end if;
			end if;
		end if;
	end process;


end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity RAM is
    Port ( Clk : in  STD_LOGIC;
           RAM_WE : in  STD_LOGIC;
           RAM_EN : in  STD_LOGIC;
           RAM_ADDR : in  STD_LOGIC_VECTOR (11 downto 0);
           RAM_DI : in  STD_LOGIC_VECTOR (7 downto 0);
           RAM_DATA : out  STD_LOGIC_VECTOR (7 downto 0)
			  );
end RAM;

architecture Behavioral of RAM is

    type ram_type is array (4095 downto 0) of STD_LOGIC_vector (7 downto 0);
    signal RAM: ram_type;
    signal RAM_DOUT : std_logic_vector (7 downto 0);

begin
    process (Clk, RAM_WE, RAM_ADDR, RAM_DI, RAM_EN)
    begin
        if CLK'event and CLK = '0' then
			 if (RAM_WE = '1') then
				 RAM(conv_integer(RAM_ADDR)) <= RAM_DI;
			 end if;
				RAM_DOUT <= RAM(conv_integer(RAM_ADDR)) ;
        end if;
    end process;

	RAM_DATA <= RAM_DOUT when (RAM_EN = '1') else (others => '0') ;
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity STATUS is
    Port ( Clk : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
           ADD_C : in  STD_LOGIC;
           ADD_DC : in  STD_LOGIC;
           ADD_OV : in  STD_LOGIC;
           ALU_Z : in  STD_LOGIC;
           ALU_N : in  STD_LOGIC;
           ADDWF : in  STD_LOGIC;
           ADDWFC : in  STD_LOGIC;
           DECF : in  STD_LOGIC;
           INCF : in  STD_LOGIC;
           NEGF : in  STD_LOGIC;
           SUBWF : in  STD_LOGIC;
           SUBWFB : in  STD_LOGIC;
           ADDLW : in  STD_LOGIC;
           SUBLW : in  STD_LOGIC;
           ANDWF : in  STD_LOGIC;
           COMF : in  STD_LOGIC;
           IORWF : in  STD_LOGIC;
           MOVF : in  STD_LOGIC;
           RLNCF : in  STD_LOGIC;
           RLCF : in  STD_LOGIC;
           RRCF : in  STD_LOGIC;
           RRNCF : in  STD_LOGIC;
           SETF : in  STD_LOGIC;
           XORWF : in  STD_LOGIC;
           ANDLW : in  STD_LOGIC;
           IORLW : in  STD_LOGIC;
           XORLW : in  STD_LOGIC;
           STATUS_EN : in  STD_LOGIC;
			  STATUS : out  STD_LOGIC_VECTOR (7 downto 0)
			  );
end STATUS;

architecture Behavioral of STATUS is
	
	signal STATUS1 : std_logic_vector (7 downto 0);
	signal STATUS_C_WE : std_logic;
	signal STATUS_DC_WE : std_logic;
	signal STATUS_Z_WE : std_logic;

begin

STATUS_C_WE <= STATUS_DC_WE or RLCF or RRCF;
STATUS_DC_WE <= ADDWF or ADDWFC or DECF or INCF or NEGF or SUBWF or SUBWFB or ADDLW or SUBLW;
STATUS_Z_WE <= STATUS_C_WE or ANDWF or COMF or IORWF or MOVF or RLNCF or RLCF or RRCF or RRNCF or SETF or XORWF or ANDLW or IORLW or XORLW;

    process (Clk, Reset, STATUS_C_WE, STATUS_DC_WE, STATUS_Z_WE)
    begin
		if Reset = '0' then
			STATUS1 <= (others => '0');
		else
			if CLK'event and CLK = '0' then
				if STATUS_C_WE = '1' then
					STATUS1(0) <= ADD_C;
				else
					null;
				end if;
				if STATUS_DC_WE = '1' then
					STATUS1(1) <= ADD_DC;
					STATUS1(3) <= ADD_OV;
				else
					null;
				end if;
				if STATUS_Z_WE = '1' then
					STATUS1(2) <= ALU_Z;
					STATUS1(4) <= ALU_N;
				else
					null;
				end if;
			end if;
		end if;
    end process;

STATUS <= STATUS1 when (STATUS_EN = '1') else (others => '0');

end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity MUL is
    Port ( Clk : in  STD_LOGIC;
           Reset : in  STD_LOGIC;
           MULWF : in  STD_LOGIC;
           MULLW : in  STD_LOGIC;
           RAM_DATA : in  STD_LOGIC_VECTOR (7 downto 0);
           WREG : in  STD_LOGIC_VECTOR (7 downto 0);
           LIT : in  STD_LOGIC_VECTOR (7 downto 0);
           PRODH_EN : in  STD_LOGIC;
           PRODL_EN : in  STD_LOGIC;
           PRODH : out  STD_LOGIC_VECTOR (7 downto 0);
           PRODL : out  STD_LOGIC_VECTOR (7 downto 0)
			  );
end MUL;

architecture Behavioral of MUL is

signal PRODWF : std_logic_vector (15 downto 0);
signal PRODLW : std_logic_vector (15 downto 0);
signal PROD : std_logic_vector (15 downto 0);
signal PROD1 : std_logic_vector (15 downto 0);
signal MULEN : std_logic;

begin

PRODWF <= (RAM_DATA * WREG) when (MULWF = '1') else (others => '0');
PRODLW <= (LIT * WREG) when (MULLW = '1') else (others => '0');
PROD <= PRODWF or PRODLW;
MULEN <= MULLW or MULWF;
	 
    process (Clk, Reset, PROD, MULEN)
    begin
		if Reset = '0' then
			PROD1 <= (others => '0');
		else
			if CLK'event and CLK = '0' then
				if (MULEN = '1') then
					PROD1 <= PROD;
				else
					null;
				end if;
			end if;
		end if;
    end process;


PRODH <= PROD1(15 downto 8) when PRODH_EN = '1' else(others => '0') ;
PRODL <= PROD1(7 downto 0) when PRODL_EN = '1' else(others => '0') ;

end Behavioral;

image.thumb.png.7f28cdc435193399e4df70ed4c6ed3a1.png cokolwiek to znaczy 🙂

  • Lubię! 1
Link do komentarza
Share on other sites

Witam.

Pierwsza próba symulacji kontrolera. 

Napisałem krótki kod testowy w języku assembler:

;**************************************************************************
;*                                SOFTWARE                                *
;**************************************************************************
;*          Microchip PIC in FPGA                                         *
;*	    DEMO1 program for testing FPGA SPARTAN3 with PIC18F4550!      *
;*          PORTA  data output                                            *
;**************************************************************************
;*          Hardw. Rev: FPGAxs3s         Softw. Rev:  1.00                *
;**************************************************************************


list p=18f4550
include "C:\Users\WINDOWS\OneDrive\Pulpit\Include_files\p18f4550.inc"



		ORG	0		;Reset vector address
        	GOTO	DELAY_ROUTINE




DELAY_ROUTINE   NOP  
                NOP
		MOVLW		H'07'
		MOVLB		H'F'
		MOVWF		PORTA,1
		ADDWF		PORTA,1,1
		ADDWF		PORTA,1,1
		SUBWF		PORTA,1,1
		GOTO		DELAY_ROUTINE
		;


		END

Kody maszynowe wygenerowane przez kompilator:

LOC	OBJECT CODE

000000 0000           00028 DELAY_ROUTINE   NOP  
000002 0000           00029                 NOP
                      00030 
                      00031 
                      00032 ;              **********************************
                      00033 ;              **  RESET :  main boot routine  **
                      00034 ;              **********************************
                      00035 
000004 0E07           00036                 MOVLW           H'07'
000006 010F           00037                 MOVLB           H'F'
000008 6F80           00038                 MOVWF           PORTA,1
00000A 2780           00039                 ADDWF           PORTA,1,1
00000C 2780           00040                 ADDWF           PORTA,1,1
00000E 5F80           00041                 SUBWF           PORTA,1,1
000010 EF00 F000      00042                 GOTO            DELAY_ROUTINE
                      00043                 ;
                      00044 
                      00045 
                      00046                 END

Kody wstawiłem do programu VHDL:

with ROM_ADDR select
ROM_DATA <= X"0000" when X"000", --NOP
	    X"0000" when X"001", --NOP
	    X"0E07" when X"002", --MOVLW X"07"
	    X"010F" when X"003", --MOVLB X"F"
	    X"6F80" when X"004", --MOVWF PORTA,1
	    X"2780" when X"005", --ADDWF PORTA,1,1
	    X"2780" when X"006", --ADDWF PORTA,1,1
	    X"5F80" when X"007", --SUBWF PORTA,1,1
	    X"EF00" when X"008", --GOTO ADDR LSB X"00"
	    X"F000" when X"009", --NdWord ADDR MSB X"000"
	    X"0000" when others;

Kod dla symulacji w TB

--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY PIC18F_TB IS
END PIC18F_TB;
 
ARCHITECTURE behavior OF PIC18F_TB IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT PIC18F
    PORT(
         Clk : IN  std_logic;
         Reset : IN  std_logic;
         INTERRUPT : IN  std_logic;
         PORTA : OUT  std_logic_vector(7 downto 0);
         ROM_ADDR : INOUT  std_logic_vector(19 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal Clk : std_logic := '0';
   signal Reset : std_logic := '0';
   signal INTERRUPT : std_logic := '0';

	--BiDirs
   signal ROM_ADDR : std_logic_vector(19 downto 0);

 	--Outputs
   signal PORTA : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant Clk_period : time := 10 ns;
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: PIC18F PORT MAP (
          Clk => Clk,
          Reset => Reset,
          INTERRUPT => INTERRUPT,
          PORTA => PORTA,
          ROM_ADDR => ROM_ADDR
        );

   -- Clock process definitions
   Clk_process :process
   begin
		Clk <= '0';
		wait for Clk_period/2;
		Clk <= '1';
		wait for Clk_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin		
	
   Reset <= '0';
   INTERRUPT <= '0';
      wait for Clk_period*2;
		
   Reset <= '1';
   INTERRUPT <= '0';
      wait for Clk_period*20;

      wait;
   end process;

END;

Kod powinien się zapętlić po poleceniu "NdWord". Tak też się dzieje. Poza tym instrukcje zapisu, dodawania i odejmowania wydają się działać poprawnie.  

                                                                        image.thumb.png.10b063c5bb6a7da39fbf0028d8320d7d.png

pozdrawiam.

 

Link do komentarza
Share on other sites

(edytowany)

 

Witam.

 

Wyjaśnienie  przetwarzania danych w układzie logicznym.

Na wejścia LOG_A i LOG_B podajemy dane na których będą wykonane trzy podstawowe operacje (AND, OR, XOR), Na wyjściu LOG_Y uzyskujemy przetworzone dane.

-------------------------------------------------------------------------------------------------------------

polecenie kontrolera     |       liczba binarna           |      operacja      |        wejścia, wyjście

-------------------------------------------------------------------------------------------------------------

1:

operacja AND

-------------------------------------------------------------------------------------------------------------

ANDLW                        |             1110 1011                   |           AND         |              LOG_A

ANDWF                        |            0101 1100                   |                            |              LOG_B

                                     |            0100 1000                   |                            |              LOG_Y

 

kod VHDL:

LOG_Y <= LOG_A and LOG_B;

-------------------------------------------------------------------------------------------------------------

2:

operacja BCF każe ustawić wybrany bit wybrany przez dekoder 1 z 8  w bajcie podanym na wejście LOG_A na logiczne '0'.

W naszym przykładzie na wejście LOG_A podajemy dane, a na wejściu LOG_B ustawiamy wybrany bit(1) na '0' (resztę bitów ustawiamy na '1') i łączymy wejścia danych bramkami AND.

W ten sposób na wybranym bicie na wyjściu LOG_Y zostanie wymuszone logiczne '0'.

-------------------------------------------------------------------------------------------------------------

BCF b'001'                   |             1110 1011                   |           AND         |              LOG_A

                                     |            1111 1101                    |                            |              LOG_B

                                     |            1110 1001                   |                            |              LOG_Y

 

kod VHDL:

with b select

BitSel <= ”00000001" when '”000” ,

               ”00000010” when '”001” ,

                ”00000100” when '”010” ,

                ”00001000” when '”011” ,

               ”00010000” when '”100” ,

              '”00100000” when '”101” ,

              ”01000000” when '”110” ,

              ”10000000” when others ;

 

               LOG_B <= (not BitSel);

-------------------------------------------------------------------------------------------------------------

3:

operacja OR

-------------------------------------------------------------------------------------------------------------

ANDLW                        |             1110 1011                   |           OR            |              LOG_A

ANDWF                        |            0101 1100                   |                            |              LOG_B

                                     |             1111 1111                    |                            |              LOG_Y

 

kod VHDL:

LOG_Y <= LOG_A or LOG_B;

-------------------------------------------------------------------------------------------------------------

4:

operacja BSF każe ustawić wybrany bit wybrany przez dekoder 1 z 8  w bajcie podanym na wejście LOG_A na logiczne '1'.

W naszym przykładzie na wejście LOG_A podajemy dane, a na wejściu LOG_B ustawiamy wybrany bit(1) na '1' (resztę bitów ustawiamy na '0') i łączymy wejścia danych bramkami OR.

W ten sposób na wybranym bicie na wyjściu LOG_Y zostanie wymuszone logiczne '1' .

-------------------------------------------------------------------------------------------------------------

BSF b'001'                    |          1110 1001             |             OR               |             LOG_A

                                      |         0000 0010           |                                  |            LOG_B

                                      |           1110 1011            |                                  |             LOG_Y

-------------------------------------------------------------------------------------------------------------

kod VHDL:

with b select

BitSel <= ”00000001" when '”000” ,

               ”00000010” when '”001” ,

                ”00000100” when '”010” ,

                ”00001000” when '”011” ,

               ”00010000” when '”100” ,

              '”00100000” when '”101” ,

              ”01000000” when '”110” ,

              ”10000000” when others ;

 

               LOG_B <= BitSel;

-------------------------------------------------------------------------------------------------------------

5:

operacja XOR

-------------------------------------------------------------------------------------------------------------

XORLW                       |                1110 1011               |              XOR           |                LOG_A

XORWF                       |                0101 1100              |                                |                LOG_B

                                    |                 1111 1111               |                                |                LOG_Y

 

 

kod VHDL:

LOG_Y <= LOG_A xor LOG_B;

-------------------------------------------------------------------------------------------------------------

6:

operacja BTG każe zanegować wybrany bit wybrany przez dekoder 1 z 8  w bajcie podanym na wejście LOG_A .

W naszym przykładzie na wejście LOG_A podajemy dane, a na wejściu LOG_B ustawiamy wybrany bit(1) na '1' (resztę bitów ustawiamy na '0') i łączymy wejścia danych bramkami XOR.

W ten sposób wybrany bit na wyjściu LOG_Y zostanie zanegowany.

-------------------------------------------------------------------------------------------------------------

BTG b'001'                    |               1110 1011                   |                XOR               |                 LOG_A

                                      |               0000 0010                |                                      |                  LOG_B

                                      |              1110 1001                   |                                       |                 LOG_Y

-------------------------------------------------------------------------------------------------------------

kod VHDL:

with b select

BitSel <= ”00000001" when '”000” ,

               ”00000010” when '”001” ,

                ”00000100” when '”010” ,

                ”00001000” when '”011” ,

               ”00010000” when '”100” ,

              '”00100000” when '”101” ,

              ”01000000” when '”110” ,

              ”10000000” when others ;

 

                  LOG_B <= BitSel;

7:

Operacje BTFSS i BTFSC polegają na testowaniu bitów i wymuszenie w liczniku programu, w przypadku prawdy, pominięcie następnego polecenia w programie.

 

Moim rozwiązaniem jest testowanie wyniku zerowego na wyjściu LOG_Y.

Dlaczego akurat tak? Ponieważ kontroler posiada inne instrukcje( np.: DECFSC) które testują wynik zerowy ALU_Z, w związku z tym, postanowiłem połączyć instrukcje o podobnych funkcjach.

Wynik zerowy uzyskujemy z zanegowanego wyjscia LOG_Y połączonego  bramkami OR ( wynik = '1' dla prawdy).

Kod VHDL : ALU_Z <= not (LOG_Y(0) or LOG_Y(1) or ... LOG_Y(7));

 

-------------------------------------------------------------------------------------------------------------

BTFSS b'001'                   |            1110 1011          |         AND           |            LOG_A

BTFSC b'001                    |          0000 0010        |                             |            LOG_B

                                         |          0000 0010         |                            |            LOG_Y

-------------------------------------------------------------------------------------------------------------

kod VHDL:

with b select

BitSel <= ”00000001" when '”000” ,

               ”00000010” when '”001” ,

                ”00000100” when '”010” ,

                ”00001000” when '”011” ,

               ”00010000” when '”100” ,

              '”00100000” when '”101” ,

              ”01000000” when '”110” ,

              ”10000000” when others ;

 

             LOG_B <= BitSel;

            Skip_Enable0 <= '1' when ((ALU_Z = '1')  and (BTFSC = '1'))else '0'; 

            Skip_Enable1 <= '1' when (ALU_Z = '0')  and (BTFSS = '1')) else '0';

            Skip_Enable <= Skip_Enable0 or Skip_Enable1;

W naszym przykładzie testowany bit (1) w na wejściu LOG_A jest w stanie logicznym '1' więc wynik operacji nie może być zerowy i wynik ALU_Z = '0'.

W związku z tym instrukcja BTFSS ( skok w programie gdy wybrany bit jest ustawiony) jest prawdziwa, podczas gdy BTFSC ( skok w programie gdy wybrany bit jest skasowany) zostanie instrukcją pustą (NOP).

PS:

W układach konfigurowalnych możemy stworzyć struktury które pozwalają rozszerzyć ich funkcjonalność. W przykładowych instrukcjach BTFSS i BTFSC można zaimplementować skoki nie tylko o jedną instrukcję, ale na przykład o trzy instrukcje tworząc dodatkowy rejestr z którego wyprowadzamy z wybranego bitu sygnał zezwolenia.

Przykład: Skip_Reg(0) = Skip_3_Enable. Ustawiając ten bit w rejestrze na logiczne '1' można podłączyć wyjściowy sygnał jako sygnał zezwolenia dla licznika programu, by w następnym cyklu przeskoczył o trzy adresy do przodu. (Nie tworzymy przy tym dodatkowych instrukcji programu zachowując kompatybilność oprogramowania kontrolera z oryginałem). By kompilator wiedział o istnieniu tego rejestru możemy go dopisać do pliku " .inc "(header file defines configurations, registers, and other useful) z którego oprogramowanie pobiera informacje o rejestrach i ich adresach.

 

Pozdrawiam.

Edytowano przez kroszkanorber
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.