Cours:De0NanoSoc : Différence entre versions
(→cross compilation) |
(→ov7670 et DDR) |
||
| (61 révisions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
| − | = | + | =schema= |
| − | + | [[Media:De0NanoTop.zip]] | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | = | + | =ov7670 et DDR= |
| − | |||
| − | + | [[Media:Ov7670.zip]] | |
| − | <source lang= | + | |
| − | + | <source lang=vhdl> | |
| − | + | library ieee; | |
| + | use ieee.std_logic_1164.all; | ||
| + | use ieee.numeric_std.all; | ||
| + | |||
| + | entity fpga_dma_rgb32_simple is | ||
| + | port ( | ||
| + | -- ============================================================ | ||
| + | -- Interface Système (Reliée à l'horloge du FPGA/HPS) | ||
| + | -- ============================================================ | ||
| + | clk : in std_logic; -- 50 MHz | ||
| + | reset_n : in std_logic; -- Reset Actif Bas | ||
| + | |||
| + | -- ============================================================ | ||
| + | -- Interface Avalon-MM Master (Vers le HPS SDRAM Controller) | ||
| + | -- ============================================================ | ||
| + | avm_address : out std_logic_vector(31 downto 0); | ||
| + | avm_write : out std_logic; | ||
| + | avm_writedata : out std_logic_vector(31 downto 0); | ||
| + | avm_byteenable : out std_logic_vector(3 downto 0); | ||
| + | avm_waitrequest : in std_logic; | ||
| + | |||
| + | -- ============================================================ | ||
| + | -- Interface Physique Caméra (Conduit vers les Pins) | ||
| + | -- ============================================================ | ||
| + | cam_pclk : in std_logic; -- Pixel Clock (~24 MHz) | ||
| + | cam_href : in std_logic; -- Ligne valide | ||
| + | cam_vsync : in std_logic; -- Nouvelle image | ||
| + | cam_data : in std_logic_vector(7 downto 0); -- Données brutes | ||
| − | + | -- Sortie horloge générée pour la caméra (25 MHz) | |
| − | + | cam_xclk : out std_logic | |
| + | ); | ||
| + | end entity; | ||
| − | + | architecture rtl of fpga_dma_rgb32_simple is | |
| − | |||
| − | + | -- ======================================================================== | |
| − | + | -- 1. DECLARATION DES COMPOSANTS IP | |
| − | + | -- ======================================================================== | |
| − | |||
| − | |||
| − | + | -- PLL (Doit correspondre à ton fichier pll.vhd) | |
| − | + | component pll is | |
| − | + | port ( | |
| + | refclk : in std_logic; | ||
| + | rst : in std_logic; | ||
| + | outclk_0 : out std_logic; | ||
| + | locked : out std_logic -- Ajouté suite à ta correction | ||
| + | ); | ||
| + | end component pll; | ||
| − | + | -- FIFO (Doit correspondre à ton fichier camera_fifo.vhd) | |
| − | + | component camera_fifo is | |
| − | + | port ( | |
| − | + | data : in std_logic_vector(15 downto 0); | |
| − | + | rdclk : in std_logic; | |
| − | + | rdreq : in std_logic; | |
| − | + | wrclk : in std_logic; | |
| − | + | wrreq : in std_logic; | |
| − | + | q : out std_logic_vector(15 downto 0); | |
| + | rdempty : out std_logic; | ||
| + | wrfull : out std_logic | ||
| + | ); | ||
| + | end component; | ||
| − | == | + | -- ======================================================================== |
| + | -- 2. SIGNAUX INTERNES | ||
| + | -- ======================================================================== | ||
| − | + | -- Configuration Mémoire | |
| − | + | constant BASE_ADDRESS : unsigned(31 downto 0) := x"30000000"; -- Adresse de départ dans la DDR | |
| − | + | -- QVGA (320x240) = 76,800 pixels. En 32 bits (4 octets) -> 307,200 octets. | |
| − | + | -- VGA (640x480) = 307,200 pixels. En 32 bits -> 1,228,800 octets. | |
| − | + | constant MAX_OFFSET : integer := 320 * 240 * 4; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | = | + | -- Signaux Capture (Domaine PCLK) |
| + | signal cam_high_byte : std_logic_vector(7 downto 0); | ||
| + | signal cam_toggle : std_logic := '0'; | ||
| + | signal fifo_data_in : std_logic_vector(15 downto 0); | ||
| + | signal fifo_wr_req : std_logic := '0'; | ||
| − | + | -- Signaux DMA (Domaine CLK 50MHz) | |
| − | + | signal fifo_data_out : std_logic_vector(15 downto 0); | |
| − | + | signal fifo_rd_req : std_logic; | |
| − | + | signal fifo_empty : std_logic; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | signal dma_addr : unsigned(31 downto 0) := BASE_ADDRESS; | |
| − | + | signal writing_active : std_logic := '0'; | |
| − | |||
| − | |||
| − | + | -- Synchro VSYNC (Passage de domaine PCLK -> CLK 50MHz) | |
| + | signal vsync_r1, vsync_r2 : std_logic; | ||
| + | signal vsync_edge : std_logic; | ||
| − | + | -- Reconstruction Pixel | |
| − | + | signal r, g, b : std_logic_vector(7 downto 0); | |
| − | |||
| + | begin | ||
| − | + | -- ======================================================================== | |
| − | + | -- 3. INSTANCIATION PLL (50MHz -> 25MHz) | |
| − | + | -- ======================================================================== | |
| − | + | u_pll : component pll | |
| − | + | port map ( | |
| − | + | refclk => clk, | |
| − | + | rst => not reset_n, -- Le reset système est actif bas, la PLL attend actif haut | |
| − | + | outclk_0 => cam_xclk, | |
| − | + | locked => open -- On laisse ouvert si on ne s'en sert pas pour une LED | |
| − | + | ); | |
| − | |||
| − | |||
| − | |||
| − | |||
| + | -- ======================================================================== | ||
| + | -- 4. LOGIQUE DE CAPTURE (Domaine PCLK) | ||
| + | -- ======================================================================== | ||
| + | process(cam_pclk) | ||
| + | begin | ||
| + | if rising_edge(cam_pclk) then | ||
| + | -- Si VSYNC actif ou pas de HREF, on reset la machine à états de capture | ||
| + | if cam_vsync = '1' or cam_href = '0' then | ||
| + | cam_toggle <= '0'; | ||
| + | fifo_wr_req <= '0'; | ||
| + | else | ||
| + | -- Si ligne valide | ||
| + | if cam_href = '1' then | ||
| + | cam_toggle <= not cam_toggle; | ||
| − | + | if cam_toggle = '0' then | |
| + | -- Premier octet reçu (MSB du RGB565) | ||
| + | cam_high_byte <= cam_data; | ||
| + | fifo_wr_req <= '0'; | ||
| + | else | ||
| + | -- Deuxième octet reçu (LSB) | ||
| + | -- On concatène pour former le pixel 16 bits | ||
| + | fifo_data_in <= cam_high_byte & cam_data; | ||
| + | fifo_wr_req <= '1'; -- On demande l'écriture dans la FIFO | ||
| + | end if; | ||
| + | end if; | ||
| + | end if; | ||
| + | end if; | ||
| + | end process; | ||
| + | -- ======================================================================== | ||
| + | -- 5. INSTANCIATION FIFO DUAL CLOCK | ||
| + | -- ======================================================================== | ||
| + | u_fifo : component camera_fifo | ||
| + | port map ( | ||
| + | -- Coté Ecriture (Caméra) | ||
| + | wrclk => cam_pclk, | ||
| + | data => fifo_data_in, | ||
| + | wrreq => fifo_wr_req, | ||
| + | wrfull => open, | ||
| − | == | + | -- Coté Lecture (Système Avalon) |
| + | rdclk => clk, | ||
| + | rdreq => fifo_rd_req, | ||
| + | q => fifo_data_out, | ||
| + | rdempty => fifo_empty | ||
| + | ); | ||
| + | -- ======================================================================== | ||
| + | -- 6. LOGIQUE DMA & AVALON (Domaine CLK 50MHz) | ||
| + | -- ======================================================================== | ||
| − | = | + | -- Détection du VSYNC dans le domaine 50MHz (pour reset l'adresse mémoire) |
| − | < | + | process(clk) |
| − | + | begin | |
| − | + | if rising_edge(clk) then | |
| − | + | vsync_r1 <= cam_vsync; | |
| − | + | vsync_r2 <= vsync_r1; | |
| + | end if; | ||
| + | end process; | ||
| + | -- Détection front montant VSYNC | ||
| + | vsync_edge <= '1' when (vsync_r1 = '1' and vsync_r2 = '0') else '0'; | ||
| − | + | -- Machine à états DMA | |
| − | + | process(clk, reset_n) | |
| − | + | begin | |
| − | + | if reset_n = '0' then | |
| − | + | dma_addr <= BASE_ADDRESS; | |
| − | + | writing_active <= '0'; | |
| − | + | fifo_rd_req <= '0'; | |
| − | < | ||
| − | + | elsif rising_edge(clk) then | |
| − | + | -- 1. Gestion du Reset Frame (VSYNC) | |
| − | + | -- Si la caméra commence une nouvelle image, on remet l'adresse au début | |
| − | + | if vsync_edge = '1' then | |
| − | + | dma_addr <= BASE_ADDRESS; | |
| − | + | end if; | |
| − | + | -- 2. Gestion de la fin d'écriture Avalon | |
| + | -- Si 'waitrequest' tombe à 0, l'écriture est validée par la DDR | ||
| + | if avm_waitrequest = '0' then | ||
| + | writing_active <= '0'; | ||
| + | end if; | ||
| − | + | -- 3. Lancement d'une nouvelle écriture | |
| − | + | -- Si on n'écrit pas ET que la FIFO n'est pas vide | |
| + | if writing_active = '0' and fifo_empty = '0' then | ||
| + | fifo_rd_req <= '1'; -- On "pop" un pixel de la FIFO | ||
| + | writing_active <= '1'; -- On lève le flag d'écriture pour Avalon | ||
| − | + | -- Calcul adresse suivante (4 octets par pixel 32 bits) | |
| + | if dma_addr < (BASE_ADDRESS + MAX_OFFSET) then | ||
| + | dma_addr <= dma_addr + 4; | ||
| + | else | ||
| + | dma_addr <= BASE_ADDRESS; -- Sécurité (bouclage) | ||
| + | end if; | ||
| + | else | ||
| + | fifo_rd_req <= '0'; | ||
| + | end if; | ||
| − | + | end if; | |
| − | + | end process; | |
| + | -- ======================================================================== | ||
| + | -- 7. CONVERSION DE DONNEES (RGB565 -> RGB32) | ||
| + | -- ======================================================================== | ||
| − | + | -- Sortie FIFO (16 bits) : R[15:11], G[10:5], B[4:0] | |
| + | -- Conversion vers 32 bits : Alpha(8) - R(8) - G(8) - B(8) | ||
| + | -- On décale les bits et on remplit les LSB avec des 0 | ||
| + | r <= fifo_data_out(15 downto 11) & "000"; | ||
| + | g <= fifo_data_out(10 downto 5) & "00"; | ||
| + | b <= fifo_data_out(4 downto 0) & "000"; | ||
| − | + | -- Mappage des sorties Avalon | |
| − | + | avm_address <= std_logic_vector(dma_addr); | |
| − | + | avm_byteenable <= "1111"; -- Ecriture sur 32 bits (4 octets) | |
| − | + | avm_write <= writing_active; | |
| − | + | -- Données : Alpha (Full Opaque) | Red | Green | Blue | |
| − | + | avm_writedata <= x"FF" & r & g & b; | |
| − | |||
| − | + | end architecture; | |
| − | + | </source> | |
| − | + | =Ecriture dans la DDR= | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | !!! ATTENTION : le bus avalon ne peut pas accéder à tout l'espace de la DDR | |
| − | + | à vérifier mais ne marche pas à l'@ 0x3f000000 | |
| − | + | utiliser une zone mémoire à l'@ 0x30000000 | |
| − | |||
| − | |||
| − | + | il faut autoriser l'accès avec : | |
| − | + | memtool mw -l 0xFFC25080 0x1F0 | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | // a supprimer | |
| − | + | *dans uboot | |
| − | + | <source lang=bash> | |
| − | + | mw 0xFFC25080 0x1F0 | |
| − | + | mw 0xFFC2505C 0xA | |
| + | </source> | ||
| + | *sur linux | ||
| + | <source lang=cpp> | ||
| + | memtool mw -l 0xFFC25080 0x1F0 | ||
| + | memtool mw -l 0xFFC2505C 0xA | ||
| + | </source> | ||
| − | |||
| − | |||
| − | + | https://www.reddit.com/r/FPGA/comments/12mg5su/having_issues_writing_data_from_fpga_to_hps_using/?tl=fr | |
| − | |||
| − | + | https://people.ece.cornell.edu/land/courses/ece5760/DE1_SOC/cv_5_HPS_tech_ref.pdf | |
| − | |||
| − | + | *fpga | |
| − | |||
| − | + | <source lang=vhdl> | |
| − | + | library ieee; | |
| − | + | use ieee.std_logic_1164.all; | |
| − | + | use ieee.numeric_std.all; | |
| − | + | entity fpga_dma_rgb32_simple is | |
| + | port ( | ||
| + | clk : in std_logic; | ||
| + | reset : in std_logic; | ||
| − | + | -- Avalon-MM master | |
| − | + | avm_address : out std_logic_vector(31 downto 0); | |
| − | + | avm_write : out std_logic; | |
| − | + | avm_writedata : out std_logic_vector(31 downto 0); | |
| + | avm_waitrequest : in std_logic | ||
| + | ); | ||
| + | end entity; | ||
| + | architecture rtl of fpga_dma_rgb32_simple is | ||
| − | + | constant BASE_ADDR : unsigned(31 downto 0) := x"3FB00000"; | |
| + | constant WIDTH : integer := 640; | ||
| + | constant HEIGHT : integer := 480; | ||
| + | constant TOTAL_PIXELS : integer := WIDTH * HEIGHT; -- 307200 | ||
| − | + | signal pixel_index : integer range 0 to TOTAL_PIXELS-1 := 0; | |
| − | + | signal addr : unsigned(31 downto 0); | |
| + | signal write_reg : std_logic := '0'; | ||
| − | + | -- Pattern RGB32 (XRGB8888) | |
| + | signal r, g, b : unsigned(7 downto 0); | ||
| + | signal pixel32 : unsigned(31 downto 0); | ||
| − | + | begin | |
| − | |||
| − | |||
| − | |||
| − | + | -------------------------------------------------------------------- | |
| − | + | -- Générateur simple de pattern | |
| + | -------------------------------------------------------------------- | ||
| + | r <= to_unsigned((pixel_index mod WIDTH) * 255 / WIDTH, 8); | ||
| + | g <= to_unsigned((pixel_index / WIDTH) * 255 / HEIGHT, 8); | ||
| + | b <= to_unsigned(128, 8); | ||
| − | + | -- pixel32 <= x"00" & r & g & b; -- XRGB8888 | |
| − | + | pixel32 <= x"AAAAAAAA"; -- XRGB8888 | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | avm_writedata <= std_logic_vector(pixel32); | |
| − | + | -------------------------------------------------------------------- | |
| − | + | -- Adresse courante | |
| + | -------------------------------------------------------------------- | ||
| + | addr <= BASE_ADDR + to_unsigned(pixel_index * 4, 32); | ||
| − | < | + | avm_address <= std_logic_vector(addr); |
| + | avm_write <= write_reg; | ||
| + | -------------------------------------------------------------------- | ||
| + | -- FSM simple | ||
| + | -------------------------------------------------------------------- | ||
| + | process(clk) | ||
| + | begin | ||
| + | if rising_edge(clk) then | ||
| + | if avm_waitrequest = '0' then | ||
| + | write_reg <= '1'; | ||
| − | = | + | pixel_index <= pixel_index + 1; |
| − | |||
| − | |||
| − | |||
| − | |||
| − | = | + | -- boucle image |
| + | if pixel_index = TOTAL_PIXELS-1 then | ||
| + | pixel_index <= 0; | ||
| + | end if; | ||
| + | else | ||
| + | write_reg <= '0'; | ||
| + | end if; | ||
| + | end if; | ||
| + | end process; | ||
| − | + | end architecture; | |
| − | + | </source> | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | =I2C= | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | [[Media:DE0-Nano-SoC_Schematic.pdf]] | |
| − | * | + | *on utilisera le bus i2c1 |
| − | * | + | *la vitesse est de 100kHz |
| − | ** | + | **dans le fichier device-tree |
| − | ** | + | **modifier speed-mode = <0x00> |
| + | ***0x00 = Standard mode (100 kHz) | ||
| + | ***0x01 = Fast mode (400 kHz) | ||
| + | *broches | ||
| + | **sur le connecteur LTC | ||
| + | **ATTENTION : il faut mettre des résistances de Pull-Up !!! | ||
Version actuelle datée du 4 février 2026 à 11:24
schema
ov7670 et DDR
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fpga_dma_rgb32_simple is
port (
-- ============================================================
-- Interface Système (Reliée à l'horloge du FPGA/HPS)
-- ============================================================
clk : in std_logic; -- 50 MHz
reset_n : in std_logic; -- Reset Actif Bas
-- ============================================================
-- Interface Avalon-MM Master (Vers le HPS SDRAM Controller)
-- ============================================================
avm_address : out std_logic_vector(31 downto 0);
avm_write : out std_logic;
avm_writedata : out std_logic_vector(31 downto 0);
avm_byteenable : out std_logic_vector(3 downto 0);
avm_waitrequest : in std_logic;
-- ============================================================
-- Interface Physique Caméra (Conduit vers les Pins)
-- ============================================================
cam_pclk : in std_logic; -- Pixel Clock (~24 MHz)
cam_href : in std_logic; -- Ligne valide
cam_vsync : in std_logic; -- Nouvelle image
cam_data : in std_logic_vector(7 downto 0); -- Données brutes
-- Sortie horloge générée pour la caméra (25 MHz)
cam_xclk : out std_logic
);
end entity;
architecture rtl of fpga_dma_rgb32_simple is
-- ========================================================================
-- 1. DECLARATION DES COMPOSANTS IP
-- ========================================================================
-- PLL (Doit correspondre à ton fichier pll.vhd)
component pll is
port (
refclk : in std_logic;
rst : in std_logic;
outclk_0 : out std_logic;
locked : out std_logic -- Ajouté suite à ta correction
);
end component pll;
-- FIFO (Doit correspondre à ton fichier camera_fifo.vhd)
component camera_fifo is
port (
data : in std_logic_vector(15 downto 0);
rdclk : in std_logic;
rdreq : in std_logic;
wrclk : in std_logic;
wrreq : in std_logic;
q : out std_logic_vector(15 downto 0);
rdempty : out std_logic;
wrfull : out std_logic
);
end component;
-- ========================================================================
-- 2. SIGNAUX INTERNES
-- ========================================================================
-- Configuration Mémoire
constant BASE_ADDRESS : unsigned(31 downto 0) := x"30000000"; -- Adresse de départ dans la DDR
-- QVGA (320x240) = 76,800 pixels. En 32 bits (4 octets) -> 307,200 octets.
-- VGA (640x480) = 307,200 pixels. En 32 bits -> 1,228,800 octets.
constant MAX_OFFSET : integer := 320 * 240 * 4;
-- Signaux Capture (Domaine PCLK)
signal cam_high_byte : std_logic_vector(7 downto 0);
signal cam_toggle : std_logic := '0';
signal fifo_data_in : std_logic_vector(15 downto 0);
signal fifo_wr_req : std_logic := '0';
-- Signaux DMA (Domaine CLK 50MHz)
signal fifo_data_out : std_logic_vector(15 downto 0);
signal fifo_rd_req : std_logic;
signal fifo_empty : std_logic;
signal dma_addr : unsigned(31 downto 0) := BASE_ADDRESS;
signal writing_active : std_logic := '0';
-- Synchro VSYNC (Passage de domaine PCLK -> CLK 50MHz)
signal vsync_r1, vsync_r2 : std_logic;
signal vsync_edge : std_logic;
-- Reconstruction Pixel
signal r, g, b : std_logic_vector(7 downto 0);
begin
-- ========================================================================
-- 3. INSTANCIATION PLL (50MHz -> 25MHz)
-- ========================================================================
u_pll : component pll
port map (
refclk => clk,
rst => not reset_n, -- Le reset système est actif bas, la PLL attend actif haut
outclk_0 => cam_xclk,
locked => open -- On laisse ouvert si on ne s'en sert pas pour une LED
);
-- ========================================================================
-- 4. LOGIQUE DE CAPTURE (Domaine PCLK)
-- ========================================================================
process(cam_pclk)
begin
if rising_edge(cam_pclk) then
-- Si VSYNC actif ou pas de HREF, on reset la machine à états de capture
if cam_vsync = '1' or cam_href = '0' then
cam_toggle <= '0';
fifo_wr_req <= '0';
else
-- Si ligne valide
if cam_href = '1' then
cam_toggle <= not cam_toggle;
if cam_toggle = '0' then
-- Premier octet reçu (MSB du RGB565)
cam_high_byte <= cam_data;
fifo_wr_req <= '0';
else
-- Deuxième octet reçu (LSB)
-- On concatène pour former le pixel 16 bits
fifo_data_in <= cam_high_byte & cam_data;
fifo_wr_req <= '1'; -- On demande l'écriture dans la FIFO
end if;
end if;
end if;
end if;
end process;
-- ========================================================================
-- 5. INSTANCIATION FIFO DUAL CLOCK
-- ========================================================================
u_fifo : component camera_fifo
port map (
-- Coté Ecriture (Caméra)
wrclk => cam_pclk,
data => fifo_data_in,
wrreq => fifo_wr_req,
wrfull => open,
-- Coté Lecture (Système Avalon)
rdclk => clk,
rdreq => fifo_rd_req,
q => fifo_data_out,
rdempty => fifo_empty
);
-- ========================================================================
-- 6. LOGIQUE DMA & AVALON (Domaine CLK 50MHz)
-- ========================================================================
-- Détection du VSYNC dans le domaine 50MHz (pour reset l'adresse mémoire)
process(clk)
begin
if rising_edge(clk) then
vsync_r1 <= cam_vsync;
vsync_r2 <= vsync_r1;
end if;
end process;
-- Détection front montant VSYNC
vsync_edge <= '1' when (vsync_r1 = '1' and vsync_r2 = '0') else '0';
-- Machine à états DMA
process(clk, reset_n)
begin
if reset_n = '0' then
dma_addr <= BASE_ADDRESS;
writing_active <= '0';
fifo_rd_req <= '0';
elsif rising_edge(clk) then
-- 1. Gestion du Reset Frame (VSYNC)
-- Si la caméra commence une nouvelle image, on remet l'adresse au début
if vsync_edge = '1' then
dma_addr <= BASE_ADDRESS;
end if;
-- 2. Gestion de la fin d'écriture Avalon
-- Si 'waitrequest' tombe à 0, l'écriture est validée par la DDR
if avm_waitrequest = '0' then
writing_active <= '0';
end if;
-- 3. Lancement d'une nouvelle écriture
-- Si on n'écrit pas ET que la FIFO n'est pas vide
if writing_active = '0' and fifo_empty = '0' then
fifo_rd_req <= '1'; -- On "pop" un pixel de la FIFO
writing_active <= '1'; -- On lève le flag d'écriture pour Avalon
-- Calcul adresse suivante (4 octets par pixel 32 bits)
if dma_addr < (BASE_ADDRESS + MAX_OFFSET) then
dma_addr <= dma_addr + 4;
else
dma_addr <= BASE_ADDRESS; -- Sécurité (bouclage)
end if;
else
fifo_rd_req <= '0';
end if;
end if;
end process;
-- ========================================================================
-- 7. CONVERSION DE DONNEES (RGB565 -> RGB32)
-- ========================================================================
-- Sortie FIFO (16 bits) : R[15:11], G[10:5], B[4:0]
-- Conversion vers 32 bits : Alpha(8) - R(8) - G(8) - B(8)
-- On décale les bits et on remplit les LSB avec des 0
r <= fifo_data_out(15 downto 11) & "000";
g <= fifo_data_out(10 downto 5) & "00";
b <= fifo_data_out(4 downto 0) & "000";
-- Mappage des sorties Avalon
avm_address <= std_logic_vector(dma_addr);
avm_byteenable <= "1111"; -- Ecriture sur 32 bits (4 octets)
avm_write <= writing_active;
-- Données : Alpha (Full Opaque) | Red | Green | Blue
avm_writedata <= x"FF" & r & g & b;
end architecture;
Ecriture dans la DDR
!!! ATTENTION : le bus avalon ne peut pas accéder à tout l'espace de la DDR à vérifier mais ne marche pas à l'@ 0x3f000000 utiliser une zone mémoire à l'@ 0x30000000
il faut autoriser l'accès avec : memtool mw -l 0xFFC25080 0x1F0
// a supprimer
- dans uboot
mw 0xFFC25080 0x1F0
mw 0xFFC2505C 0xA
- sur linux
memtool mw -l 0xFFC25080 0x1F0
memtool mw -l 0xFFC2505C 0xA
https://people.ece.cornell.edu/land/courses/ece5760/DE1_SOC/cv_5_HPS_tech_ref.pdf
- fpga
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fpga_dma_rgb32_simple is
port (
clk : in std_logic;
reset : in std_logic;
-- Avalon-MM master
avm_address : out std_logic_vector(31 downto 0);
avm_write : out std_logic;
avm_writedata : out std_logic_vector(31 downto 0);
avm_waitrequest : in std_logic
);
end entity;
architecture rtl of fpga_dma_rgb32_simple is
constant BASE_ADDR : unsigned(31 downto 0) := x"3FB00000";
constant WIDTH : integer := 640;
constant HEIGHT : integer := 480;
constant TOTAL_PIXELS : integer := WIDTH * HEIGHT; -- 307200
signal pixel_index : integer range 0 to TOTAL_PIXELS-1 := 0;
signal addr : unsigned(31 downto 0);
signal write_reg : std_logic := '0';
-- Pattern RGB32 (XRGB8888)
signal r, g, b : unsigned(7 downto 0);
signal pixel32 : unsigned(31 downto 0);
begin
--------------------------------------------------------------------
-- Générateur simple de pattern
--------------------------------------------------------------------
r <= to_unsigned((pixel_index mod WIDTH) * 255 / WIDTH, 8);
g <= to_unsigned((pixel_index / WIDTH) * 255 / HEIGHT, 8);
b <= to_unsigned(128, 8);
-- pixel32 <= x"00" & r & g & b; -- XRGB8888
pixel32 <= x"AAAAAAAA"; -- XRGB8888
avm_writedata <= std_logic_vector(pixel32);
--------------------------------------------------------------------
-- Adresse courante
--------------------------------------------------------------------
addr <= BASE_ADDR + to_unsigned(pixel_index * 4, 32);
avm_address <= std_logic_vector(addr);
avm_write <= write_reg;
--------------------------------------------------------------------
-- FSM simple
--------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if avm_waitrequest = '0' then
write_reg <= '1';
pixel_index <= pixel_index + 1;
-- boucle image
if pixel_index = TOTAL_PIXELS-1 then
pixel_index <= 0;
end if;
else
write_reg <= '0';
end if;
end if;
end process;
end architecture;
I2C
Media:DE0-Nano-SoC_Schematic.pdf
- on utilisera le bus i2c1
- la vitesse est de 100kHz
- dans le fichier device-tree
- modifier speed-mode = <0x00>
- 0x00 = Standard mode (100 kHz)
- 0x01 = Fast mode (400 kHz)
- broches
- sur le connecteur LTC
- ATTENTION : il faut mettre des résistances de Pull-Up !!!