[23:0] array [15:0][15:0]
→ [23:0] array [3:0][3:0]
, pentru a reduce riscul de confuzieTema are ca scop exersarea noțiunilor Verilog folosite pentru implementarea circuitelor secvențiale complexe, prin:
Implementați în Verilog un circuit secvențial sincron care ascunde un mesaj secret într-o imagine. Imaginile inițiale sunt reprezentate în spațiul de culoare RGB și au dimensiunea de 64×64 de elemente (pixeli), în care fiecare element are 24 de biți (8 biți 'R', 8 biți 'G' și 8 biți 'B'). Mesajul este de tip text, cu caractere ce aparțin setului extASCII (8 biți necesari pentru fiecare caracter). Pentru a putea cripta mesajul în imagine, va fi necesară efectuarea următoarelor etape de prelucrare:
În Anexă este descris procesul complet de prelucrare a unui bloc de $4$x$4$ pixeli, împreună cu detalii relevante pentru implementarea în Verilog.
Pentru implementare este necesară construirea unui automat cu stări finite care să modeleze cele 3 cerințe. Acest automat va comunica cu module adiționale, image
și base2_to_base3
. Descrierea detaliată a fiecărui modul se regăsește mai jos.
Modul deja implementat, el instanțiază modulul responsabil cu prelucrarea imaginii (process
), cel ce emulează imaginea încărcată în memorie (image
) și încarcă șirul ce urmează a fi codat. Totodată, acesta este responsabil pentru realizarea conexiunilor între cele
două module.
Modul deja implementat, responsabil cu încărcarea imaginii din fisier în memoria internă, acesta reprezintă interfața între fsm-ul implementat în process și imagine. Folosind semnalele de control, modulul process
poate citi sau scrie elemente individuale (pixeli).
Modulul respectă următoarea interfață:
module image ( input clk, input [image_size - 1:0] row, input [image_size - 1:0] col, input we, input [23:0] in, output[23:0] out
Descrierea semnalelor folosite de acest modul este următoarea:
clk
- semnal de ceas;row
- selectează un rând din imagine;col
- selectează o coloană din imagine;we
- write enable - activează scrierea în imagine la rândul și coloana date;in
- valoarea pixelului care va fi scris pe poziția dată;out
- valoarea pixelului care va fi citit de pe pozitia dată.Funcționalitatea modulului este următoarea:
row
și col
. Valoarea va fi disponibilă imediat pe semnalul out
.row
și col
, precum și semnalul we
. Valoarea prezentă pe semnalul in
va fi stocată în memorie la următorul ciclu de ceas.
top
pentru a vedea corespondența cu modulul process
Automatul cu stări finite care va modela comportamentul trebuie implementat în modulul process. Aici se vor efectua toate transformările necesare și se va instanția base2_to_base3, util în secvența de transformare a caracterelor în ultima etapă.
Modulul trebuie să respecte următoarea interfață:
module process ( input clk, input [23:0] in_pix, input [8*512-1:0] hiding_string, output [5:0] row, col, output out_we, output [23:0] out_pix, output gray_done, output compress_done, output encode_done
Descrierea semnalelor folosite de acest modul este următoarea:
clk
- semnal de ceas;in_pix
- valoarea pixelului de pe poziția [row, col] din imaginea de intrare (R 23:16; G 15:8; B 7:0);hiding_string
- șirul care trebuie codat;row
, col
- selectează un pixel din imagine din poziția (row, col), atât pentru citire, cât și pentru scriere;out_we
- activează scrierea pentru imaginea de ieșire (write enable);out_pix
- valoarea pixelului care va fi scrisa in imaginea de iesire pe pozitia [row, col] (R 23:16; G 15:8; B 7:0);gray_done
- semnaleaza terminarea actiunii de transformare în grayscale (activ pe 1);compress_done
- semnalează terminarea acțiunii de compresie (activ pe 1);encode_done
- semnalează terminarea acțiunii de codare (activ pe 1).
Modulul process va interacționa cu modulul image
pentru operațiile de citire și scriere a imaginii și cu modulul base2_to_base3
pentru transformarea caracterelor într-un șir compatibil operației de codare. Ambele module sunt deja implementate în scheletul temei.
output reg
este permisă exclusiv pentru acest modul.
Modul deja implementat, responsabil cu executarea algoritmului de transformare din baza 2 în baza 3.
Modulul are următoarea interfață:
module base2_to_base3 ( output [31 : 0] base3_no, output done, input [15 : 0] base2_no, input en, input clk);
Descrierea semnalelor folosite de acest modul este următoarea:
base3_no
- valoarea numărului exprimată în baza 3 - fiecare cifra este codată pe 2 biți; urmărește exemplul din Anexă pentru mai multe detalii.done
- semnal ce marchează sfârșitul conversiei; acesta trebuie asertat în momentul în care pe portul de ieșire base3_no este prezentă valoarea finalăbase2_no
- numărul în baza 2 ce trebuie transformat în baza 3; acesta are sens să fie citit doar în momentul în care en are valoarea 1;en
- semnal ce marchează faptul că numărul prezent pe portul base2_no este valid și poate fi cititclk
- semnal de ceas
Pentru a-l putea folosi, intrarea base2_no
va fi setată și pe același ciclu de ceas semnalul en
va fi asertat. Ulterior, într-o altă stare, se va aștepta semnalul done, care va indica faptul că output-ul este valid și poate fi citit. Pentru o descriere detaliată, revedeți Tema 1.
[23:0] array [3:0][3:0]
, dacă considerați necesar; motivați folosirea lor.gray_done
, compress_done
și encode_done
trebuie să mențină valoarea HIGH timp de un ciclu de ceas pentru a putea fi luate în considerare de tester. În acest ciclu de ceas nu veți face alte procesări și nu veți începe rezolvarea următorului task.Punctajul inițial al checker-ului nu reprezintă punctajul final al temei. Acesta va fi acordat de către asistent, în urma analizei individuale a fiecărei implementări.
Dacă tema primește 0 puncte pe platforma vmchecker, se pot acorda maxim 2 pct pentru ideea de implementare, la latitudinea asistentului. Ideea și motivele pentru care nu funcționează trebuie documentate temeinic în README și/sau comentarii. Temele care au erori de compilare vor fi notate cu 0 puncte.
În anexă va fi prezentat un exemplu numeric pentru un bloc generic B, de dimensiune $4$x$4$, precum și detalii relevante pentru implementarea în Verilog.
Considerăm imaginea noastră de dimensiune $64$x$64$ pixeli, împărțită în blocuri de dimensiune $4$x$4$, pentru a putea efectua algoritmul de încapsulare a mesajului secret.
Pentru exemplificare considerăm primul bloc, format din intersecția primelor 4 rânduri cu primele 4 coloane. Valoarea minimă și valoarea maximă sunt marcate cu bold în figura de mai jos. Asupra lor se efectuează media aritmetică.
Ulterior transformării imaginii din RGB în grayscale, se trece la compresie. Dacă pentru operația anterioară împărțirea pe blocuri nu e necesară, pentru compresie este obligatorie considerarea blocurilor individuale. După citirea elementelor ( se poate citi un singur pixel / ciclu de ceas ) se calculează media $AVG$, variația $var$, se construiește matricea cu noile valori $L_m$ și $H_m$. Bitmap-ul (matricea ce marchează tipul noului pixel) este o etapă intermediară care poate să fie inclusă în implementare, pentru o lizibilitate mai bună a algoritmului, dar nu este obligatorie.
Ultima etapă presupune codarea mesajului în interiorul imaginii. Ordinea codării se consideră începând cu primul caracter de la final (LSB→MSB).
În fiecare bloc sunt codate 2 caractere (16 biți), întrucât folosirea a 3 caractere conduce la depășirea spațiului alocat.
Așadar, în primul bloc vor fi secretizate caracterele cu indicii [15:8] și [7:0], EA.
Caracterele se vor converti împreună din baza 2 în baza 3, folosind modulul base2_to_base3
, și vom folosi primele 14 cifre (fiecare cifră e codată pe 2 biți) pentru a le încapsula în imagine. Ordinea este LSB → MSB, așa cum este prezentat și în imagine. Pixelii marcați cu roșu se omit, deoarece ei vor reprezenta baza pentru decodarea mesajului.
Aceste operații se efectuează pentru toate caracterele: 512 caractere, câte 2 în fiecare bloc, întrucât lungimea șirului nu este definită.