Моя сущность pixel_controller во время симуляции работает (я думаю) правильно, но выводит неправильно, а точнее выводит std_logic_vector «форсирования неизвестных» вместо правильных битов.
Терминология: Charactor: линия пикселейиз 8 битов символа шрифта.
Я разрабатываю контроллер VGA, который печатает символы на экране.Поэтому после написания (копирования) работающей сущности font_ROM (был создан и протестирован тестовый стенд), я начал работать над логикой, которая будет печатать символы, хранящиеся (пока) в строке;эта логика называется Pixel Controller.
Мой pixel_controller получает сигналы от vga_controller и выводит значения rgb в течение времени screen_enable.
Важно знать, что для ограничения синхронизации контроллер пикселей запрашивает вектор символов, прежде чем они понадобятся, например: когда печатается символ N, контроллер пикселей запрашивает font_ROM для символа N + 1, чтобы на цикле N + 1 этот символ был готов.
Когда векторы символов запрашиваются в тестовом стенде для font_rom, все работает отлично, но когда то же самоесимволы запрашиваются в реализованном font_rom (внутри pixel_controller), заставляя вместо этого генерироваться неизвестные, и только для символов, содержащих хотя бы один 1.
pixel_controller.vhd
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;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity pixel_controller is
Generic(
HORIZONTAL_PIXELS : INTEGER := 640;
VERTICAL_PIXELS : INTEGER := 480;
ADDR_WIDTH : INTEGER := 11; -- address width 2^11-1 = addressable memory
DATA_WIDTH : INTEGER := 8; -- data width no of pixel reperesenting the character width
CHAR_WIDTH : INTEGER := DATA_WIDTH;
CHAR_HEIGHT : INTEGER := 16;
CHAR_IN_ALPHABET : INTEGER := 127;
BITS_ADDRESSING_ALPHABET : INTEGER := 7; --ln(CHAR_IN_ALPHABET)
BITS_ADDRESSING_CHAR_HEIGHT: INTEGER := 4; --ln(CHAR_HEIGHT)
);
Port (
clk : in STD_LOGIC;
resetn : in STD_LOGIC;
disp_en : in STD_LOGIC;
pixel_col : in INTEGER;
pixel_row : in INTEGER;
VGA_R : out STD_LOGIC_VECTOR(3 DOWNTO 0);
VGA_G : out STD_LOGIC_VECTOR(3 DOWNTO 0);
VGA_B : out STD_LOGIC_VECTOR(3 DOWNTO 0)
);
end pixel_controller;
architecture Behavioral of pixel_controller is
type DATA_ARRAY is array (integer range <>) OF INTEGER RANGE 0 TO 127;
signal stream : DATA_ARRAY (0 to 127):= ( --its the srteam
0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,
51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,69,70,
71,72,73,74,75,76,77,78,79,80,
81,82,83,84,85,86,87,88,89,90,
91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107,108,109,110,
111,112,113,114,115,116,117,118,119,120,
121,122,123,124,125,126,127
);
signal font_address : STD_LOGIC_VECTOR(ADDR_WIDTH-1 DOWNTO 0);
signal font_out : STD_LOGIC_VECTOR(DATA_WIDTH-1 DOWNTO 0);
signal char_max_col : INTEGER := HORIZONTAL_PIXELS/data_width; --max number of characters IN A row printable
signal char_max_row : INTEGER := VERTICAL_PIXELS/data_width; --max number of text rows printable
signal char_VGA_col: INTEGER RANGE 0 TO HORIZONTAL_PIXELS/data_width; -- since we think in characters it's usefull to know in witch character column we are
signal char_VGA_row : INTEGER RANGE 0 TO VERTICAL_PIXELS/data_width; -- since we think in characters it's usefull to know in witch character row we are
begin
f_rom: entity work.fonts_rom(Behavioral)
port map(
clk =>clk,
addr=>font_address,
data_out => font_out
);
char_VGA_col <= pixel_col/CHAR_WIDTH; --with this we know in witch character colum we are
char_VGA_row <= pixel_row/CHAR_HEIGHT; --with this we know on which line of text we are
GET_FUT_PIX_VAL: process (resetn,char_VGA_col) is -- at clock N get the pixel value for process N+1
-- the process depends on the char_VGA_Col since
-- char_VGA_row cannot change previously to it
variable requested_character : INTEGER := 0; -- character obtained by stream
variable charactor_line : INTEGER:= 0; -- which line of pixels of a specific character is requested
begin
if resetn = '0' then -- async reset
font_address <= (others => '0');
font_out <= (others =>'0');
requested_character := 0;
charactor_line := 0;
elsif char_VGA_col /= char_VGA_col'LAST_VALUE then -- if actual value is different then the previous one
-- process starts every CHAR_WIDTH pixel printed
if(char_VGA_col + char_max_col*char_VGA_row < 126) -- my string contains 127 chars
requested_character := stream(char_max_col*char_VGA_row + char_VGA_col + 1); -- note the + 1: the requested value is for the future pixel_col
-- the value will be accessible at a clk delay (not VGA_CLK)
charactor_line := pixel_row MOD CHAR_HEIGHT; -- which charactor line of the character we are printing
font_address <= std_logic_vector(to_unsigned(requested_character,BITS_ADDRESSING_ALPHABET))
& std_logic_vector(to_unsigned(charactor_line,BITS_ADDRESSING_CHAR_HEIGHT));
end if; -- NB values will be requested even during the back porch pulse and front porch of v_sync
end if;
end process;
PRINT_PIXEL: process (pixel_col) is -- pixel_col is effectively the same as CLK TODO:see if the latency is problematic
begin
if (font_out( (pixel_col) MOD CHAR_WIDTH ) = '0' AND disp_en = '1') then -- HERE COULD BE PRINTED ALL IN REVERS ORDER LOOK AT HOW FONT_OUT IS DEFINED
VGA_R <= (others => '1'); -- inverse coloring: white on black
VGA_G <= (others => '1');
VGA_B <= (others => '1');
else
VGA_R <= (others => '0');
VGA_G <= (others => '0');
VGA_B <= (others => '0');
end if;
end process;
testbench_pixel_controller.vhd
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;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
use work.commonPak.ALL;
entity pixel_controller_testbench is
-- Port ( );
end pixel_controller_testbench;
architecture Behavioral of pixel_controller_testbench is
component clk_wiz_0 is --takes 100MHZ and returns 25MHz
port(
clk_in1 : in STD_LOGIC;
resetn : in STD_LOGIC;
CLK_VGA : out STD_LOGIC
);
end component;
component pixel_controller is
Generic(
HORIZONTAL_PIXELS : INTEGER := 640;
VERTICAL_PIXELS : INTEGER := 480;
ADDR_WIDTH : INTEGER := 11;
DATA_WIDTH : INTEGER := 8;
CHAR_WIDTH : INTEGER := DATA_WIDTH;
CHAR_HEIGHT : INTEGER := 16;
CHAR_IN_ALPHABET : INTEGER := 127;
BITS_ADDRESSING_ALPHABET : INTEGER := 7; --ln(CHAR_IN_ALPHABET)
BITS_ADDRESSING_CHAR_HEIGHT: INTEGER := 4; --ln(CHAR_HEIGHT)
);
port(
clk : in STD_LOGIC;
resetn : in STD_LOGIC;
disp_en : in STD_LOGIC;
pixel_col : in INTEGER;
pixel_row : in INTEGER;
VGA_R : out STD_LOGIC_VECTOR(3 DOWNTO 0);
VGA_G : out STD_LOGIC_VECTOR(3 DOWNTO 0);
VGA_B : out STD_LOGIC_VECTOR(3 DOWNTO 0)
);
end component;
component vga_controller is
generic(
h_pulse : INTEGER :=96;
h_bkprch : INTEGER :=48;
h_pixels : INTEGER :=640;
h_frprch : INTEGER :=16;
h_pol : STD_LOGIC :='0';
v_pulse : INTEGER :=2;
v_bkprch : INTEGER :=33;
v_pixels : INTEGER :=480;
v_frprch : INTEGER :=10;
v_pol : STD_LOGIC :='1'
);
port(
pixel_clk : in STD_LOGIC;
res : in STD_LOGIC;
h_sync : out STD_LOGIC;
v_sync : out STD_LOGIC;
disp_en : out STD_LOGIC;
column : out INTEGER;
row : out INTEGER
);
end component;
signal CLK100HZ,CPU_RESETN,VGA_HS,VGA_VS,CLK_25,disp_en : STD_LOGIC;
signal column,row : INTEGER;
signal VGA_R,VGA_G,VGA_B : STD_LOGIC_VECTOR (3 DOWNTO 0);
begin
clk_wiz: clk_wiz_0 port map(
clk_in1 => CLK100HZ,
resetn => CPU_RESETN,
CLK_VGA =>CLK_25
);
vga_c: vga_controller port map(
pixel_clk => CLK_25,
res => CPU_RESETN,
h_sync => VGA_HS,
v_sync => VGA_VS,
disp_en => disp_en,
column => column,
row => row
);
px_ctrl: pixel_controller port map(
clk => CLK100HZ,
resetn => CPU_RESETN,
disp_en => disp_en,
pixel_col => column,
pixel_row => row,
VGA_R => VGA_R,
VGA_G => VGA_G,
VGA_B => VGA_B
);
CLK:process begin
CLK100HZ <= '0';
wait for 5ns;
CLK100HZ <= '1';
wait for 5ns;
end process;
process begin
CPU_RESETN <= '0';
wait for 15ns;
CPU_RESETN <= '1';
wait;
end process;
end Behavioral;
VGA_controller.vhd и font_ROM.vhd (ASCII) - это файлы, которые "всегда" везде одинаковы.
На пикселе 56 первой строки должно отображаться значение 07 характера и запрашиваться значение 08 характера.Запрос выполняется, и после clk значение должно быть «11111111», иначе xff, вместо этого я получаю кучу «X».
Здесь визуализация последовательности
- clk100 - это система clk, с которой выполняются запросы шрифтов
- clk25 - это VGA clk, с помощью которого рисуются пиксели.