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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.