§ Код

Это общий код к модулю пиксельному процессору ZX Spectrum. Используется адрес от $4000 до $5AFF включительно.
1/* verilator lint_off WIDTH */
2/* verilator lint_off CASEINCOMPLETE */
3
4module zxppu
5(
6    input               CLOCK,
7    output  reg  [3:0]  R,
8    output  reg  [3:0]  G,
9    output  reg  [3:0]  B,
10    output              HS,
11    output              VS,
12
13    // Считывание данных
14    output  reg  [15:0] A,
15    input        [ 7:0] D,
16    input        [ 2:0] BORDER
17);
18
19// -----------------------------------------------------------------------------
20// Тайминги для горизонтальной и вертикальной развертки
21//        Visible    Front     Sync      Back      Whole
22parameter hzv = 640, hzf = 16, hzs = 96, hzb = 48, hzw = 800,
23          vtv = 400, vtf = 12, vts = 2,  vtb = 35, vtw = 449;
24// -----------------------------------------------------------------------------
25assign HS = X  < (hzb + hzv + hzf); // NEG
26assign VS = Y >= (vtb + vtv + vtf); // POS
27// -----------------------------------------------------------------------------
28// Позиция луча в кадре и максимальные позиции (x,y)
29reg  [ 9:0] X  = 0; wire xmax = (X == hzw - 1);
30reg  [ 9:0] Y  = 0; wire ymax = (Y == vtw - 1);
31wire [ 9:0] x  = (X - hzb);
32wire [ 9:0] y  = (Y - vtb);
33wire [ 7:0] xm = ((X - hzb - 64) >> 1) + 8;
34wire [ 7:0] ym = ((Y - vtb - 8)  >> 1);
35// -----------------------------------------------------------------------------
36reg  [ 7:0] temp;
37reg  [ 7:0] attr;
38reg  [ 7:0] mask;
39// -----------------------------------------------------------------------------
40wire        cbit  = mask[ 3'h7 ^ x[3:1] ];
41wire        paper = (x >= 64 && x < 64 + 512 && y >= 8 && y < 8 + 384);
42wire [ 3:0] K     = paper ? ({attr[6], cbit ^ (attr[7] & flash) ? attr[2:0] : attr[5:3]}) : BORDER;
43// -----------------------------------------------------------------------------
44
45always @(posedge CLOCK) begin
46
47    // Черный цвет по краям
48    {R, G, B} <= 12'h000;
49
50    // Кадровая развертка
51    X <= xmax ?         0 : X + 1;
52    Y <= xmax ? (ymax ? 0 : Y + 1) : Y;
53
54    // Вывод окна видеоадаптера
55    if (X >= hzb && X < hzb + hzv && Y >= vtb && Y < vtb + vtv)
56    begin
57
58        // Цвет или бордер
59        {R, G, B} <=
60        {
61            {2{K[1]}}, {2{K[1] & K[3]}}, // RED
62            {2{K[2]}}, {2{K[2] & K[3]}}, // GREEN
63            {2{K[0]}}, {2{K[0] & K[3]}}  // BLUE
64        };
65
66        case (x[3:0])
67        // Запрос CHAR $4000-$5700 (6144)
68        4'h0: begin A <= {ym[7:6], ym[2:0], ym[5:3], xm[7:3]} | 16'h4000; end
69        // Запрос ATTR $5800-$5AFF (768)
70        4'hE: begin A <= {ym[7:3], xm[7:3]} | 16'h5800; temp <= D; end
71        // Следующие 8 бит цвета готовы
72        4'hF: begin mask <= temp; attr <= D; end
73        endcase
74
75    end
76
77end
78
79// ---------------------------------------------------------------------
80
81reg        flash;
82reg [23:0] timer;
83
84always @(posedge CLOCK) begin
85
86    if (timer == 12500000) begin /* полсекунды */
87        timer <= 1'b0;
88        flash <= flash ^ 1'b1; // мигать каждые 0.5 секунд
89    end else begin
90        timer <= timer + 1'b1;
91    end
92
93end
94
95endmodule