Rejestr 4-bitowy LFSR na GTKWave Ubuntu, vhdl, ghdl

LFSR – Linear Feedback Shift Register, czyli rejestr przesuwający z liniowym sprzężeniem zwrotnym, jest powszechnie wykorzystywany jako generator liczb pseudolosowych lub też generator szumu. Opiera się on na bramkach xor lub xnor.

W poniższym artykule przedstawię, jak przeprowadzić symulację rejestru w systemie Ubuntu, korzystając z języka vhdl i narzędzia do symulacji GTKWave.

Aby rozpocząć pracę z językiem vhdl, należy najpierw zainstalować odpowiednie paczki:

sudo add-apt-repository ppa:pgavin/ghdl
sudo apt-get update
sudo apt-get install ghdl

Następnie tworzymy 2 pliki, z których jeden będzie służył do symulacji jak poniżej lub – jeżeli nie chcemy tworzyć plików – możemy je pobrać poleceniem:

wget http://szymonwojtowicz.no-ip.org/ftp/lfsr4f.tar.bz2

i rozpakować poleceniem:

tar -xvjf ./lfsr4f.tar.bz2 

PLIKI DO SYMULACJI:

-- Plik lfsr.vhdl, jest on odpowiedzialny za logikę systemu, tzn. przerzucanie bitów:
entity lfsr is port(ck:in bit; rst : in bit; b: out bit);
end lfsr;
architecture rtl of lfsr is
signal lfsr : bit_vector(3 downto 0) <= "0110";
begin
process(ck,rst)
variable temp : bit := '0';
begin
if rst='1' then
lfsr(3 downto 0) <= "0110";
elsif ck = '1' and ck'event then
temp := lfsr(3);
-- przypisuje wartość tymczasową do rejestru (jeżelibym tego nie zrobił zapisana
-- byłaby w kolejnej linijce kodu wartość nadpisana, czyli bieżąca rejestru)
lfsr <= (lfsr(2) xor lfsr(3)) & lfsr(1) & lfsr(0) & temp;
-- przypisuje strumieniowo do wektora wartości
b <= lfsr(3);
-- wysyła wartość rejestru 3 (może być dowolna) na wyjście układu
end if;
end process;
end rtl;

I drugi plik o nazwie lfsr_tb.vhdl

-- Plik lfsr_tb.vhdl przeznaczony do symulacji, ponieważ zawiera on moduł czasowy
-- Plik testowy nie posiada zadeklarowanych portów
entity lfsr_tb is
end lfsr_tb;
architecture behav of lfsr_tb is
-- Deklaracja poszczególnych komponentów, które zostaną zainicjalizowane
component lfsr
port (ck : in bit; rst: in bit; b : out bit);
end component;
-- Przypisanie jednostek do składników
for lfsr_0: lfsr use entity work.lfsr;
signal b : bit;
signal ck : bit;
signal rst : bit;
begin
-- Inicjalizacja komponentów
lfsr_0: lfsr port map (ck => ck, rst => rst, b => b);
-- Proces poniżej wykonuje rzeczywistą pracę dla układu w GTKWave
process
begin
for i in 65535 downto 0 loop -- Ilość iteracji pętli
wait for 10 ps; -- Okres czasu, przez jaki zegar ma przyjmować wartość 1
ck <= '1'; -- Przypisanie wartości do ck
wait for 10 ps; -- Okres czasu, przez jaki zegar ma przyjmować wartość 0
ck <= '0'; -- Przypisanie wartości do ck
end loop; -- Zakończenie pętli
wait;
end process;
end behav;

Następnie tworzymy skrypt, który uprości proces kompilacji o nazwie run.sh:

#!/bin/bash
ghdl -a lfsr.vhdl
ghdl -a lfsr_tb.vhdl
ghdl -e lfsr_tb
./lfsr_tb --vcd=out_dump.vcd
gtkwave out_dump.vcd

Po utworzeniu skryptu nadajemy mu odpowiednie uprawnienia do wykonywania w terminalu:
sudo chmod +x ./run.sh
Następnie możemy zobaczyć, jak działa algorytm w programie GTKWave poprzez wydanie polecenia w obecnym folderze ./run.sh:
Aby zobaczyć poniższą symulację należy z listy SST wybrać lfsr_0. Następnie poniżej ukażą nam się sygnały, które należy przenieść do zakładki Signals i rozwinąć (dwukrotnie klikając). Następnie trzeba dostosować długość sygnału do wygodnego rozmiaru okna, używając lupy:
GTKWave

Poniższy schemat przedstawia działanie naszego rejestru:
CLK - clock, czyli zegar
RST - reset
B - sygnał emitowany na wyjściu przy każdym cyklu
D0,D1,D2,D3 - poszczególne rejestry zapamiętujące stany (0 lub 1) między taktami zegara

Schemat Rejestrów

W poniższej tabeli zostały zaprezentowane stany, jakie przyjmują poszczególne rejestry D0,D1,D2,D w kolejnych taktach zegarowych. Należy wspomnieć, że stan początkowy 0110 jest stanem umownym. Co za tym idzie, po pierwszym umownym cyklu następuje cykl drugi, a w nim wartość D0 jest brana z cyklu pierwszego, jaki przyjmował rejestr D3, równocześnie wartość D1 przyjmuje wartość jaką miał w pierwszym cyklu rejestr D0, a rejestr D2 przyjmuje wartość D1. Najważniejsza zmiana w całym układzie występuje w rejestrze D3, który pobierając wartości z samego siebie z poprzedniego stanu i z rejestru D2 przesyła ją przez bramkę XOR, dając odpowiednie wartości. W roli przypomnienia dołączyłem wartości, jakie przyjmuje bramka po przyjęciu odpowiednich stanów.

p q p v q
0 0 0
0 1 1
1 0 1
1 1 0

Bramka XOR to inaczej alternatywa wykluczająca. W skrócie można, przyjmując logikę jej działania, powiedzieć, że jeżeli 2 stany wejściowe są różne, to wyjście jest prawdziwe (przyjmuje stan równy 1). W pierwszym cyklu D3 i D2 kolejno przyjmują stany 0 i 1, a więc na wyjściu będziemy mieli w drugim cyklu wartość prawdziwą (równą 1).



style=”display:inline-block;width:728px;height:90px”
data-ad-client=”ca-pub-3473784311111784″
data-ad-slot=”1536038152″>

Wartość dzeiesiętna 8 4 2 1
Cykl / Rejestr Wartość D3 D2 D1 D0
1 – 6 0 1 1 0
2 – 12/C 1 1 0 0
3 – 1 0 0 0 1
4 – 2 0 0 1 0
5 – 4 0 1 0 0
6 – 8 1 0 0 0
7 – 9 1 0 0 1
8 – 11/B 1 0 1 1
9 – 15/F 1 1 1 1
11 – 7 0 1 1 1
12 – 14/E 1 1 1 0
13 – 5 0 1 0 1
14 – A 1 0 1 0
15 – D 1 1 0 1
16 – 3 0 0 1 1

Poniżej został przedstawiony cykl generowania liczb pseudolosowych. Należy zwrócić uwagę, że 16 nie ma stanu 0000, czyli cyfry 0.

Algorytm LFSR

I na zakończenie filmik, abyście nie przestraszyli się, że nic się nie generuje:

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *