tinyvga.v 4.51 KB
Newer Older
Christian Fibich's avatar
Christian Fibich committed
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
`default_nettype none

module tinyvga (input  osc,
                output reg [3:0] red,
                output reg [3:0] green,
                output reg [3:0] blue,
                output reg [7:0] led,
                output reg hsync,
                output reg vsync);

    wire clk36m;
    wire reset;
    wire locked;
    reg  [2:0]  reset_sync;

    // VGA
    wire blank;
    wire [10:0] column_next;
    wire [9:0]  line_next;
    reg  [9:0]  column;
    reg  [9:0]  line;

    // Image mover
    reg  [5:0]  sinetab [127:0];
    reg  [6:0]  memcol;
    reg  [5:0]  memcol_off;
    reg  [5:0]  memln;
    reg  [5:0]  memln_off;
    reg  [7:0]  frame_cnt;
    wire [7:0]  frame_cnt_next;

32
33
34
35
    // Logo
    reg  [6:0]  logocol;
    reg  [5:0]  logoln;

Christian Fibich's avatar
Christian Fibich committed
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
    ////////////////////////////////////////////////////////////////////

    pll pll_i(.clock_in(osc),.clock_out(clk36m),.locked(locked));

    always @(posedge clk36m or negedge locked) begin
        if (!locked)
            reset_sync <= "111";
        else
            reset_sync <= {reset_sync[1:0],1'b0};
    end

    assign reset = reset_sync[2];

    ////////////////////////////////////////////////////////////////////

    assign column_next    = {1'b0, column} + 11'b1;
    assign line_next      = line + 10'b1;
    assign blank          = ((column_next > 800) || (line_next > 600));
    assign frame_cnt_next = frame_cnt + 1;

    always @(posedge clk36m) begin
        if (reset) begin
            column       <= 10'b0;
            line         <= 10'b0;
            hsync        <= 1'b0;
            vsync        <= 1'b0;
            memcol       <= 7'h0;
            memln        <= 6'h0;
            frame_cnt    <= 8'b0;
            led          <= 8'b0;
66
67
            logocol      <= 8'b0;
            logoln       <= 7'b0;
Christian Fibich's avatar
Christian Fibich committed
68
        end else begin
69
70
71
72
73
74
            column  <= column_next[9:0];
            memcol  <= column[7:1] + memcol_off;
            memln   <= line[6:1] + memln_off;
            led     <= frame_cnt;
            logocol <= column[9:2] - 8'd36;
            logoln  <= line[7:2] - 7'd43;
Christian Fibich's avatar
Christian Fibich committed
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

            if (column == 823)
                hsync <= 1'b1;
            else if (column == 895)
                hsync <= 1'b0;

            if (column_next[10]) begin
                line      <= line_next;

                if (line == 601)
                    vsync <= 1'b1;
                else if (line == 603)
                    vsync <= 1'b0;
                else if (line == 624) begin
                    line <= 10'b0;
                    frame_cnt <= frame_cnt_next;
                end
            end
        end
    end

    ////////////////////////////////////////////////////////////////////

    wire [6:0] sinetab_addr_a;
    wire [6:0] sinetab_addr_b;

    assign sinetab_addr_a = frame_cnt[6:0];
    assign sinetab_addr_b = frame_cnt[6:0]+6'd32;

    always @(posedge clk36m) begin
        if (reset) begin
            memln_off  <= 0;
            memcol_off <= 0;
        end else begin
            memln_off  <= sinetab[sinetab_addr_a];
            memcol_off <= sinetab[sinetab_addr_b];
        end
    end

    initial
        $readmemh("sinetab.mem",sinetab);

    ////////////////////////////////////////////////////////////////////

    reg [11:0] imem [8191:0];
    reg [11:0] memline;

122
123
    reg [1:0] logo[8191:0];
    reg [1:0] logoline;
Christian Fibich's avatar
Christian Fibich committed
124

125
126
127
128
    initial begin
        $readmemh("color.mem",imem);
        $readmemb("logo.mem",logo);
    end
Christian Fibich's avatar
Christian Fibich committed
129
130
131

    always @(posedge clk36m) begin
        if (reset) begin
132
133
134
135
136
            red      <= 4'b0;
            green    <= 4'b0;
            blue     <= 4'b0;
            memline  <= 12'b0;
            logoline <= 2'b0;
Christian Fibich's avatar
Christian Fibich committed
137
138
        end else begin
            memline = imem[{memln,memcol}];
139
            logoline = logo[{logoln,logocol}];
Christian Fibich's avatar
Christian Fibich committed
140
141
142
143
            if (blank) begin
                red   <= 4'b0;
                green <= 4'b0;
                blue  <= 4'b0;
144
145
146
147
148
149
150
151
152
153
            end else if (logoline > 2'b0 && line > 171 && line < 428 && column > 143 && column < 656) begin
                if (logoline == 2'b01) begin
                    red   <= {2'b0,memline[11:10]};
                    green <= {2'b0,memline[7:6]};
                    blue  <= {2'b0,memline[3:2]};
                end else begin
                    red   <= {logoline[0],memln_off[4:2]};
                    green <= {logoline[0],memln_off[4:2]};
                    blue  <= {logoline[0],memln_off[4:2]};
                end
Christian Fibich's avatar
Christian Fibich committed
154
155
156
157
158
159
160
161
162
            end else begin
                red   <= memline[11:8];
                green <= memline[7:4];
                blue  <= memline[3:0];
            end
        end
    end

endmodule