Root/lm32/logic/sakc/cores/vgafb/rtl/vgafb.v

1/*
2 * Milkymist VJ SoC
3 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18module vgafb #(
19    parameter csr_addr = 4'h0,
20    parameter fml_depth = 26
21) (
22    input sys_clk,
23    input sys_rst,
24    
25    /* Configuration interface */
26    input [13:0] csr_a,
27    input csr_we,
28    input [31:0] csr_di,
29    output [31:0] csr_do,
30    
31    /* Framebuffer FML 4x64 interface */
32    output [fml_depth-1:0] fml_adr,
33    output fml_stb,
34    input fml_ack,
35    input [63:0] fml_di,
36    
37    /* VGA pixel clock */
38    input vga_clk,
39    
40    /* VGA signal pads */
41    output vga_psave_n,
42    output reg vga_hsync_n,
43    output reg vga_vsync_n,
44    output vga_sync_n,
45    output vga_blank_n,
46    output reg [7:0] vga_r,
47    output reg [7:0] vga_g,
48    output reg [7:0] vga_b,
49    output [1:0] vga_clk_sel
50);
51
52/*
53 * Control interface
54 */
55wire vga_rst;
56
57wire [10:0] hres;
58wire [10:0] hsync_start;
59wire [10:0] hsync_end;
60wire [10:0] hscan;
61
62wire [10:0] vres;
63wire [10:0] vsync_start;
64wire [10:0] vsync_end;
65wire [10:0] vscan;
66
67wire [fml_depth-1:0] baseaddress;
68wire baseaddress_ack;
69
70wire [17:0] nbursts;
71
72vgafb_ctlif #(
73    .csr_addr(csr_addr),
74    .fml_depth(fml_depth)
75) ctlif (
76    .sys_clk(sys_clk),
77    .sys_rst(sys_rst),
78    
79    .csr_a(csr_a),
80    .csr_we(csr_we),
81    .csr_di(csr_di),
82    .csr_do(csr_do),
83    
84    .vga_rst(vga_rst),
85    
86    .hres(hres),
87    .hsync_start(hsync_start),
88    .hsync_end(hsync_end),
89    .hscan(hscan),
90    
91    .vres(vres),
92    .vsync_start(vsync_start),
93    .vsync_end(vsync_end),
94    .vscan(vscan),
95    
96    .baseaddress(baseaddress),
97    .baseaddress_ack(baseaddress_ack),
98    
99    .nbursts(nbursts),
100
101    .vga_clk_sel(vga_clk_sel)
102);
103
104/*
105 * Generate signal data
106 */
107reg hsync_n;
108reg vsync_n;
109wire pixel_valid;
110wire [15:0] pixel_fb;
111wire pixel_ack;
112wire [15:0] pixel;
113
114wire fifo_full;
115
116reg hactive;
117reg vactive;
118wire active = hactive & vactive;
119assign pixel = active ? pixel_fb : 16'h0000;
120
121wire generate_en;
122
123reg [10:0] hcounter;
124reg [10:0] vcounter;
125
126always @(posedge sys_clk) begin
127    if(vga_rst) begin
128        hcounter <= 10'd0;
129        vcounter <= 10'd0;
130        hactive <= 1'b0;
131        hsync_n <= 1'b1;
132        vactive <= 1'b0;
133        vsync_n <= 1'b1;
134    end else begin
135        if(generate_en) begin
136            hcounter <= hcounter + 10'd1;
137            
138            if(hcounter == 10'd0) hactive <= 1'b1;
139            if(hcounter == hres) hactive <= 1'b0;
140            if(hcounter == hsync_start) hsync_n <= 1'b0;
141            if(hcounter == hsync_end) hsync_n <= 1'b1;
142            if(hcounter == hscan) begin
143                hcounter <= 10'd0;
144                if(vcounter == vscan)
145                    vcounter <= 10'd0;
146                else
147                    vcounter <= vcounter + 10'd1;
148            end
149            
150            if(vcounter == 10'd0) vactive <= 1'b1;
151            if(vcounter == vres) vactive <= 1'b0;
152            if(vcounter == vsync_start) vsync_n <= 1'b0;
153            if(vcounter == vsync_end) vsync_n <= 1'b1;
154        end
155    end
156end
157
158assign generate_en = ~fifo_full & (~active | pixel_valid);
159assign pixel_ack = ~fifo_full & active & pixel_valid;
160
161vgafb_pixelfeed #(
162    .fml_depth(fml_depth)
163) pixelfeed (
164    .sys_clk(sys_clk),
165    .sys_rst(sys_rst),
166    .vga_rst(vga_rst),
167    
168    .nbursts(nbursts),
169    .baseaddress(baseaddress),
170    .baseaddress_ack(baseaddress_ack),
171    
172    .fml_adr(fml_adr),
173    .fml_stb(fml_stb),
174    .fml_ack(fml_ack),
175    .fml_di(fml_di),
176    
177    .pixel_valid(pixel_valid),
178    .pixel(pixel_fb),
179    .pixel_ack(pixel_ack)
180);
181
182/*
183 * System clock to VGA clock domain crossing is
184 * acheived by an asynchronous FIFO.
185 *
186 * Bits 0-15 are RGB565 pixel data
187 * Bit 16 is negated Horizontal Sync
188 * Bit 17 is negated Verical Sync
189 */
190wire [17:0] fifo_do;
191
192vgafb_asfifo #(
193    .DATA_WIDTH(18),
194    .ADDRESS_WIDTH(6)
195) fifo (
196    .Data_out(fifo_do),
197    .Empty_out(),
198    .ReadEn_in(1'b1),
199    .RClk(vga_clk),
200    
201    .Data_in({vsync_n, hsync_n, pixel}),
202    .Full_out(fifo_full),
203    .WriteEn_in(generate_en),
204    .WClk(sys_clk),
205    
206    .Clear_in(vga_rst)
207);
208
209/*
210 * Drive the VGA pads.
211 * RGB565 -> RGB888 color space conversion is also performed here
212 * by bit shifting and replicating the most significant bits of
213 * the input into the least significant bits of the output left
214 * undefined by the shifting.
215 */
216
217assign vga_sync_n = 1'b0; /* Sync-on-Green is not implemented */
218assign vga_psave_n = 1'b1;
219assign vga_blank_n = 1'b1;
220
221always @(posedge vga_clk) begin
222    vga_vsync_n <= fifo_do[17];
223    vga_hsync_n <= fifo_do[16];
224    vga_r <= {fifo_do[15:11], fifo_do[15:13]};
225    vga_g <= {fifo_do[10:5], fifo_do[10:9]};
226    vga_b <= {fifo_do[4:0], fifo_do[4:2]};
227end
228
229endmodule
230

Archive Download this file

Branches:
master



interactive