找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4270|回复: 0
收起左侧

FPGA三人抢答器设计 Verilog源程序

[复制链接]
ID:579814 发表于 2019-7-8 11:34 | 显示全部楼层 |阅读模式
1.设计一个十秒的倒计时计时器用于选手看题准备并且设计一个60秒的倒计时用于答题。
2.设计电路实现三人抢答。
3.实现用LCD1602显示当前比赛进行的状态。各个状态如下:
(1)抢答前显示开始抢答和该问题为第几个问题(共有5题):“Begin!”“Question-x”。
(2)若在十秒的该抢答时间内无人抢答,显示失败,下一题。“Fail to quiz!“”Next!“。
(3)抢答后显示抢答选手姓名,如:“Respondent”“Zhangsan”。
(4)选手抢到题后该选手指示灯亮,回答完毕或回答时间到熄灭。
(5)若选手在六十秒的回答时间内未完成回答则显示失败。“Failure!“若在有效的十秒内回答完毕则由裁判对回答的正误判断分别显示“Congratulation!+10““Failure!“。如此反复,共进行五次。
(6)当完成竞赛总数(共5题)题目时,显示竞赛结束。“End of the quiz!”
4.设计计分器对选手的得分进行及时的显示。(答对一题得一分,答错或回答超时扣一分)

2 设计分析及系统方案设计

为了实现以上四点设计要求,把总方案分成顶层(top)模块、液晶显示(lcd)模块、液晶控制(lcdcontroller)模块、倒计时(discount)模块、计分(jifen)模块共五个模块。其中倒计时模块和计分模块融合在顶层模块里。

顶层(Top)模块用于对整个电路的逻辑设计和各个状态的转换以及对子模块的调用。

液晶显示(Lcd)模块则用于显示相关字符。需要先把要显示的字符写在程序中备用,并编码。采用译码器的方式调用某串字符。故该模块的输入为需要调用的字符的编码、竞赛进行到第几个问题(共五个)的编码以及时钟等。

液晶控制(lcdcontroller)模块用于对液晶读写显示的驱动。

倒计时(discount)模块用于比赛中的计时。先把50M的频率分成1HZ的频率进行记秒。采用译码器的原理把倒计时显示在对应的数码管上。

计分模块用于实时显示选手的得分。同样采用译码器原理进行数码管的显示。输入为选手的得分。

图2.1  系统框图


3系统以及模块硬件电路设计

3.1系统硬件电路设计

图3.1  按键原理图

该设计共使用7个按键用于实现使能、裁判判决、选手表示等功能。
图3.2  选手对应的灯的原理图
采用排阻接发光二极管接地的方式,当输入为高时灯亮。
图3.3  数码管原理图
该设计共采用了五个共阴极数码管,分别对应于开发板的HEX0 HEX2 HEX4 HEX5 HEX6。前三者用于实时显示选手分数后两者用于显示倒计时。
图3.4  液晶LCD1602原理图
3.2功能管脚定义
程序定义
管脚号
功能
clk_en
PIN_N2
连接开发板50M作为时钟
en
PIN_N25
使能端
en_next
PIN_P25
是否的进入下一题
lcd_en
PIN_K3
LCD使能
lcd_on
PIN_L4
LCD电源
lcd_rs
PIN_K1
LCD命令/数据端
lcd_rw
PIN_K4
LCD读/写端
led_a
PIN_AD12
选手a的Led灯
led_b
PIN_AE12
选手b的Led灯
led_c
PIN_AE13
选手c的Led灯
right[0]
PIN_B13
组合判断选手答案的正误。(都为高则表示真确只有一个为高则错误)
right[1]
PIN_C13
chosen[0]
PIN_U4
选手张三
chosen[1]
PIN_V1
选手李四
chosen[2]
PIN_V2
选手王五
程序定义
管脚号
功能
count_down_0[0]
PIN_R2
数码管显示的倒计时的十位
count_down_0[1]
PIN_P4
count_down_0[2]
PIN_P3
count_down_0[3]
PIN_M2
count_down_0[4]
PIN_M3
count_down_0[5]
PIN_M5
count_down_0[6]
PIN_M4
count_down_1[0]
PIN_L3
数码管显示的倒计时的个位
count_down_1[1]
PIN_L2
count_down_1[2]
PIN_K9
count_down_1[3]
PIN_L6
count_down_1[4]
PIN_L7
count_down_1[5]
PIN_P9
count_down_1[6]
PIN_N9
fenshu_a[0]
PIN_U9
数码管显示的选手张三的分数
fenshu_a[1]
PIN_U1
fenshu_a[2]
PIN_U2
fenshu_a[3]
PIN_T4
fenshu_a[4]
PIN_R7
fenshu_a[5]
PIN_R6
fenshu_a[6]
PIN_T3
fenshu_b[0]
PIN_AB23
数码管显示的选手李四的分数
fenshu_b[1]
PIN_V22
fenshu_b[2]
PIN_AC25
fenshu_b[3]
PIN_AC26
fenshu_b[4]
PIN_AB26
fenshu_b[5]
PIN_AB25
fenshu_b[6]
PIN_Y24
fenshu_c[0]
PIN_AF10
数码管显示的选手王五的分数
fenshu_c[1]
PIN_AB12
fenshu_c[2]
PIN_AC12
fenshu_c[3]
PIN_AD11
fenshu_c[4]
PIN_AE11
fenshu_c[5]
PIN_V14
fenshu_c[6]
PIN_V13
lcd_data[0]
PIN_J1
LCD的数据/指令输入
lcd_data[1]
PIN_J2
lcd_data[2]
PIN_H1
lcd_data[3]
PIN_H2
lcd_data[4]
PIN_J4
lcd_data[5]
PIN_J3

lcd_data[6]
PIN_H4
lcd_data[7]
PIN_H3

4 系统的Verilog HDL设计

4.1.1顶层(Top module)
当主裁判发出开始标志时先判断n(比赛的题目数)是否小于5(题目总数)然后进入十秒的倒计时让选手看题抢答,若有选手在十秒内作答则进入该选手的state进入下一轮10秒的答题倒计时,并判断是否超时,若60秒内选手答题完毕则由裁判判断正确与否以及是否进入下一题,若答题的60秒内选手未答题或者答题超时则失败。若在选手抢答的十秒内没有选手抢答则该题作废由裁判判决进入下一题。

图4.1  顶层状态图
4.1.2 LCD显示
查看液晶1602的手册先行配置相关显示参数确保能够静态显示。在此基础上,对该设计需要现实的字符串先行查找相关的8位二进制代码。考虑到显示的字符串比较多,故选择了定义两个128位(16*8)的寄存器型变量对1602的两行进行数据的存储,然后利用译码器的思想设置了三位的变量调用相关字符串以达到实时显示相关字符串的目的。对于比赛进行到几个项目的显示也是采用相同的先编码存储然后调用的方法实现。
下表为字符与输入编码的对应表。
Choose[2]
Choose[1]
Choose[0]
显示
0
0
0
Begin! Question-x
0
0
1
End of the quiz!
0
1
0
Fail to quiz! Next!
0
1
1
Zhang san
1
0
0
Li si
1
0
1
Wang wu
1
1
0
Failure! -1
1
1
1
Congratulation! +1

4.1.3 倒计时(discount)
该设计中有需要两个倒计时,一个用来计时抢答一个用来计时回答,同时需要在一次倒计时结束时生成标志位并且在生成标志位完成一个问题的抢答后需要对标志位进行复位让主模块里的状态循环得以正常进行。该模块采用的仍是对置数的十位和个位进行译码进而显示在相关的数码管上。
4.1.4 计分(jifen)
在每次副裁判宣布进入下一题的下降沿触发判断该上一个问题的得分情况。把计分和主模块写在两个always里面主要是避免主模块里时钟频率太大导致计数不准确的问题。
//////////////////顶层模块代码
  1. module test7_20(input en,input en_next_ctr,input clk_en,input [2:0]chosen,input [2:0]chosen_over,
  2. input [1:0]right,output reg [6:0]fenshu_a,output reg [6:0]fenshu_b,output reg [6:0]fenshu_c,
  3. output reg [6:0]count_down_1,output reg [6:0]count_down_0,output reg led_a,output reg led_b,
  4. output reg led_c,inout [7:0]lcd_data,output  rw,output  lcd_en,output  lcd_rs,output  lcd_on);
  5. //en使能(按键控制,代表总裁判) en_next_ctr裁判判决是否进入下一题 [2:0]chosen代表三个选手[2:0]chosen_over用于判断选手是否答题完毕
  6. //[1:0]right用于裁判判断对错 fenshu_a fenshu_b fenshu_c代表选手的分数
  7. /////////////////////////////////////////////////////////////
  8. //internal
  9. reg [2:0]chose,a,b,c;
  10. reg [2:0]n;
  11. reg t_an,t_kai,en_next,discount_en_1,t_1,t_first;
  12. reg [27:0]count;
  13. ////////////////////////////////////////////////////////////
  14. always@(posedge clk_en)
  15. begin
  16. if(en)
  17. begin
  18.               if(en_next_ctr==0)
  19.                             begin
  20.                             en_next<=1;
  21.                             //discount_en_1<=0;
  22.                             //t_1<=0;
  23.                             end
  24.               if(n==3'd5)
  25.                             begin
  26.                             chose<=3'o1;//显示End of the quiz!
  27.                             discount_en_1<=0;
  28.                             t_1<=0;
  29.                             led_a<=0;
  30.                             led_b<=0;
  31.                             led_c<=0;
  32.                             end
  33.               else begin
  34.                             if((en_next==1))
  35.                             begin
  36.                                           discount_en_1<=1;
  37.                                           t_1<=0;//使能倒计时
  38.                                           chose<=3'o0;
  39.                                           end//液晶第一行显示Begin!第二行显示Question-x 其中x 表示第几个问题
  40.                             if(t_kai==1)//无人抢答
  41.                                                         begin
  42.                                                         discount_en_1<=0;
  43.                                                         t_1<=0;
  44.                                                         chose<=3'o2;//第一行显示Fail to quiz!第二行显示Next!
  45.                                                         en_next<=0;
  46.                                                         end
  47.                             else begin
  48.                            
  49.                                                                       if(chosen==3'b100)//a
  50.                                                                                     if(!t_first)//
  51.                                                                                     begin//
  52.                                                                                                   discount_en_1<=1;
  53.                                                                                                   t_1<=1;
  54.                                                                                                   led_a<=1;
  55.                                                                                                   chose<=3'o3;//显示选手姓名
  56.                                                                                                   if(t_an==1)//回答超时
  57.                                                                                                                 begin
  58.                                                                                                                 chose<=3'o6;
  59.                                                                                                                 en_next<=0;
  60.                                                                                    
  61.                                                                                                                 end
  62.                                                                                                   else if(chosen_over[2]==1)//回答结束
  63.                                                                                                                 begin
  64.                                                                                                                 t_1<=0;
  65.                                                                                                                 discount_en_1<=0;
  66.                                                                                                                 if(right==2'b01)//判断正确与否
  67.                                                                                                                                             begin
  68.                                                                                                                                             en_next<=0;
  69.                                                                                                                                             chose<=3'o7;
  70.                                                                                                                                             //              a<=a+1'b1;
  71.                                                                                                                                             led_a<=0;
  72.                                                                                                                                             end
  73.                                                                                                                                             else if(right==2'b10)
  74.                                                                                                                                             begin
  75.                                                                                                                                             en_next<=0;
  76.                                                                                                                                             chose<=3'o6;
  77.                                                                                                                                             led_a<=0;
  78.                                                                                                                                             end
  79.                                                                                                                 end
  80.                                                                                                   end//
  81.                                                                                                   else//
  82.                                                                                                                 begin
  83.                                                                                                                 chose<=3'o6;
  84.                                                                                                                 en_next<=0;
  85.                                                                                                                 discount_en_1<=0;
  86.                                                                                                                 t_1<=0;
  87.                                                                                                                 end//
  88.                                                                                                 
  89.                                                                                     else            
  90.                                                                                                   if(chosen==3'b010)//b
  91.                                                                                                                 begin
  92.                                                                                                                 if(!t_first)
  93.                                                                                                   begin
  94.                                                                                                                               discount_en_1<=1;
  95.                                                                                                                               t_1<=1;
  96.                                                                                                                               led_b<=1;
  97.                                                                                                                               chose<=3'o4;//显示选手姓名
  98.                                                                                                                 if(t_an==1)
  99.                                                                                                                               begin
  100.                                                                                                                               chose<=3'o6;
  101.                                                                                                                               en_next<=0;
  102.                                                                                                 
  103.                                                                                                                               end
  104.                                                                                                                 else if(chosen_over[1]==1)
  105.                                                                                                                               begin
  106.                                                                                                                               t_1<=0;
  107.                                                                                                                               discount_en_1<=0;
  108.                                                                                                                               if(right==2'b01)
  109.                                                                                                                                             begin
  110.                                                                                                                                             led_b<=0;
  111.                                                                                                                                             en_next<=0;
  112.                                                                                                                                             chose<=3'o7;
  113.                                                                                                                                             end
  114.                                                                                                                                             else if(right==2'b10)
  115.                                                                                                                                             begin
  116.                                                                                                                                             en_next<=0;
  117.                                                                                                                                             chose<=3'o6;
  118.                                                                                                                                             led_b<=0;
  119.                                                                                                                                             end
  120.                                                                                                                               end
  121.                                                                                                                 end//
  122.                                                                                                                 else//
  123.                                                                                                                 begin
  124.                                                                                                                 chose<=3'o6;//
  125.                                                                                                                 en_next<=0;//
  126.                                                                                                                 discount_en_1<=0;
  127.                                                                                                                 t_1<=0;
  128.                                                                                                                 end//
  129.                                                                                                                 end
  130.                                                                                                                              
  131.                                                                                                                 else
  132.                                                                                                                               if(chosen==3'b001)//c
  133.                                                                                                                 begin if(!t_first)//
  134.                                                                                                                                             begin
  135.                                                                                                                                             discount_en_1<=1;
  136.                                                                                                                                             t_1<=1;
  137.                                                                                                                                             led_c<=1;
  138.                                                                                                                                             chose<=3'o5;//显示选手姓名
  139.                                                                                                                                             if(t_an==1)
  140.                                                                                                                                                           begin
  141.                                                                                                                                             chose<=3'o6;
  142.                                                                                                                                             en_next<=0;
  143.                                                                                                                              
  144.                                                                                                                                             end
  145.                                                                                                                                             else if(chosen_over[0]==1)
  146.                                                                                                                                                           begin
  147.                                                                                                                                                           t_1<=0;
  148.                                                                                                                                                           discount_en_1<=0;
  149.                                                                                                                                                           if(right==2'b01)
  150.                                                                                                                                                           begin
  151.                                                                                                                                                                         en_next<=0;
  152.                                                                                                                                                                         chose<=3'o7;
  153.                                                                                                                                                                         led_c<=0;
  154.                                                                                                                                                           end
  155.                                                                                                                                             else if(right==2'b10)
  156.                                                                                                                                             begin
  157.                                                                                                                                             en_next<=0;
  158.                                                                                                                                             chose<=3'o6;
  159.                                                                                                                                             led_c<=0;
  160.                                                                                                                                             end
  161.                                                                                                                                             end
  162.                                                                                                                                             end
  163.                                                                                                                                             else
  164.                                                                                                                                             begin
  165.                                                                                                                                             chose<=3'o6;
  166.                                                                                                                                             en_next<=0;
  167.                                                                                                                                             discount_en_1<=0;
  168.                                                                                                                                             t_1<=0;
  169.                                                                                                                                             end
  170.                                                                                                                               end
  171.                                                                                                   end//若无选手答题返回继续倒计时并判断
  172.                                                                                     end
  173.                                           end
  174. end
  175. ////////////////////////////////////////////////
  176. always@(negedge en_next)//计数比赛进行到第几个问题
  177. begin
  178.               if(en)
  179.               if(n==5)
  180.               n<=3'd0;
  181.               else
  182.               n<=n+1'b1;
  183. end


  184. //////////////////////////////////////////////
  185. always@( negedge en_next )//实时显示比赛得分
  186. begin
  187. if(en)
  188. begin
  189. if(chose==3'o1)
  190.               begin
  191.               a<=3'd0;
  192.               b<=3'd0;
  193.               c<=3'd0;
  194.               end
  195. else
  196. if(chose==3'o7)
  197. case(chosen_over)
  198. 3'b100:a<=a+1'b1;
  199. 3'b010:b<=b+1'b1;
  200. 3'b001:c<=a+1'b1;

  201. endcase
  202. else if(chose==3'o6)
  203. case(chosen_over)
  204. 3'b100:begin
  205.                                                         if(a==0)
  206.                                                         a<=0;
  207.                                                         else
  208.                                                         a<=a-1'b1;
  209.                                           end
  210. 3'b010:begin
  211.                                                         if(b==0)
  212.                                                         b<=0;
  213.                                                         else
  214.                                                         b<=b-1'b1;
  215.                                           end
  216. 3'b001:begin
  217.                                                         if(c==0)
  218.                                                         c<=0;
  219.                                                         else
  220.                                                         c<=c-1'b1;
  221.                                           end
  222. endcase
  223. end
  224. end

  225. ////////////////////////////////////////////////////////////////////////

  226. ///////////////////////////////////////////////////////////////////////////
  227. reg [3:0]shi,ge;//时钟clk 使能en 输出显示数码管a b///输出tt用于判断是否计时结束
  228. reg [24:0]count_0;//计数用于分频
  229. reg out_clk,t_0,t_2;
  230. //out_clk为1hz的时钟信号
  231. //该模块的功能为输入时钟和使能进行10秒倒计时
  232. always@(posedge clk_en)//50M分频--1HZ
  233. begin
  234.               if(count_0==25'h17d7840)
  235.                             begin
  236.                             count_0<=25'h0000000;
  237.                             out_clk<=!out_clk;
  238.                             end
  239.               else
  240.                             count_0<=count_0+1'b1;
  241. end

  242. always@(posedge out_clk)//倒计时
  243. begin
  244. if(en)
  245.               case({discount_en_1,t_1})
  246.               2'd0:begin
  247.                             shi<=4'd0;
  248.                             ge<=4'd0;
  249.                             t_0<=0;
  250.                             t_2<=0;
  251.                             t_kai<=0;
  252.                            
  253.                             t_an<=0;
  254.                             //t<=0;
  255.                             end
  256.               2'd1:;
  257.               2'd2:if(t_0==0)
  258.                                           begin
  259.                                           shi<=4'd1;
  260.                                           ge<=4'd0;
  261.                                           t_0<=1;
  262.                                           t_first<=0;
  263.                                           //t_kai<=0;
  264.                                           end
  265.                             else begin
  266.                             if(shi==0&&ge==0&&t_0==1)
  267.                                                         t_kai<=1;
  268.                             else begin
  269.                                           if(ge==4'd0)
  270.                                                         begin
  271.                                                                       shi<=shi-1'b1;
  272.                                                                       ge<=4'd9;
  273.                                                                       end
  274.                                                         else ge<=ge-1'b1;            
  275.                                                         end
  276.                             end            
  277.               2'd3:if(t_2==0)
  278.                                           begin
  279.                                           shi<=4'd1;
  280.                                           ge<=4'd0;
  281.                                           t_2<=1;
  282.                                           t_first<=0;
  283.                                           //t_an<=0;
  284.                                           end
  285.                             else begin
  286.                             if(shi==0&&ge==0&&t_2==1)
  287.                                           begin
  288.                                                         t_an<=1;
  289.                                                         t_first<=1;
  290.                                                         end
  291.                             else begin
  292.                                           if(ge==4'd0)
  293.                                                         begin
  294.                                                                       shi<=shi-1'b1;
  295.                                                                       ge<=4'd9;
  296.                                                                       end
  297.                                                         else ge<=ge-1'b1;            
  298.                                                         end
  299.                             end            
  300.               endcase
  301. end

  302.                                          
  303. always@(shi)
  304.   begin
  305.    case(shi)
  306.                  4'd0: count_down_1<=7'b1000000;
  307.                  4'd1: count_down_1<=7'b1111001;
  308.               4'd2: count_down_1<=7'b0100100;
  309.               4'd3: count_down_1<=7'b0110000;
  310.               4'd4: count_down_1<=7'b0011001;
  311.               4'd5: count_down_1<=7'b0010010;
  312.               4'd6: count_down_1<=7'b0000010;
  313.               4'd7: count_down_1<=7'b1111000;
  314.               4'd8: count_down_1<=7'b0000000;
  315.               4'd9: count_down_1<=7'b0010000;
  316.     default: count_down_1<=7'b1111111;
  317.     endcase
  318.   end

  319. always@(ge)
  320.   begin
  321.    case(ge)
  322.                  4'd0: count_down_0<=7'b1000000;
  323.                  4'd1: count_down_0<=7'b1111001;
  324.               4'd2: count_down_0<=7'b0100100;
  325.               4'd3: count_down_0<=7'b0110000;
  326.               4'd4: count_down_0<=7'b0011001;
  327.               4'd5: count_down_0<=7'b0010010;
  328.               4'd6: count_down_0<=7'b0000010;
  329.               4'd7: count_down_0<=7'b1111000;
  330.               4'd8: count_down_0<=7'b0000000;
  331.               4'd9: count_down_0<=7'b0010000;
  332.     default: count_down_0<=7'b1111111;
  333.     endcase
  334.   end            
  335. always@(a)//显示得分
  336. begin
  337.               case(a)
  338.               0:fenshu_a<=7'b1000000;//共五道题每题一分
  339.               1:fenshu_a<=7'b1111001;
  340.               2:fenshu_a<=7'b0100100;
  341.               3:fenshu_a<=7'b0110000;
  342.               4:fenshu_a<=7'b0011001;
  343.               5:fenshu_a<=7'b0010010;
  344.               endcase
  345. end
  346. always@(b)//显示得分
  347. begin
  348.               case(b)
  349.               0:fenshu_b<=7'b1000000;//共五道题每题一分
  350.               1:fenshu_b<=7'b1111001;
  351.               2:fenshu_b<=7'b0100100;
  352.               3:fenshu_b<=7'b0110000;
  353.               4:fenshu_b<=7'b0011001;
  354.               5:fenshu_b<=7'b0010010;
  355.               endcase
  356. end
  357. always@(c)//显示得分
  358. begin
  359.               case(c)
  360.               0:fenshu_c<=7'b1000000;//共五道题每题一分
  361.               1:fenshu_c<=7'b1111001;
  362.               2:fenshu_c<=7'b0100100;
  363.               3:fenshu_c<=7'b0110000;
  364.               4:fenshu_c<=7'b0011001;
  365.               5:fenshu_c<=7'b0010010;
  366.               endcase
  367. end
  368. //discount(.clk(clk_en),.en(discount_en_1),.a(count_down_1),.b(count_down_0),.tt(t));//调用倒计时模块
  369. //jifen(.data_in(a),.data_out(fenshu_a));//调用显示数码管计分模块分别显示三位选手的得分
  370. //jifen(.data_in(b),.data_out(fenshu_b));
  371. //jifen(.data_in(c),.data_out(fenshu_c));
  372. lcd (.iCLK(clk_en),.iRST_N(en),.choose(chose),.m(n),.LCD_DATA(lcd_data),
  373. .LCD_RW(lcd_rw),.LCD_EN(lcd_en),.LCD_RS(lcd_rs),.LCD_ON(lcd_on));//调用LCD模块显示相关的字符串
  374. endmodule
  375. //LCD显示模块代码

  376. module              lcd (              //              Host Side
  377.                                                                       iCLK,iRST_N,choose,m,
  378.                                                                       //              LCD Side
  379.                                                                       LCD_DATA,LCD_RW,
  380.                                                                       LCD_EN,LCD_RS,LCD_ON);//改模块的功能为实现LCD在不同的抢答状态输出不同的字符串
  381. //m用于判断是第几个问题              //choose用于选择那个字符串
  382.                                                                      
  383. //              Host Side
  384. input [2:0]choose,m;
  385. input                                          iCLK,iRST_N;
  386. //              LCD Side
  387. inout              [7:0]              LCD_DATA;
  388. output                                          LCD_RW,LCD_EN,LCD_RS,LCD_ON;

  389. //              Internal Wires/Registers
  390. reg              [5:0]              LUT_INDEX;
  391. reg              [7:0]              LUT_DATA;
  392. reg              [5:0]              mLCD_ST;
  393. reg              [17:0]              mDLY;
  394. reg                                          mLCD_Start;
  395. reg              [7:0]              mLCD_DATA;
  396. reg                                          mLCD_RS;
  397. wire                            mLCD_Done;
  398. reg [127:0]lineone,linetwo;//定义两个128位的数据用于存储液晶每一行应该显示的数据128=16*8





  399. parameter              LCD_INTIAL              =              0;
  400. parameter              LCD_LINE1              =              5;
  401. parameter              LCD_CH_LINE              =              LCD_LINE1+16;
  402. parameter              LCD_LINE2              =              LCD_LINE1+16+1;
  403. parameter              LUT_SIZE              =              LCD_LINE1+32+1;

  404. assign LCD_ON = 1'b1;
  405. always@(posedge iCLK or negedge iRST_N)
  406. begin
  407.               if(!iRST_N)
  408.               begin
  409.                             LUT_INDEX              <=              0;
  410.                             mLCD_ST                            <=              0;
  411.                             mDLY                            <=              0;
  412.                             mLCD_Start              <=              0;
  413.                             mLCD_DATA              <=              0;
  414.                             end
  415.               else
  416.               begin
  417.                             if(LUT_INDEX<LUT_SIZE)
  418.                             begin
  419.                                           case(mLCD_ST)
  420.                                           0:              begin
  421.                                                                       mLCD_DATA              <=              LUT_DATA[7:0];
  422.                                                                       mLCD_Start              <=              1;
  423.                                                                       mLCD_ST                            <=              1;                  
  424.                                                         end
  425.                                           1:              begin
  426.                                                                       if(mLCD_Done)
  427.                                                                       begin
  428.                                                                                     mLCD_Start              <=              0;
  429.                                                                                     mLCD_ST                            <=              2;
  430.                                                                       end
  431.                                                         end
  432.                                           2:              begin
  433.                                                                       if(mDLY<18'h3FFFE)
  434.                                                                       mDLY              <=              mDLY+1;
  435.                                                                       else
  436.                                                                       begin
  437.                                                                                     mDLY              <=              0;
  438.                                                                                     mLCD_ST              <=              3;                     
  439.                                                                       end
  440.                                                         end
  441.                                           3:              begin
  442.                                                                       if (LUT_INDEX<LUT_SIZE-1)
  443.                                                                       LUT_INDEX              <=              LUT_INDEX+1;
  444.                                                                       else
  445.                                                                       LUT_INDEX              <=  LCD_INTIAL+4;
  446.                     mLCD_ST              <=              0;
  447.                                                         end
  448.                                           endcase
  449.                             end
  450.               end
  451. end

  452. always
  453. begin
  454.               case(LUT_INDEX)
  455.               //              Initial
  456.               LCD_INTIAL+0:              begin
  457.                                                                       mLCD_RS                            <=0;
  458.                                                                       LUT_DATA              <=              8'h38;//16*2 5*7点阵8位数据端口
  459.                                                                       end
  460.               LCD_INTIAL+1:              begin
  461.                                                                       mLCD_RS                            <=0;
  462.                                                                       LUT_DATA              <=              8'h0C;//开显示
  463.                                                                       end
  464.               LCD_INTIAL+2:              begin
  465.                                                                       mLCD_RS                            <=0;
  466.                                                                       LUT_DATA              <=              8'h01;//显示清屏
  467.                                                                       end
  468.               LCD_INTIAL+3:              begin
  469.                                                                       mLCD_RS                            <=0;
  470.                                                                       LUT_DATA              <=              8'h06;//写或读一个字符后地址指针加一光标加一
  471.                                                                       end
  472.               LCD_INTIAL+4:              begin
  473.                                                                       mLCD_RS                            <=0;
  474.                                                                       LUT_DATA              <=              8'h80;//设置数据地址指针
  475.                                                                       end
  476.               //              Line 1
  477.               LCD_LINE1+0:              begin
  478.                                                                       mLCD_RS                            <=1;
  479.                                                                       LUT_DATA              <=              lineone[127:120];            
  480.                                                                       end
  481.               LCD_LINE1+1:              begin
  482.                                                                       mLCD_RS                            <=1;
  483.                                                                       LUT_DATA              <=              lineone[119:112];
  484.                                                                       end
  485.               LCD_LINE1+2:              begin
  486.                                                                       mLCD_RS                            <=1;
  487.                                                                       LUT_DATA              <=              lineone[111:104];
  488.                                                                       end
  489.               LCD_LINE1+3:              begin
  490.                                                                       mLCD_RS                            <=1;
  491.                                                                       LUT_DATA              <=              lineone[103:96];
  492.                                                                       end
  493.               LCD_LINE1+4:              begin
  494.                                                                       mLCD_RS                            <=1;
  495.                                                                       LUT_DATA              <=              lineone[95:88];
  496.                                                                       end
  497.               LCD_LINE1+5:              begin
  498.                                                                       mLCD_RS                            <=1;
  499.                                                                       LUT_DATA              <=              lineone[87:80];
  500.                                                                       end
  501.               LCD_LINE1+6:              begin
  502.                                                                       mLCD_RS                            <=1;
  503.                                                                       LUT_DATA              <=              lineone[79:72];
  504.                                                                       end
  505.               LCD_LINE1+7:              begin
  506.                                                                       mLCD_RS                            <=1;
  507.                                                                       LUT_DATA              <=              lineone[71:64];
  508.                                                                       end
  509.               LCD_LINE1+8:              begin
  510.                                                                       mLCD_RS                            <=1;
  511.                                                                       LUT_DATA              <=              lineone[63:56];
  512.                                                                       end
  513.               LCD_LINE1+9:              begin
  514.                                                                       mLCD_RS                            <=1;
  515.                                                                       LUT_DATA              <=              lineone[55:48];
  516.                                                                       end
  517.               LCD_LINE1+10:              begin
  518.                                                                       mLCD_RS                            <=1;
  519.                                                                       LUT_DATA              <=              lineone[47:40];
  520.                                                                       end
  521.               LCD_LINE1+11:              begin
  522.                                                                       mLCD_RS                            <=1;
  523.                                                                       LUT_DATA              <=              lineone[39:32];
  524.                                                                       end
  525.               LCD_LINE1+12:              begin
  526.                                                                       mLCD_RS                            <=1;
  527.                                                                       LUT_DATA              <=              lineone[31:24];
  528.                                                                       end
  529.               LCD_LINE1+13:              begin
  530.                                                                       mLCD_RS                            <=1;
  531.                                                                       LUT_DATA              <=              lineone[23:16];
  532.                                                                       end
  533.               LCD_LINE1+14:              begin
  534.                                                                       mLCD_RS                            <=1;
  535.                                                                       LUT_DATA              <=              lineone[15:8];
  536.                                                                       end
  537.               LCD_LINE1+15:              begin
  538.                                                                       mLCD_RS                            <=1;
  539.                                                                       LUT_DATA              <=              lineone[7:0];
  540.                                                                       end
  541.               //              Change Line
  542.               LCD_CH_LINE:              begin
  543.                                                                       mLCD_RS                            <=0;
  544.                                                                       LUT_DATA              <=              8'hC0;
  545.                                                                       end
  546.               //              Line 2
  547.               LCD_LINE2+0:              begin
  548.                                                                       mLCD_RS                            <=1;
  549.                                                                       LUT_DATA              <=              linetwo[127:120];            
  550.                                                                       end
  551.               LCD_LINE2+1:              begin
  552.                                                                       mLCD_RS                            <=1;
  553.                                                                       LUT_DATA              <=              linetwo[119:112];
  554.                                                                       end
  555.               LCD_LINE2+2:              begin
  556.                                                                       mLCD_RS                            <=1;
  557.                                                                       LUT_DATA              <=              linetwo[111:104];
  558.                                                                       end
  559.               LCD_LINE2+3:              begin
  560.                                                                       mLCD_RS                            <=1;
  561.                                                                       LUT_DATA              <=              linetwo[103:96];
  562.                                                                       end
  563.               LCD_LINE2+4:              begin
  564.                                                                       mLCD_RS                            <=1;
  565.                                                                       LUT_DATA              <=              linetwo[95:88];
  566.                                                                       end
  567.               LCD_LINE2+5:              begin
  568.                                                                       mLCD_RS                            <=1;
  569.                                                                       LUT_DATA              <=              linetwo[87:80];
  570.                                                                       end
  571.               LCD_LINE2+6:              begin
  572.                                                                       mLCD_RS                            <=1;
  573.                                                                       LUT_DATA              <=              linetwo[79:72];
  574.                                                                       end
  575.               LCD_LINE2+7:              begin
  576.                                                                       mLCD_RS                            <=1;
  577.                                                                       LUT_DATA              <=              linetwo[71:64];
  578.                                                                       end
  579.               LCD_LINE2+8:              begin
  580.                                                                       mLCD_RS                            <=1;
  581.                                                                       LUT_DATA              <=              linetwo[63:56];
  582.                                                                       end
  583.               LCD_LINE2+9:              begin
  584.                                                                       mLCD_RS                            <=1;
  585.                                                                       LUT_DATA              <=              linetwo[55:48];
  586.                                                                       end
  587.               LCD_LINE2+10:              begin
  588.                                                                       mLCD_RS                            <=1;
  589.                                                                       LUT_DATA              <=              linetwo[47:40];
  590.                                                                       end
  591.               LCD_LINE2+11:              begin
  592.                                                                       mLCD_RS                            <=1;
  593.                                                                       LUT_DATA              <=              linetwo[39:32];
  594.                                                                       end
  595.               LCD_LINE2+12:              begin
  596.                                                                       mLCD_RS                            <=1;
  597.                                                                       LUT_DATA              <=              linetwo[31:24];
  598.                                                                       end
  599.               LCD_LINE2+13:              begin
  600.                                                                       mLCD_RS                            <=1;
  601.                                                                       LUT_DATA              <=              linetwo[23:16];
  602.                                                                       end
  603.               LCD_LINE2+14:              begin
  604.                                                                       mLCD_RS                            <=1;
  605.                                                                       LUT_DATA              <=              linetwo[15:8];
  606.                                                                       end
  607.               LCD_LINE2+15:              begin
  608.                                                                       mLCD_RS                            <=1;
  609.                                                                       LUT_DATA              <=              linetwo[7:0];
  610.                                                                       end
  611.               default:                            begin
  612.                                                                       mLCD_RS                            <=1;
  613.                                                                       LUT_DATA              <=              8'h00;
  614.                                                                       end
  615.               endcase
  616. end

  617. always@(choose)//选择液晶输出什么字符串
  618. begin
  619.               case(choose)
  620.               3'o0:              begin
  621.                                                         lineone<=128'h20_20_20_20_20_42_65_67_69_6E_21_20_20_20_20_20;//Begin!
  622.                                                         case(m)//选择输出问题几
  623.                                                                       0:linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_31_20_20_20;//Question
  624.                                                                       1:linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_32_20_20_20;
  625.                                                                       2:linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_33_20_20_20;
  626.                                                                       3:linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_34_20_20_20;
  627.                                                                       4:linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_35_20_20_20;
  628.                                                                       default:linetwo<=128'h20_20_20_20_20_20_20_20_20_20_20_20_20_20_20_20;
  629.                                                         endcase
  630.                                           end
  631.               3'o1:              begin
  632.                                           lineone<=128'h45_6E_64_20_6F_66_20_74_68_65_20_71_75_69_7A_21;//End of the quiz!
  633.                                           linetwo<=128'h20_20_20_20_20_20_20_20_20_20_20_20_20_20_20_20;
  634.                                           end
  635.               3'o2:              begin
  636.                                                         lineone<=128'h20_46_61_69_6C_20_74_6F_20_71_75_69_7A_21_20_20;//Fail to quiz!
  637.                                                         linetwo<=128'h20_20_20_20_20_4E_65_78_74_21_20_20_20_20_20_20;//Next!
  638.                                           end
  639.               3'o3:              begin
  640.                                                         lineone<=128'h20_20_20_52_65_73_70_6F_6E_64_65_6E_74_20_20_20;//Zhang san
  641.                                                         linetwo<=128'h20_20_20_5A_68_61_6E_67_20_73_61_6E_20_20_20_20;
  642.                                           end
  643.               3'o4:              begin
  644.                                                         lineone<=128'h20_20_20_52_65_73_70_6F_6E_64_65_6E_74_20_20_20;
  645.                                                         linetwo<=128'h20_20_20_20_20_4C_69_20_73_69_20_20_20_20_20_20;//Li si
  646.                                           end
  647.               3'o5:              begin
  648.                                                         lineone<=128'h20_20_20_52_65_73_70_6F_6E_64_65_6E_74_20_20_20;//Wang wu
  649.                                                         linetwo<=128'h20_20_20_20_57_61_6E_67_20_77_75_20_20_20_20_20;
  650.                                           end
  651.               3'o6:              begin
  652.                                                         lineone<=128'h20_20_20_20_46_61_69_6C_75_72_65_21_20_20_20_20;//Failure!linetwo<=128'h20_20_20_20_20_4F_76_65_72_21_20_20_20_20_20_20;
  653.                                                         linetwo<=128'h20_20_20_20_20_20_20_20_20_20_20_20_20_20_20_20;
  654.                                           end
  655.               3'o7:              begin
  656.                                                         lineone<=128'h43_6F_6E_67_72_61_74_75_6C_61_74_69_6F_6E_73_21;//Congratulation!
  657.                                                         linetwo<=128'h20_20_20_20_20_20_2B_31_20_20_20_20_20_20_20_20;//+10
  658.                                           end            
  659.                                           default:begin
  660.                                                         lineone<=128'h20_20_20_20_20_42_65_67_69_6E_21_20_20_20_20_20;//Begin!
  661.                                                         linetwo<=128'h20_20_20_51_75_65_73_74_69_6F_6E_2D_20_20_20_20;//Question
  662.                                                         end
  663.                                           endcase
  664.               end

  665. lcdcontroller                             u0              (              //              Host Side
  666.                                                                                                   .iDATA(mLCD_DATA),
  667.                                                                                                   .iRS(mLCD_RS),
  668.                                                                                                   .iStart(mLCD_Start),
  669.                                                                                                   .oDone(mLCD_Done),
  670.                                                                                                   .iCLK(iCLK),
  671.                                                                                                   .iRST_N(iRST_N),
  672.                                                                                                   //              LCD Interface
  673.                                                                                                   .LCD_DATA(LCD_DATA),
  674.                                                                                                   .LCD_RW(LCD_RW),
  675.                                                                                                   .LCD_EN(LCD_EN),
  676.                                                                                                   .LCD_RS(LCD_RS)              );
  677. endmodule
  678. lcdcontroller                             u0              (              //              Host Side
  679.                                                                                                   .iDATA(mLCD_DATA),
  680.                                                                                                   .iRS(mLCD_RS),
  681.                                                                                                   .iStart(mLCD_Start),
  682.                                                                                                   .oDone(mLCD_Done),
  683.                                                                                                   .iCLK(iCLK),
  684.                                                                                                   .iRST_N(iRST_N),
  685.                                                                                                   //              LCD Interface
  686.                                                                                                   .LCD_DATA(LCD_DATA),
  687.                                                                                                   .LCD_RW(LCD_RW),
  688.                                                                                                   .LCD_EN(LCD_EN),
  689.                                                                                                   .LCD_RS(LCD_RS)              );
  690. endmodule

  691. //LCD控制模块代码
  692. module lcdcontroller (              //              Host Side
  693.                                                                                     iDATA,iRS,
  694.                                                                                     iStart,oDone,
  695.                                                                                     iCLK,iRST_N,
  696.                                                                                     //              LCD Interface
  697.                                                                                     LCD_DATA,
  698.                                                                                     LCD_RW,
  699.                                                                                     LCD_EN,
  700.                                                                                     LCD_RS              );//控制LCD的显示
  701. //              CLK
  702. parameter              CLK_Divide              =              16;

  703. //              Host Side
  704. input              [7:0]              iDATA;
  705. input              iRS,iStart;
  706. input              iCLK,iRST_N;
  707. output              reg                            oDone;
  708. //              LCD Interface
  709. output              [7:0]              LCD_DATA;
  710. output              reg                            LCD_EN;
  711. output                                          LCD_RW;
  712. output                                          LCD_RS;
  713. //              Internal Register
  714. reg                            [4:0]              Cont;
  715. reg                            [1:0]              ST;
  716. reg                            preStart,mStart;

  717. /////////////////////////////////////////////
  718. //              Only write to LCD, by pass iRS to LCD_RS
  719. assign              LCD_DATA              =              iDATA;
  720. assign              LCD_RW                            =              1'b0;
  721. assign              LCD_RS                            =              iRS;
  722. /////////////////////////////////////////////

  723. always@(posedge iCLK or negedge iRST_N)
  724. begin
  725.               if(!iRST_N)
  726.               begin
  727.                             oDone              <=              1'b0;
  728.                             LCD_EN              <=              1'b0;
  729.                             preStart<=              1'b0;
  730.                             mStart              <=              1'b0;
  731.                             Cont              <=              0;
  732.                             ST                            <=              0;
  733.               end
  734.               else
  735.               begin
  736.                             //////              Input Start Detect ///////
  737.                             preStart<=              iStart;
  738.                             if({preStart,iStart}==2'b01)
  739.                             begin
  740.                                           mStart              <=              1'b1;
  741.                                           oDone              <=              1'b0;
  742.                             end
  743.                             //////////////////////////////////
  744.                             if(mStart)
  745.                             begin
  746.                                           case(ST)
  747.                                           0:              ST              <=              1;              //              Wait Setup
  748.                                           1:              begin
  749.                                                                       LCD_EN              <=              1'b1;
  750.                                                                       ST                            <=              2;
  751.                                                         end
  752.                                           2:              begin                                                                     
  753.                                                                       if(Cont<CLK_Divide)
  754.                                                                       Cont              <=              Cont+1;
  755.                                                                       else
  756.                                                                       ST                            <=              3;
  757.                                                         end
  758.                                           3:              begin
  759.                                                                       LCD_EN              <=              1'b0;
  760.                                                                       mStart              <=              1'b0;
  761.                                                                       oDone              <=              1'b1;
  762.                                                                       Cont              <=              0;
  763.                                                                       ST                            <=              0;
  764.                                                         end
  765.                                           endcase
  766.                             end
  767.               end
  768. end

  769. endmodule
复制代码

结论以及结果说明
系统运行在Cyclone II开发板上,程序代码运行在Quartus II6.0上。该设计中抢答时间和回答时间可以根据具体情况进行调整。在计时分频环节把50M的频率分成1HZ的频率时通对需要计数的值进行判定。同样的在LCD显示模块里为了让模块可以正常工作,并且简化显示流程,对比LCD1602的参考手册采用把时钟分成约100HZ 让LCD只需不断地写入指令或数据即可。运行结果可以达到设计效果。
0.png

全部资料51hei下载地址:
test7_21.zip (1.64 MB, 下载次数: 25)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表