f4e30e9c61b3cd48741b305694c25f7228e63a36
[mw/milkymist.git] / 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
18 module 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         /* Direct Cache Bus */
38         output dcb_stb,
39         output [fml_depth-1:0] dcb_adr,
40         input [63:0] dcb_dat,
41         input dcb_hit,
42         
43         /* VGA pixel clock */
44         input vga_clk,
45         
46         /* VGA signal pads */
47         output vga_psave_n,
48         output reg vga_hsync_n,
49         output reg vga_vsync_n,
50         output vga_sync_n,
51         output vga_blank_n,
52         output reg [7:0] vga_r,
53         output reg [7:0] vga_g,
54         output reg [7:0] vga_b,
55         output [1:0] vga_clk_sel
56 );
57
58 /*
59  * Control interface
60  */
61 wire vga_rst;
62
63 wire [10:0] hres;
64 wire [10:0] hsync_start;
65 wire [10:0] hsync_end;
66 wire [10:0] hscan;
67
68 wire [10:0] vres;
69 wire [10:0] vsync_start;
70 wire [10:0] vsync_end;
71 wire [10:0] vscan;
72
73 wire [fml_depth-1:0] baseaddress;
74 wire baseaddress_ack;
75
76 wire [17:0] nbursts;
77
78 vgafb_ctlif #(
79         .csr_addr(csr_addr),
80         .fml_depth(fml_depth)
81 ) ctlif (
82         .sys_clk(sys_clk),
83         .sys_rst(sys_rst),
84         
85         .csr_a(csr_a),
86         .csr_we(csr_we),
87         .csr_di(csr_di),
88         .csr_do(csr_do),
89         
90         .vga_rst(vga_rst),
91         
92         .hres(hres),
93         .hsync_start(hsync_start),
94         .hsync_end(hsync_end),
95         .hscan(hscan),
96         
97         .vres(vres),
98         .vsync_start(vsync_start),
99         .vsync_end(vsync_end),
100         .vscan(vscan),
101         
102         .baseaddress(baseaddress),
103         .baseaddress_ack(baseaddress_ack),
104         
105         .nbursts(nbursts),
106
107         .vga_clk_sel(vga_clk_sel)
108 );
109
110 /*
111  * Generate signal data
112  */
113 reg hsync_n;
114 reg vsync_n;
115 wire pixel_valid;
116 wire [15:0] pixel_fb;
117 wire pixel_ack;
118 wire [15:0] pixel;
119
120 wire fifo_full;
121
122 reg hactive;
123 reg vactive;
124 wire active = hactive & vactive;
125 assign pixel = active ? pixel_fb : 16'h0000;
126
127 wire generate_en;
128
129 reg [10:0] hcounter;
130 reg [10:0] vcounter;
131
132 always @(posedge sys_clk) begin
133         if(vga_rst) begin
134                 hcounter <= 10'd0;
135                 vcounter <= 10'd0;
136                 hactive <= 1'b0;
137                 hsync_n <= 1'b1;
138                 vactive <= 1'b0;
139                 vsync_n <= 1'b1;
140         end else begin
141                 if(generate_en) begin
142                         hcounter <= hcounter + 10'd1;
143                         
144                         if(hcounter == 10'd0) hactive <= 1'b1;
145                         if(hcounter == hres) hactive <= 1'b0;
146                         if(hcounter == hsync_start) hsync_n <= 1'b0;
147                         if(hcounter == hsync_end) hsync_n <= 1'b1;
148                         if(hcounter == hscan) begin
149                                 hcounter <= 10'd0;
150                                 if(vcounter == vscan)
151                                         vcounter <= 10'd0;
152                                 else
153                                         vcounter <= vcounter + 10'd1;
154                         end
155                         
156                         if(vcounter == 10'd0) vactive <= 1'b1;
157                         if(vcounter == vres) vactive <= 1'b0;
158                         if(vcounter == vsync_start) vsync_n <= 1'b0;
159                         if(vcounter == vsync_end) vsync_n <= 1'b1;
160                 end
161         end
162 end
163
164 assign generate_en = ~fifo_full & (~active | pixel_valid);
165 assign pixel_ack = ~fifo_full & active & pixel_valid;
166
167 vgafb_pixelfeed #(
168         .fml_depth(fml_depth)
169 ) pixelfeed (
170         .sys_clk(sys_clk),
171         .sys_rst(sys_rst),
172         .vga_rst(vga_rst),
173         
174         .nbursts(nbursts),
175         .baseaddress(baseaddress),
176         .baseaddress_ack(baseaddress_ack),
177         
178         .fml_adr(fml_adr),
179         .fml_stb(fml_stb),
180         .fml_ack(fml_ack),
181         .fml_di(fml_di),
182
183         .dcb_stb(dcb_stb),
184         .dcb_adr(dcb_adr),
185         .dcb_dat(dcb_dat),
186         .dcb_hit(dcb_hit),
187         
188         .pixel_valid(pixel_valid),
189         .pixel(pixel_fb),
190         .pixel_ack(pixel_ack)
191 );
192
193 /*
194  * System clock to VGA clock domain crossing is
195  * acheived by an asynchronous FIFO.
196  *
197  * Bits 0-15 are RGB565 pixel data
198  * Bit 16 is negated Horizontal Sync
199  * Bit 17 is negated Verical Sync
200  */
201 wire [17:0] fifo_do;
202
203 asfifo #(
204         .data_width(18),
205         .address_width(6)
206 ) fifo (
207         .data_out(fifo_do),
208         .empty(),
209         .read_en(1'b1),
210         .clk_read(vga_clk),
211         
212         .data_in({vsync_n, hsync_n, pixel}),
213         .full(fifo_full),
214         .write_en(generate_en),
215         .clk_write(sys_clk),
216         
217         .rst(vga_rst)
218 );
219
220 /*
221  * Drive the VGA pads.
222  * RGB565 -> RGB888 color space conversion is also performed here
223  * by bit shifting and replicating the most significant bits of
224  * the input into the least significant bits of the output left
225  * undefined by the shifting.
226  */
227
228 assign vga_sync_n = 1'b0; /* Sync-on-Green is not implemented */
229 assign vga_psave_n = 1'b1;
230 assign vga_blank_n = 1'b1;
231
232 always @(posedge vga_clk) begin
233         vga_vsync_n <= fifo_do[17];
234         vga_hsync_n <= fifo_do[16];
235         vga_r <= {fifo_do[15:11], fifo_do[15:13]};
236         vga_g <= {fifo_do[10:5], fifo_do[10:9]};
237         vga_b <= {fifo_do[4:0], fifo_do[4:2]};
238 end
239
240 endmodule