FPGA实验:数码管滚动显示字符串“HELLO”(verilog编写、移位扫描驱动显示)

实验题目:移位显示“Hello”字符串(开发板上有6个数码管):
设计基本要求: (1)复位信号高电平有效由滑动开关送入,下降沿的同时右对齐显示“Hello”字符, 并由右向左移动,空两格循环显示;
(2)按键触发单稳态定时,字符由左向右逆向循环,定时结束后恢复(定时为5s);
(3)按键控制位移步进速度,至少三个不同值。
设计进阶: (4)使用同一按键控制步进速度;

视频展示:
链接:https://pan.baidu.com/s/1OEkvViKP239-_0miCaBeBg
提取码:0uup

在这里插入图片描述

采用top-down设计;
设计基本模块

module div(clock_in,clock_out);//先做个时钟分频模块
  input clock_in;
  output clock_out;

  reg clk_p_r;
  reg clk_n_r;
  reg [F_DIV_WIDTH-1:0] count_p;
  reg [F_DIV_WIDTH-1:0] count_n;

  parameter F_DIV=48000000;//分频参数设置,因为本人开发板晶振时钟为50MHz,当此值为50000000时,可得1Hz频率
  parameter F_DIV_WIDTH=32;//

  wire full_div_p; 
  wire half_div_p;
  wire full_div_n;
  wire half_div_n;

  assign full_div_p = (count_p<F_DIV-1);
  assign half_div_p = (count_p<(F_DIV>>1)-1);
  assign full_div_n = (count_p<F_DIV-1);
  assign half_div_n = (count_p<(F_DIV>>1)-1);
 
  assign clock_out = (F_DIV==1)? clock_in:(F_DIV[0]? (clk_p_r&clk_n_r):clk_p_r);

  always @(posedge clock_in)
  begin
   if(full_div_p)
   begin
     count_p=count_p+1'b1;
     if(half_div_p)
       clk_p_r=1'b0;
     else
       clk_p_r=1'b1;
   end
   else
   begin
      count_p=0;
      clk_p_r=1'b0;
   end
  end  

  always@(negedge clock_in)
  begin
     if(full_div_n)
     begin
       count_n=count_n+1'b1;
       if(half_div_n)
          clk_n_r=1'b0;
       else 
          clk_n_r=1'b1;
     end
     else
     begin
       count_n=0;
       clk_n_r=1'b0;
     end
  end    
endmodule

module State_left(clk,rst,in,Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0);//数码管正循环(从右向左移动)状态机模块
  input clk,rst;
  input in;//由同一个按键控制的步进速度信号
  output [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;//输出6个数码管的状态变化
  reg  [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
  reg [25:0]Time1;
  reg [1:0] Speed;
  reg  [25:0]Count5,Count4,Count3,Count2,Count1,Count0;
  wire clk_1Hz;
  div #(50000000,32) nclk(clk,clk_1Hz);
  always@(posedge clk_1Hz)//步进速度信号控制,每按一次按键,速度逐渐加快。
    begin
	  if(rst==1)
	  Speed=2'd0;
    else
	 begin
	  if(in)
	   begin
	    if(Speed==2'd3)
	     Speed=2'd0;
	    else
        Speed=Speed+1'b1;	
      end
	  else 
	    Speed=Speed;
    end 
	 end

 always@(posedge clk)
  begin
  case(Speed)//内置步进速度自定义设置
	    2'b00:Time1=26'd50000000;//1Hz(1s一格)
	    2'b01:Time1=26'd20000000;//2.5Hz(0.4s一格)
	    2'b10:Time1=26'd5000000;//10Hz(0.1s一格)
	    2'b11:Time1=26'd1000000;//50Hz(0.02s一格)
       endcase  
  end
	
 always@(posedge clk)//右起第一个数码管的状态机循环,初始值为Stateout=3'b100,显示字母为“O”
	begin
	 if (rst==1)
	  Stateout0=3'b100;
	 else
	 begin
	  if(Count0==Time1)
	   begin
	    Count0=26'd0;
	   if(Stateout0==3'b110)
		  Stateout0=3'b000;
	   else 
	    Stateout0=Stateout0+3'b001;
	   end
	  else
	   begin
	    Count0=Count0+1'b1;
	    Stateout0=Stateout0;
	   end
	 end
	end
	
 always@(posedge clk)//右起第二个数码管的状态机循环,初始值为Stateout=3'b011,显示字母为“L”
	begin
	 if (rst==1)
	  Stateout1=3'b011;
	 else
	 begin
	  if(Count1==Time1)
	   begin
	    Count1=26'd0;
	   if(Stateout1==3'b110)
		  Stateout1=3'b000;
	   else 
	    Stateout1=Stateout1+3'b001;
	   end
	  else
	   begin
	    Count1=Count1+1'b1;
	    Stateout1=Stateout1;
	   end
	 end
	end
	
 always@(posedge clk)//右起第三个数码管的状态机循环,初始值为Stateout=3'b010,显示字母为“L”
	begin
	 if (rst==1)
	  Stateout2=3'b010;
	 else
	 begin
	  if(Count2==Time1)
	   begin
	    Count2=26'd0;
	   if(Stateout2==3'b110)
		  Stateout2=3'b000;
	   else 
	    Stateout2=Stateout2+3'b001;
	   end
	  else
	   begin
	    Count2=Count2+1'b1;
	    Stateout2=Stateout2;
	   end
	 end
	end
	
 always@(posedge clk)//右起第四个数码管的状态机循环,初始值为Stateout=3'b001,显示字母为“E”
	begin
	 if (rst==1)
	   Stateout3=3'b001;
	 else
	 begin
	  if(Count3==Time1)
	   begin
	    Count3=26'd0;
	    if(Stateout3==3'b110)
		  Stateout3=3'b000;
	   else 
	    Stateout3=Stateout3+3'b001;
	   end
	  else
	   begin
	    Count3=Count3+1'b1;
	    Stateout3=Stateout3;
	   end
	 end
	end
	
 always@(posedge clk)//右起第五个数码管的状态机循环,初始值为Stateout=3'b000,显示为“H”
	begin
	 if (rst==1)
	   Stateout4=3'b000;
	 else
	 begin
	  if(Count4==Time1)
	   begin
	    Count4=26'd0;
	   if(Stateout4==3'b110)
		  Stateout4=3'b000;
	   else 
	    Stateout4=Stateout4+3'b001;
	   end
	  else
	   begin
	    Count4=Count4+1'b1;
	    Stateout4=Stateout4;
	   end
	 end
	end
	
 always@(posedge clk)//右起第六个数码管的状态机循环,初始值为Stateout=3'b110,显示字母为“空”
	begin
    if (rst==1)
	   Stateout5=3'b110;
	 else
	 begin
	  if(Count5==Time1)
	   begin
	    Count5=26'd0;
	   if(Stateout5==3'b110)
		  Stateout5=3'b000;
	   else 
	    Stateout5=Stateout5+3'b001;
	   end
	  else
	   begin
	    Count5=Count5+1'b1;
	    Stateout5=Stateout5;
	   end
	 end
	end
endmodule

module State_right(clk,rst,Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0);//单稳态逆循环数码管状态机模块
  input clk,rst;
  output [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;//输出6个数码管的状态变化
  reg  [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
  parameter Time1=26'd25000000;//设置分频参数,固定步进速度。
  reg  [25:0]Count5,Count4,Count3,Count2,Count1,Count0;


	
 always@(posedge clk)//右起第一个数码管的状态机循环,初始值为Stateout=3'b101,显示字母为“空”
	begin
	 if (rst==1)
	  Stateout0=3'b101;
	 else
	 begin
	  if(Count0==Time1)
	   begin
	    Count0=26'd0;
	   if(Stateout0==3'b000)
		  Stateout0=3'b110;
	   else 
	    Stateout0=Stateout0-3'b001;
	   end
	  else
	   begin
	    Count0=Count0+1'b1;
	    Stateout0=Stateout0;
	   end
	 end
	end
	
 always@(posedge clk)//右起第二个数码管的状态机循环,初始值为Stateout=3'b100,显示字母为“O”
	begin
	 if (rst==1)
	  Stateout1=3'b100;
	 else
	 begin
	  if(Count1==Time1)
	   begin
	    Count1=26'd0;
	   if(Stateout1==3'b000)
		  Stateout1=3'b110;
	   else 
	    Stateout1=Stateout1-3'b001;
	   end
	  else
	   begin
	    Count1=Count1+1'b1;
	    Stateout1=Stateout1;
	   end
	 end
	end
	
 always@(posedge clk)//右起第三个数码管的状态机循环,初始值为Stateout=3'b011,显示字母为“L”
	begin
	 if (rst==1)
	  Stateout2=3'b011;
	 else
	 begin
	  if(Count2==Time1)
	   begin
	    Count2=26'd0;
	   if(Stateout2==3'b000)
		  Stateout2=3'b110;
	   else 
	    Stateout2=Stateout2-3'b001;
	   end
	  else
	   begin
	    Count2=Count2+1'b1;
	    Stateout2=Stateout2;
	   end
	 end
	end
	
 always@(posedge clk)//右起第四个数码管的状态机循环,初始值为Stateout=3'b010,显示字母为“L”
	begin
	 if (rst==1)
	   Stateout3=3'b010;
	 else
	 begin
	  if(Count3==Time1)
	   begin
	    Count3=26'd0;
	    if(Stateout3==3'b000)
		  Stateout3=3'b110;
	   else 
	    Stateout3=Stateout3-3'b001;
	   end
	  else
	   begin
	    Count3=Count3+1'b1;
	    Stateout3=Stateout3;
	   end
	 end
	end
	
 always@(posedge clk)//右起第五个数码管的状态机循环,初始值为Stateout=3'b001,显示为“E”
	begin
	 if (rst==1)
	   Stateout4=3'b001;
	 else
	 begin
	  if(Count4==Time1)
	   begin
	    Count4=26'd0;
	   if(Stateout4==3'b000)
		  Stateout4=3'b110;
	   else 
	    Stateout4=Stateout4-3'b001;
	   end
	  else
	   begin
	    Count4=Count4+1'b1;
	    Stateout4=Stateout4;
	   end
	 end
	end
	
 always@(posedge clk)//右起第六个数码管的状态机循环,初始值为Stateout=3'b000,显示字母为“H”
	begin
    if (rst==1)
	   Stateout5=3'b000;
	 else
	 begin
	  if(Count5==Time1)
	   begin
	    Count5=26'd0;
	   if(Stateout5==3'b00)
		  Stateout5=3'b110;
	   else 
	    Stateout5=Stateout5-3'b001;
	   end
	  else
	   begin
	    Count5=Count5+1'b1;
	    Stateout5=Stateout5;
	   end
	 end
	end
endmodule

module Display(clk,rst,Stateout5,Stateout4,Stateout3,Stateout2,
               Stateout1,Stateout0,DigtronCS_out,Digtron_out);//数码管扫描驱动显示模块
  input clk,rst;
  input [2:0] Stateout5,Stateout4,Stateout3,Stateout2,Stateout1,Stateout0;
  output [5:0] DigtronCS_out;//输出七段数码管的八位字码段显示信号
  output [7:0] Digtron_out;//输出六个数码管的六位片选信号
  reg [7:0] Digtron_out;
  
  reg [5:0] DigtronCS_out;
  reg [2:0] dis;
  parameter Timex=8'd200;//设置扫描显示频率为250kHz
  reg [7:0] Count; 

  always@(posedge clk)
	begin
   if(rst==1)
	  DigtronCS_out=6'b111110;
	else
	begin
	  if(Count==Timex)
	   begin
	    Count=8'd0;
		 DigtronCS_out={DigtronCS_out[4:0],DigtronCS_out[5]};//数码管片选扫描驱动状态机循环
		end
	  else
	   begin
	    Count=Count+1'b1;
		 DigtronCS_out=DigtronCS_out; 
		end
	end
	end
	
	always@( posedge clk)
	 begin
	 case(DigtronCS_out)
	  6'b111110:dis=Stateout0;
	  6'b111101:dis=Stateout1;
	  6'b111011:dis=Stateout2;
	  6'b110111:dis=Stateout3;
	  6'b101111:dis=Stateout4;
	  6'b011111:dis=Stateout5;
	  endcase
	 end
	
	always@(posedge clk)	//数码管不同的状态对应字段显示的字母编码
	 begin
	 case(dis)
	 3'b000:Digtron_out=8'h6e;//字母“H”
	 3'b001:Digtron_out=8'h9e;//字母“E”
	 3'b010:Digtron_out=8'h1c;//字母“L”
	 3'b011:Digtron_out=8'h1c;//字母“L”
	 3'b100:Digtron_out=8'hfc;//字母“0”
	 3'b101:Digtron_out=8'h00;//空
	 3'b110:Digtron_out=8'h00;//空
	 endcase
	 end
endmodule

module select_dir(clk,in,S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10,S5,S4,S3,S2,S1,S0);//移动方向选择模块
  input clk,in;
  input [2:0] S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10;
  output [2:0] S5,S4,S3,S2,S1,S0;
  reg [2:0] S5,S4,S3,S2,S1,S0;
  wire clk_1Hz;
  reg[4:0] count;
 
  div #(50000000,32) nclk(clk,clk_1Hz);//设置频率为1S;
  
  always@(posedge clk_1Hz)
  begin
   if(in==1'b1)//in输入时,开始计时
	    count=count+1'b1; 
	else
      count=5'd0;	//in无输入时,为初始状态
  end
 
 always@(posedge clk)
  begin
	  if(count==5'd0)//初始状态为正循环
		  begin
		    S5=S15;
			 S4=S14;
			 S3=S13;
			 S2=S12;
			 S1=S11;
			 S0=S10;
		  end
		 else
		  begin 
		  if(count<=5'd10)//每当计时不到5s的时候,启动单稳态逆循环
			 begin 
		    S5=S25;
			 S4=S24;
			 S3=S23;
			 S2=S22;
			 S1=S21;
			 S0=S20;
          end
         else //单稳态逆循环定时时间为5s,计时超过5s,自动返回到正循环
          begin 
			 S5=S15;
			 S4=S14;
			 S3=S13;
			 S2=S12;
			 S1=S11;
			 S0=S10;
	       end		 
		  end
	end
endmodule 

module Hello(clk,rst,in0,in1,DigtronCS_out,Digtron_out);//顶层文件
 input clk,rst,in0,in1;
 output [5:0] DigtronCS_out;
 output [7:0] Digtron_out;
 

 wire[2:0] S15,S14,S13,S12,S11,S10;
 wire [2:0] S25,S24,S23,S22,S21,S20;
 wire [2:0] S5,S4,S3,S2,S1,S0;
 

 State_left u1(clk,rst,~in0,S15,S14,S13,S12,S11,S10);//正循环数码管状态机模块
 State_right u2(clk,rst,S25,S24,S23,S22,S21,S20);//单稳态逆循环数码管状态机模块
 select_dir u3(clk,in1,S25,S24,S23,S22,S21,S20,S15,S14,S13,S12,S11,S10,S5,S4,S3,S2,S1,S0);//方向选择模块
 Display u4(clk,rst,S5,S4,S3,S2,S1,S0,DigtronCS_out,Digtron_out);//数码管显示模块
endmodule 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值