§ Небольшое описание
Этот видеоадаптер, это вывод символов на экран 80 на 25, для OMDAZZ CYCLONE IV. Так как на этой отладочной плате установлено только 3 бита для цвета (R,G,B), то он может выводить только 8 цветов, к сожалению. А внешний переходник мне подключать что-то лень.
Сначала надо определиться с тем, что подключать. Для вывода символов 8x16 нам потребуется хранить знакоместа для них, и так как символов 256, и на каждый символ тратится по 16 строк (по 8 бит одна строка), то необходимо 4096 байт для хранения знакомест. Аналогично, для хранения номеров знакомест потребуется 80 на 25 = 2000 байт, и напротив каждого существует атрибут, что дает по итогу 4000 байт (без 96 байт в конце).
Как объявить блоки памяти в TOP модуле, всем понятно. Просто и легко.
»
Diяect download шаблон of проект
wire [11:0] ram_a, rom_a;
wire [ 7:0] ram_i, rom_i;
wire [10:0] cursor;
video U1
(
.clock (clock_25),
.r (VGA_R),
.g (VGA_G),
.b (VGA_B),
.hs (VGA_HS),
.vs (VGA_VS),
.ram_a (ram_a),
.rom_a (rom_a),
.ram_i (ram_i),
.rom_i (rom_i),
.cursor (cursor)
);
vram U2
(
.clock (~clock_25),
.a (ram_a),
.q (ram_i)
);
vrom U3
(
.clock (~clock_25),
.a (rom_a),
.q (rom_i)
);
§ Сам модуль
Теперь приведу код самого модуля, который выводит на экран необходимые символы. Он, как и все остальное с видеоадаптерами, крайне прост и тратит всего лишь 3 такта (из 8 тактов на 1 символ), чтобы извлечь.
- Номер знакоместа
- Атрибут
- Значение знакоместа
Ниже приведен полный код.
module video
(
input clock,
output reg r,
output reg g,
output reg b,
output hs,
output vs,
output reg [11:0] ram_a,
output reg [11:0] rom_a,
input [ 7:0] ram_i,
input [ 7:0] rom_i,
input [10:0] cursor
);
parameter
hzv = 640, hzb = 48, hzs = 96, hzf = 16, hzw = 800,
vtv = 400, vtb = 35, vts = 2, vtf = 12, vtw = 449;
assign hs = x < (hzb + hzv + hzf);
assign vs = y < (vtb + vtv + vtf);
reg [ 9:0] x = 0;
reg [ 9:0] y = 0;
wire [ 9:0] rx = x - hzb + 8;
wire [ 9:0] ry = y - vtb;
wire xmax = (x == hzw - 1);
wire ymax = (y == vtw - 1);
wire show = (x >= hzb && x < hzb + hzv) && (y >= vtb && y < vtb + vtv);
reg flash;
reg [ 7:0] mask, attr;
reg [22:0] incr;
wire [10:0] curr = rx[9:3] + ry[9:4]*80;
wire cbit = mask[ ~rx[2:0] ];
wire cur = flash && (curr == cursor+1 && ry[3:0] >= 14);
wire blink = (flash & attr[7]) || (attr[7] == 1'b0);
always @(posedge clock) begin
{r, b, g} <= 3'b000;
x <= xmax ? 0 : x + 1;
y <= xmax ? (ymax ? 0 : y + 1) : y;
case (rx[2:0])
5: begin ram_a <= 2*curr; end
6: begin rom_a <= {ram_i, ry[3:0]};
ram_a <= ram_a + 1; end
7: begin {mask, attr} <= {rom_i, ram_i}; end
endcase
if (show) begin {r,g,b} <= ((cbit && blink) || cur ? attr[2:0] : attr[6:4]); end
incr <= (incr == 6250000) ? 0 : incr+1;
flash <= !incr ? ~flash : flash;
end
endmodule