§ Код модуля
Опорная частота 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