§ Код модуля

Опорная частота 25 мгц, 640 x 400.
Карта памяти - 4Кб это знакоместа; 4Кб знакогенератор 8 x 16
1/* verilator lint_off WIDTH */
2
3module text
4(
5    // Опорная частота 25 мгц
6    input   wire        clock,
7
8    // Выходные данные
9    output  reg  [3:0]  r,       // 4 бит на красный
10    output  reg  [3:0]  g,       // 4 бит на зеленый
11    output  reg  [3:0]  b,       // 4 бит на синий
12    output  wire        hs,      // горизонтальная развертка
13    output  wire        vs,      // вертикальная развертка
14
15    // Доступ к памяти
16    output  reg  [11:0] char_address,
17    output  reg  [11:0] font_address,
18    input   wire [ 7:0] char_data,
19    input   wire [ 7:0] font_data,
20
21    // Внешний интерфейс
22    input   wire [10:0] cursor   // Положение курсора от 0 до 2047
23);
24
25// ---------------------------------------------------------------------
26// Тайминги для горизонтальной|вертикальной развертки (640x400)
27// ---------------------------------------------------------------------
28
29localparam
30
31    hz_visible = 640, vt_visible = 400,
32    hz_front   = 16,  vt_front   = 12,
33    hz_sync    = 96,  vt_sync    = 2,
34    hz_back    = 48,  vt_back    = 35,
35    hz_whole   = 800, vt_whole   = 449;
36
37assign hs = x  < (hz_back + hz_visible + hz_front); // NEG.
38assign vs = y >= (vt_back + vt_visible + vt_front); // POS.
39// ---------------------------------------------------------------------
40wire        xmax = (x == hz_whole - 1);
41wire        ymax = (y == vt_whole - 1);
42reg  [10:0] x    = 0;
43reg  [10:0] y    = 0;
44wire [10:0] X    = x - hz_back + 8; // X=[0..639]
45wire [ 9:0] Y    = y - vt_back;     // Y=[0..399]
46// ---------------------------------------------------------------------
47reg         flash;
48reg  [ 7:0] attr;
49reg  [ 7:0] char;
50reg  [23:0] timer;
51// ---------------------------------------------------------------------
52
53wire [10:0] id = X[9:3] + (Y[8:4] * 80);
54wire        maskbit = (char[ ~X[2:0] ]) | (flash && (id == cursor + 1) && Y[3:0] >= 14);
55wire [ 3:0] kcolor = maskbit ? (attr[7] & flash ? attr[6:4] : attr[3:0]) : attr[6:4];
56wire [15:0] color =
57
58    kcolor == 4'h0 ? 12'h111 : // 0 Черный (почти)
59    kcolor == 4'h1 ? 12'h008 : // 1 Синий (темный)
60    kcolor == 4'h2 ? 12'h080 : // 2 Зеленый (темный)
61    kcolor == 4'h3 ? 12'h088 : // 3 Бирюзовый (темный)
62    kcolor == 4'h4 ? 12'h800 : // 4 Красный (темный)
63    kcolor == 4'h5 ? 12'h808 : // 5 Фиолетовый (темный)
64    kcolor == 4'h6 ? 12'h880 : // 6 Коричневый
65    kcolor == 4'h7 ? 12'hCCC : // 7 Серый -- тут что-то не то
66    kcolor == 4'h8 ? 12'h888 : // 8 Темно-серый
67    kcolor == 4'h9 ? 12'h00F : // 9 Синий (темный)
68    kcolor == 4'hA ? 12'h0F0 : // 10 Зеленый
69    kcolor == 4'hB ? 12'h0FF : // 11 Бирюзовый
70    kcolor == 4'hC ? 12'hF00 : // 12 Красный
71    kcolor == 4'hD ? 12'hF0F : // 13 Фиолетовый
72    kcolor == 4'hE ? 12'hFF0 : // 14 Желтый
73                     12'hFFF;  // 15 Белый
74
75// Вывод видеосигнала
76always @(posedge clock) begin
77
78    // Кадровая развертка
79    x <= xmax ?         0 : x + 1;
80    y <= xmax ? (ymax ? 0 : y + 1) : y;
81
82    // Вывод окна видеоадаптера
83    if (x >= hz_back && x < hz_visible + hz_back &&
84        y >= vt_back && y < vt_visible + vt_back)
85    begin
86         {r, g, b} <= color;
87    end
88    else {r, g, b} <= 12'h000;
89
90    // Извлечение текущей маски
91    case (X[2:0])
92
93        0: begin char_address <= {id[10:0], 1'b0}; end
94        2: begin font_address <= {char_data, Y[3:0]}; end
95        4: begin char_address <= {id[10:0], 1'b1}; end
96        7: begin {attr, char} <= {char_data, font_data}; end
97
98    endcase
99
100    // Каждые 0,5 секунды перебрасывается регистр flash
101    if (timer == 12500000) begin
102        timer <= 0;
103        flash <= ~flash;
104    end else
105        timer <= timer + 1;
106
107end
108
109endmodule