博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最终大赛作品——VGA简单显示、简单视力检测
阅读量:7099 次
发布时间:2019-06-28

本文共 18517 字,大约阅读时间需要 61 分钟。

最终的功能怎么说呢。。一个字——怂!(PS:此时此刻只想默默地发个笑不出的表情。。。)

算个半成品吧,不过还是记录一下,中间对Verilog有了很多新的理解

其实其中的一部分代码是借鉴网上的,比如PLL.v,比如VGA驱动时序,比如按键消抖。。

 

 

1. PLL.v

  这个据说是可以自动生成的,还有待学习——

// synopsys translate_off`timescale 1 ps / 1 ps// synopsys translate_onmodule PLL (    inclk0,    c0,    c1,    c2);    input      inclk0;    output      c0;    output      c1;    output      c2;    wire [5:0] sub_wire0;    wire [0:0] sub_wire6 = 1'h0;    wire [2:2] sub_wire3 = sub_wire0[2:2];    wire [1:1] sub_wire2 = sub_wire0[1:1];    wire [0:0] sub_wire1 = sub_wire0[0:0];    wire  c0 = sub_wire1;    wire  c1 = sub_wire2;    wire  c2 = sub_wire3;    wire  sub_wire4 = inclk0;    wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};    altpll    altpll_component (                .inclk (sub_wire5),                .clk (sub_wire0),                .activeclock (),                .areset (1'b0),                .clkbad (),                .clkena ({
6{
1'b1}}), .clkloss (), .clkswitch (1'b0), .enable0 (), .enable1 (), .extclk (), .extclkena ({
4{
1'b1}}), .fbin (1'b1), .locked (), .pfdena (1'b1), .pllena (1'b1), .scanaclr (1'b0), .scanclk (1'b0), .scandata (1'b0), .scandataout (), .scandone (), .scanread (1'b0), .scanwrite (1'b0), .sclkout0 (), .sclkout1 ()); defparam altpll_component.clk0_divide_by = 2, altpll_component.clk0_duty_cycle = 50, altpll_component.clk0_multiply_by = 1, altpll_component.clk0_phase_shift = "0", altpll_component.clk1_divide_by = 1250, altpll_component.clk1_duty_cycle = 50, altpll_component.clk1_multiply_by = 1597, altpll_component.clk1_phase_shift = "0", altpll_component.clk2_divide_by = 32, altpll_component.clk2_duty_cycle = 50, altpll_component.clk2_multiply_by = 23, altpll_component.clk2_phase_shift = "0", altpll_component.compensate_clock = "CLK0", altpll_component.inclk0_input_frequency = 20000, altpll_component.intended_device_family = "Cyclone II", altpll_component.lpm_type = "altpll", altpll_component.operation_mode = "NORMAL", altpll_component.pll_type = "FAST", altpll_component.port_activeclock = "PORT_UNUSED", altpll_component.port_areset = "PORT_UNUSED", altpll_component.port_clkbad0 = "PORT_UNUSED", altpll_component.port_clkbad1 = "PORT_UNUSED", altpll_component.port_clkloss = "PORT_UNUSED", altpll_component.port_clkswitch = "PORT_UNUSED", altpll_component.port_fbin = "PORT_UNUSED", altpll_component.port_inclk0 = "PORT_USED", altpll_component.port_inclk1 = "PORT_UNUSED", altpll_component.port_locked = "PORT_UNUSED", altpll_component.port_pfdena = "PORT_UNUSED", altpll_component.port_pllena = "PORT_UNUSED", altpll_component.port_scanaclr = "PORT_UNUSED", altpll_component.port_scanclk = "PORT_UNUSED", altpll_component.port_scandata = "PORT_UNUSED", altpll_component.port_scandataout = "PORT_UNUSED", altpll_component.port_scandone = "PORT_UNUSED", altpll_component.port_scanread = "PORT_UNUSED", altpll_component.port_scanwrite = "PORT_UNUSED", altpll_component.port_clk0 = "PORT_USED", altpll_component.port_clk1 = "PORT_USED", altpll_component.port_clk2 = "PORT_USED", altpll_component.port_clk3 = "PORT_UNUSED", altpll_component.port_clk4 = "PORT_UNUSED", altpll_component.port_clk5 = "PORT_UNUSED", altpll_component.port_clkena0 = "PORT_UNUSED", altpll_component.port_clkena1 = "PORT_UNUSED", altpll_component.port_clkena2 = "PORT_UNUSED", altpll_component.port_clkena3 = "PORT_UNUSED", altpll_component.port_clkena4 = "PORT_UNUSED", altpll_component.port_clkena5 = "PORT_UNUSED", altpll_component.port_enable0 = "PORT_UNUSED", altpll_component.port_enable1 = "PORT_UNUSED", altpll_component.port_extclk0 = "PORT_UNUSED", altpll_component.port_extclk1 = "PORT_UNUSED", altpll_component.port_extclk2 = "PORT_UNUSED", altpll_component.port_extclk3 = "PORT_UNUSED", altpll_component.port_extclkena0 = "PORT_UNUSED", altpll_component.port_extclkena1 = "PORT_UNUSED", altpll_component.port_extclkena2 = "PORT_UNUSED", altpll_component.port_extclkena3 = "PORT_UNUSED", altpll_component.port_sclkout0 = "PORT_UNUSED", altpll_component.port_sclkout1 = "PORT_UNUSED";endmodule

 

 

2. VGA_Control.v

  前半部分为借鉴网上代码,后半部分为本人原创,但是依照最后的结果来看,后半部分并不能稳定工作->-

module    VGA_Control(input                                CLOCK_50,input                                RSTn,input                 [3:0]        KEY,output                          VGA_BLANK_N,output                          VGA_CLK,output                          VGA_SYNC_N,output                          VGA_VS,output                          VGA_HS,output            [7:0]      VGA_R,output            [7:0]         VGA_G,output            [7:0]      VGA_B);//==============================VGA底层驱动-时序控制====================================reg[9:0] H_Cont; //行扫描计数器reg[9:0] V_Cont; //列扫描计数器reg vga_hs;reg vga_vs;reg[10:0] X;   //横坐标reg[10:0] Y;   //纵坐标assign VGA_HS=vga_hs;assign VGA_VS=vga_vs;//水平参数parameter H_FRONT=16;parameter H_SYNC=96;parameter H_BACK=48;parameter H_ACT=640;parameter H_BLANK=H_FRONT+H_SYNC+H_BACK;parameter H_TOTAL=H_FRONT+H_SYNC+H_BACK+H_ACT;//垂直参数parameter V_FRONT=11;parameter V_SYNC=2;parameter V_BACK=32;parameter V_ACT=480;parameter V_BLANK=V_FRONT+V_SYNC+V_BACK;parameter V_TOTAL=V_FRONT+V_SYNC+V_BACK+V_ACT;//锁相环产生25MHZ的时钟wire CLK_25;PLL pll0(.inclk0 ( CLOCK_50 ),.c0 ( CLK_25 ));//Select DAC CLOCKassign VGA_CLK = CLK_25;assign VGA_SYNC_N = 1'b0; //If not SOG, Sync input should be tied to 0;assign VGA_BLANK_N = ~((H_Cont
=H_BLANK) X<=H_Cont-H_BLANK;else X<=0;endend//水平扫描always@(posedge VGA_HS, negedge RSTn)beginif(!RSTn)begin V_Cont<=0; vga_vs<=1; Y<=0;endelse begin if(V_Cont
=V_BLANK) Y<=V_Cont-V_BLANK; else Y<=0; endend//================================================VGA显示================================================= reg[7:0] vga_r;reg[7:0] vga_g;reg[7:0] vga_b;assign VGA_R=vga_r;assign VGA_G=vga_g;assign VGA_B=vga_b;//==========显示控制算法模块===========//==========键盘检测===========wire isDown1;wire isDown2;wire isDown3;wire isDown4;Button_Module b0( .CLOCK_50(CLOCK_50), .RSTn(RSTn), .key(KEY[3]), .isDown(isDown1) );Button_Module b1( .CLOCK_50(CLOCK_50), .RSTn(RSTn), .key(KEY[2]), .isDown(isDown2) );Button_Module b2( .CLOCK_50(CLOCK_50), .RSTn(RSTn), .key(KEY[1]), .isDown(isDown3) );Button_Module b3( .CLOCK_50(CLOCK_50), .RSTn(RSTn), .key(KEY[0]), .isDown(isDown4) ); //=========一旦检测到按键,产生一个高脉冲 reg Start_Sig;always@(posedge CLOCK_50, negedge RSTn)if(!RSTn) Start_Sig <= 1'b0; else begin if(isDown1 || isDown2 || isDown3 || isDown4) Start_Sig <= 1'b1; else Start_Sig <= 1'b0; end //============产生随机数==============wire [1:0] direction;wire Done_Sig;suijishu s0( .clk(CLK_25), .RSTn(RSTn), .Start_Sig(Start_Sig), .Done_Sig(Done_Sig), .direction(direction) ); //====================================================================//======判断为E显示还是结果显示reg [1:0] i;reg [1:0] qi;always@(posedge CLOCK_50, negedge RSTn)begin if(!RSTn) begin i <= 0; qi <= 0; end else if(Start_Sig) begin case({isDown1,isDown2,isDown3,isDown4}) 4'b1000 : if(direction == 2'b00) begin i <= 1; qi <= i; end else begin i <= 2; qi <= i; end 4'b0100 : if(direction == 2'b01) begin i <= 1; qi <= i; end else begin i <= 2; qi <= i; end 4'b0010 : if(direction == 2'b10) begin i <= 1; qi <= i; end else begin i <= 2; qi <= i; end 4'b0001 : if(direction == 2'b11) begin i <= 1; qi <= i; end else begin i <= 2; qi <= i; end endcaseendelse begin i <= 0; qi <= 0; endend //计时reg [15:0] cnt0;reg [15:0] cnt1;reg e;reg [1:0] ee;always@(posedge CLOCK_50, negedge RSTn)beginif(!RSTn) cnt0 <= 0; else if(cnt0 == 16'd49_999) cnt0 <= 0; else cnt0 <= cnt0 + 1;endalways@(posedge CLOCK_50, negedge RSTn)beginif(!RSTn) cnt1 <= 0; else if(e) begin if(cnt0 == 16'd49_999) cnt1 <= cnt1 + 1;endelse cnt1 <= 0; endalways@(posedge CLK_25, negedge RSTn)beginif(!RSTn) e <= 0;else case(e) 0: if((qi == 0) && (i == 1)) begin //正确提示 e <= 1; ee <= 1; end else if((qi == 0) && (i == 2)) begin //错误提示 e <= 1; ee <= 2; end else e <= 0; 1: e <= cnt1 == 10'd5000 ? 0 : 1; endcase end/*wire [1:0] direction;wire [1:0] ee;wire e;judge j0( .CLOCK_50(CLOCK_50), .CLOCK_25(CLOCK_25), .RSTn(RSTn), .KEY(KEY), .e(e), .ee(ee) ); */ always@(posedge CLK_25, negedge RSTn)beginif(!RSTn)begin vga_r<=0; vga_g<=0; vga_b<=0;endelse if(e == 0) begin case(direction) 2'b00: //右 begin if((X>=215 && X<=240 && Y>=110 && Y<=370) || ((X>=240 && X<=400) && ((Y>=110 && Y<=130) || (Y>=230 && Y<=250) || (Y>=350 && Y<=370)))) begin vga_r <= 0; vga_g <= 0; vga_b <= 0; end else begin vga_r <= 128; vga_g <= 128; vga_b <= 128; end end 2'b01: //上 begin if((X>=190 && X<=450 && Y>=307 && Y<=332) || ((Y>=147 && Y<=307) && ((X>=190 && X<=210) || (X>=310 && X<=330) || (X>=430 && X<=450)))) begin vga_r <= 0; vga_g <= 0; vga_b <= 0; end else begin vga_r <= 128; vga_g <= 128; vga_b <= 128; end end 2'b10: //左 begin if((X>=375 && X<=400 && Y>=110 && Y<=370) || ((X>=215 && X<=375) && ((Y>=110 && Y<=130) || (Y>=230 && Y<=250) || (Y>=350 && Y<=370)))) begin vga_r <= 0; vga_g <= 0; vga_b <= 0; end else begin vga_r <= 128; vga_g <= 128; vga_b <= 128; end end 2'b11: //下 begin if((X>=190 && X<=450 && Y>=147 && Y<=172) || ((Y>=172 && Y<=332) && ((X>=190 && X<=210) || (X>=310 && X<=330) || (X>=430 && X<=450)))) begin vga_r <= 0; vga_g <= 0; vga_b <= 0; end else begin vga_r <= 128; vga_g <= 128; vga_b <= 128; end end endcaseendelse if(e == 1) begin case(ee) 1: begin vga_r <= 0; vga_g <= 128; vga_b <= 0; end 2: begin vga_r <= 128; vga_g <= 0; vga_b <= 0; end endcase end endendmodule

 

3. suijishu.v

  这个算法思想借鉴一篇论文,代码是自己实现的

  

module    suijishu(input        clk,input        RSTn,input        Start_Sig,output    Done_Sig,output    [1:0]        direction);reg    [3:0]        e;reg    [1:0]        rd;reg    [1:0]        qd;reg                 rDone;always @ (posedge clk or negedge RSTn)if(!RSTn) begin    e <= 4'd0;    rd <= 2'd0;        qd <= 2'd0;    rDone <= 0;endelse begin    if(Start_Sig == 1) begin        rd <= e[1:0];        qd <= rd;        rDone <= 1;    end    else        e <= e + 1'b1;end//防止与上一次重复assign direction = (qd == rd) ? rd+1 : rd;assign Done_Sig = rDone;endmodule

 

4. Button_Module.v

  这个部分靠自己之前写的代码不能稳定工作,因此后来还是借鉴了《VerilogHDL那些事儿——建模篇》这本书上的代码

module    Button_Module(input                 CLOCK_50,input                 RSTn,input                 key,output            isDown);/*//按键按下后有个延迟等待时间,知道键被松开reg    i;    //当前ireg    qi;   //当前i的前一个状态always@(posedge clk or negedge RSTn) begin    if(!RSTn)        i <= 1'b1;    else        case(i)            1'b0:            begin                i <= key == 1'b0 ? 1'b0 : 1'b1;                 qi <= i;            end                        1'b1:            begin                i <= key == 1'b1 ? 1'b1 : 1'b0;                qi <= i;            end        endcaseend*///===========电平检测模块============parameter    T100US = 11'd4999;reg    [10:0]    Count1;reg isEn;//电平检测不稳定需延时100USalways @ (posedge CLOCK_50 or negedge RSTn)    if(!RSTn)        begin                Count1 <= 11'd0;            isEn <=1'b0;        end    else if(Count1==T100US)        isEn <= 1'b1;    else    Count1 <= Count1 + 1'b1;//检测按键状态    reg    H2L_F1;reg    H2L_F2;reg    L2H_F1;reg    L2H_F2;always @ (posedge CLOCK_50 or negedge RSTn)    if(!RSTn)        begin                H2L_F1 <= 1'b1;            H2L_F2 <= 1'b1;            L2H_F1 <= 1'b0;            L2H_F2 <= 1'b0;        end    else         begin            H2L_F1 <= key;            H2L_F2 <= H2L_F1;            L2H_F1 <= key;            L2H_F2 <= L2H_F1;        endwire H2L_Sig;        wire L2H_Sig;    assign    H2L_Sig = isEn ? (H2L_F2 & !H2L_F1) : 1'b0;assign    L2H_Sig = isEn ? (!L2H_F2 & L2H_F1) : 1'b0;//=============消抖模块===============parameter    T1MS = 16'd49_999;reg    [15:0]    Count2;reg    [3:0]    Count_MS;//延时1MSalways @ (posedge CLOCK_50 or negedge RSTn)    if(!RSTn)        Count2 <= 16'd0;    else if(isCount && Count2==T1MS)        Count2 <= 16'd0;    else if(isCount)        Count2 <= Count2 + 1'b1;    else if(!isCount)        Count2 <= 16'd0;        always @ (posedge CLOCK_50 or negedge RSTn)    if(!RSTn)        Count_MS <= 4'd0;    else if(isCount && Count2==T1MS)        Count_MS <= Count_MS + 1'b1;    else if(!isCount)        Count_MS <= 4'd0;reg    isCount;        reg    Pin_Out;        reg    [1:0]    i;always @ (posedge CLOCK_50 or negedge RSTn)    if(!RSTn)        begin                isCount <= 1'b0;            Pin_Out <= 1'b0;            i <= 2'd0;        end    else        case(i)            2'd0:            if(H2L_Sig)    i <= 2'd1;            else if(L2H_Sig)    i<= 2'd2;                        2'd1:            if(Count_MS == 4'd10) begin                isCount <= 1'b0;                Pin_Out <= 1'b1;                i <= 2'd0;                end            else    isCount <= 1'b1;            2'd2:            if(Count_MS == 4'd10) begin                isCount <= 1'b0;                Pin_Out <= 1'b0;                i <= 2'd0;                end                else    isCount <= 1'b1;        endcase        assign    isDown = Pin_Out;   //Pin_Out为1表示按键被按下,为表示松开endmodule

 

5. sighting.v

  顶层

//=======================================================//  This code is generated by Terasic System Builder//=======================================================module sighting(     CLOCK //    CLOCK_50,    RSTn,     LED //    LEDG,    LEDR,     KEY //    KEY,     VGA //    VGA_B,    VGA_BLANK_N,    VGA_CLK,    VGA_G,    VGA_HS,    VGA_R,    VGA_SYNC_N,    VGA_VS );//=======================================================//  PORT declarations//======================================================= CLOCK //input                          CLOCK_50;input                          RSTn; LED //output             [8:0]        LEDG;output            [17:0]        LEDR; KEY //input             [3:0]        KEY; VGA //output             [7:0]        VGA_B;output                          VGA_BLANK_N;output                          VGA_CLK;output             [7:0]        VGA_G;output                          VGA_HS;output             [7:0]        VGA_R;output                          VGA_SYNC_N;output                          VGA_VS;//=======================================================//  Structural coding//=======================================================//====================VGA显示========================VGA_Control    v0(                    .CLOCK_50(CLOCK_50),                    .RSTn(RSTn),                    .KEY(KEY),                    .VGA_BLANK_N(VGA_BLANK_N),                    .VGA_CLK(VGA_CLK),                    .VGA_SYNC_N(VGA_SYNC_N),                    .VGA_VS(VGA_VS),                    .VGA_HS(VGA_HS),                    .VGA_R(VGA_R),                    .VGA_B(VGA_B),                    .VGA_G(VGA_G));endmodule

 

 

 

 

遇到的问题——尚未解决的有:1、VGA的分模块写,这个尝试了好多遍,一把底层驱动部分和VGA显示部分分开写就不能正常工作了,后来就只能把这两部分写在一个模块里了

              2、VGA数码管,LCD仿佛不能同时用的样子,一把Seg或者LCD用DE2_115_SystemBuilder添进去VGA就不能正常工作了,原因不明

 

已解决部分的问题:判断按键与图标的一致性之后,需控制显示屏红或绿5秒,一个大概可以说搞了一整天,最后勉强可以实现了,但是不稳定,这个时候我才意识到仿真的重要性。——的确,一个工具只有当你不得不用到它的时候才不得不去学,嗯,就是这样。

人家书上之前讲案件模块中电平检测需要延时的时候自己总觉得没啥必要,后来自己实现了一个不用电平检测延时的程序依旧能用按键控制LED亮灭的时候就更确定自己的想法了——知道在这个小项目中遇到显示屏显示闪动问题,才知道自己错了,完全没有考虑全面的思想啊。。。

 

收获:看了那么多代码,明白了什么时候用reg,什么时候用wire,reg 和 wire 后面的[]里的数怎么自己根据情况定。

需要在always里用到的变量需要用reg先定义,如果要output需用assign赋给对应的output

如果要执行assign,而output里有没有该变量的话,就需要用wire定义一个

嗯,其实也没有很难,当你自己敲代码调试代码,遇到报错的次数多了之后,其中的规则就都明白了,不错,为自己点个赞*^_^*

  •  还有就是想循环间歇性执行某个操作的时候,因为没有for语句,所以实现起来还是有点技巧的,具体的技巧我体会得也不是很透彻,还有待阅读更多书籍丫。。。

 

 

 

 

 

 

 

           

转载于:https://www.cnblogs.com/fengyanlover/p/5049176.html

你可能感兴趣的文章
Window平台搭建Redis分布式缓存集群 (一)server搭建及性能測试
查看>>
SQL变量与全局变量
查看>>
bootstrap基础学习六篇
查看>>
[.net 面向对象程序设计深入](5)MVC 6 —— 构建跨平台.NET开发环境(Windows/Mac OS X/Linux)...
查看>>
Android横竖屏切换及其相应布局载入问题
查看>>
带辉光效果的跑马灯
查看>>
CSS隐藏元素的几个方法(display,visibility)的区别
查看>>
HTML 中的 dl(dt,dd)、ul(li)、ol(li)
查看>>
Linux下Redis主从复制以及SSDB主主复制环境部署记录
查看>>
如何让win10实现关机确认-暂没确认
查看>>
常用js函数整理--common.js
查看>>
java内存泄漏与内存溢出
查看>>
互联网服务器的实现过程需要考虑哪些安全问题 & 加解密及哈希知识点
查看>>
sql server2008给数据表,字段,添加修改注释
查看>>
meta标签清理缓存
查看>>
onvif开发之设备发现功能的实现--转
查看>>
虚拟机下linux迁移造成MAC地址异常处理办法
查看>>
数据库事务原子性、一致性是怎样实现的?[转]
查看>>
“营改增”后你该知道的…代开发票需要知道的16个事项
查看>>
动态设置js的属性
查看>>