设计及实现 完整代码见我的GitHub仓库
设计思路 要在VGA显示屏上显示内容,实质上是给显示屏的不同位置像素改变其RGB属性。因此需要知道设计一套字典,方便查询每个字母对应的像素位置。这里我们设计一个字母或者符号占8*7个像素(8行7列)。将其中应该有显示的像素标记为1,没有显示的像素标记为0。之后根据每个像素为1或为0来分别改变其RGB属性。
通过一个寄存器来存储拨码开关的输入,再根据该寄存器在字典中查找具体的像素赋值情况。再根据显示屏刷新时刷到的每个像素的值改变其RGB属性。
需注意显示屏并非一直显示信息,其中有部分时间用来发送行同步和场同步信息,但因为时间过短,人类的眼睛无法辨认因此看起来像是显示屏一直在显示。在具体代码中要实现相关行同步和场同步信号的产生与发送。
代码实现 字典示例 符号“*”的字典:
1 2 3 4 5 6 7 8 9 10 default : begin col0 <= 8'b 0000_0000; col1 <= 8'b 0010_0010; col2 <= 8'b 0001_0100; col3 <= 8'b 0000_1000; col4 <= 8'b 0001_0100; col5 <= 8'b 0010_0010; col6 <= 8'b 0000_0000; end
接收拨码开关输入及查询字典相应信息 字典过长,只展示部分
其中s为开关的输入信号
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 32 33 34 35 36 37 38 39 40 41 42 43 44 input wire [5 :0 ] s; reg [5 :0 ] data; always @(posedge clk or negedge rst_n) begin data = s; if (!rst_n) begin col0 <= 8'b 0000_0000; col1 <= 8'b 0000_0000; col2 <= 8'b 0000_0000; col3 <= 8'b 0000_0000; col4 <= 8'b 0000_0000; col5 <= 8'b 0000_0000; col6 <= 8'b 0000_0000; end else begin case (data) 6'b00_0000: begin col0 < = 8'b 0000_0000; col1 <= 8'b 0011_1110; col2 <= 8'b 0101_0001; col3 <= 8'b 0100_1001; col4 <= 8'b 0100_0101; col5 <= 8'b 0011_1110; col6 <= 8'b 0000_0000; end ... default : begin col0 <= 8'b 0000_0000; col1 <= 8'b 0010_0010; col2 <= 8'b 0001_0100; col3 <= 8'b 0000_1000; col4 <= 8'b 0001_0100; col5 <= 8'b 0010_0010; col6 <= 8'b 0000_0000; end endcase end
定义x计数器和y计数器用于产生基本的行和场时序 1 2 3 4 5 6 7 8 9 10 11 12 reg[10 :0 ] x_cnt; reg[9 :0 ] y_cnt; always @ (posedge clk or negedge rst_n) if (!rst_n) x_cnt <= 11' d0; else if (x_cnt == 11' d1039) x_cnt <= 11' d0; else x_cnt <= x_cnt+1'b 1; always @ (posedge clk or negedge rst_n) if (!rst_n) y_cnt <= 10' d0; else if (y_cnt == 10' d665) y_cnt <= 10' d0; else if (x_cnt == 11' d1039) y_cnt <= y_cnt+1'b 1;
设计行同步信号与场同步信号 1 2 3 4 5 6 7 8 9 10 11 12 always @ (posedge clk or negedge rst_n) if (!rst_n) hsync <= 1'b 1; else if (x_cnt == 11' d0) hsync <= 1'b 0; else if (x_cnt == 11' d120) hsync <= 1'b 1; always @ (posedge clk or negedge rst_n) if (!rst_n) vsync <= 1'b 1; else if (y_cnt == 10' d0) vsync <= 1'b 0; else if (y_cnt == 10' d6) vsync <= 1'b 1;
根据字典查找到的字形着色 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 always @(posedge clk) begin c=0 ; if ((ypos>=300 )&&(ypos<=306 )) begin c0<=(col0[ypos-300 ])&&(xpos==200 ); c1<=(col1[ypos-300 ])&&(xpos==201 ); c2<=(col2[ypos-300 ])&&(xpos==202 ); c3<=(col3[ypos-300 ])&&(xpos==203 ); c4<=(col4[ypos-300 ])&&(xpos==204 ); c5<=(col5[ypos-300 ])&&(xpos==205 ); c6<=(col6[ypos-300 ])&&(xpos==206 ); c=c0|c1|c2|c3|c4|c5|c6; end end assign vga_r=c?1 :0 ; assign vga_g=0 ; assign vga_b=1 ;
结果展示