EDA课设之幸运老虎机的设计

前言

     这是作者第一次做eda有关的课设,选题为“幸运老虎机的设计”。功能逻辑为本人以及一位小伙伴原创,上机显示部分参考了老师给的代码。整体编写流程就是先写源代码,然后通过仿真调试逻辑,最终基本逻辑无误后再下载到板子上运行调试。

    在仿真阶段,这篇文章写的很好,我就是按照这个步骤来的~

    最后希望能对大家的编写提供一定的借鉴,也欢迎大家提问或者给出建议~~~

 

问题简介

    主要功能为:设计一个游戏机,有三位数码管显示0—7之间的数码,按下按钮,三个数码管循环显示,抬起按钮,显示停止,当显示内容相同时,为赢。  要求:  
    1、三个数码管循环显示的速度不同。
    2、停止时的延迟时间也要不同。
    3、游戏胜利是,发光二极管闪烁提示。
    4、有“作弊”功能,按下该功能按键后,每次都能赢。

 

基本实现思路

1、利用时钟分频来使得数字增加的速度不同。

2、四个随机数r1、r2、r3、rand跟随时间变化。

 (1)正常情况下,最终显示的三个数字,是stop时刻三个不同的随机数r1、r2、r3。

 (2)作弊(cheat为1)情况下,最终显示的三个数字都是cheat信号为1时刻的随机数rand。

3、发光二极管用不断取反实现闪烁,注意stop信号下次开始的时候会停止闪烁。

 

注意事项以及说明

1、为了保证最后停止的时间不同,我们采用了不同的随机数作为最后的数字的方法。

2、为了最后停止的时候不会遇到这个随机数就停下,我们选择不管stop的时刻什么情况,都需要至少再跑一轮才能停下。

3、随机函数random在仿真阶段可以写到testbench里面,但是在模块里面是不支持的。

   这里我们采用了不断乘以限定的数字,需要的时候对8取余传入即可得到一种随机数。

   对于这种方法,我有几点说明:

      (1)因为是根据时间来随机,这可能在某种程度上比随机算法更优。

      (2)需要判断数字溢出的情况以及可能取到负数的情况,应加以规避。

      (3)随机数传入的时刻需要注意,不能一直在赋值,一旦信号确定,传入后随机数字记录的数字就不能再发生变化。

4、最终数字显示到数码管上的时候需要进行对应的译码。

 

环境:

源代码编辑环境:

    Quartus (Quartus Prime 18.1) Lite Edition

仿真环境:

    ModelSim - Intel FPGA Starter Edition 10.5b (Quartus Prime 18.1)

板子型号

上机驱动

 

控制信号

输入信号:

(1)stop信号控制循环的开始与停止。

(2)cheat信号控制作弊功能。

输出信号:

(1)out1、out2、out3对应三个循环输出的数字。

(2)tip信号作为最终三个数字相同时候的闪烁提示。

 

仿真阶段源代码(.v文件)

module lhj(in,cheat,stop,r1,r2,r3,out1,out2,out3,tip,rand);
input in,cheat,stop;
input [2:0] r1,r2,r3,rand;
output[2:0] out1,out2,out3;
output tip;
reg tip;
reg[2:0] out1,out2,out3;
integer flag1=0,flag2=0,flag3=0;
integer num1,num2,num3;
integer t1,t2,t3;
integer n1=0,n2=0,n3=0;
initial
begin
out1=3'b000;
out2=3'b000;
out3=3'b000;
t1=-1;
t2=-2;
t3=-3;
tip=1'b0;
end
always @(in)
	begin
	n1=n1+1;
	if(stop==0 && n1%2==0) 
	begin
		out1=out1+1;
		if(cheat==0)
		num1=r1;
		else if(cheat==1)
		num1=rand;
	end
	if(stop==1 && n1%2==0)
	begin
	if(flag1==0)
	begin
		if(out1==num1)
		begin
			flag1=1;
			out1=out1+1;
		end
		else
		out1=out1+1;
	end
	else if(flag1==1) 
	begin
	if(out1!=num1)
		out1=out1+1;
	else
		flag1=2;
	end	
	else if(flag1==2)
		begin
		out1=out1;
		t1=out1;
		end
	end
	end
	
always @(in)
	begin
	n2=n2+1;
	if(stop==0 && n2%3==0) 
	begin
		out2=out2+1;
		if(cheat==0)
		num2=r2;
		else if(cheat==1)
		num2=rand;
	end
	if(stop==1 && n2%3==0)
	begin	
	if(flag2==0)
	begin		
		if(out2==num2)
		begin
			flag2=1;
			out2=out2+1;
		end
		else
		out2=out2+1;
	end
	else if(flag2==1) 
	begin
	if(out2!=num2)
		out2=out2+1;
	else
		flag2=2;
	end	
	else if(flag2==2)
		begin
		out2=out2;
		t2=out2;
		end
	end
	end
	
	
always @(in)
	begin
	n3=n3+1;
	if(stop==0 && n3%4==0) 
	begin
		out3=out3+1;
		if(cheat==0)
		num3=r3;
		else if(cheat==1)
		num3=rand;
	end
	if(stop==1 && n3%4==0)
	begin
	if(flag3==0)
	begin
		if(out3==num3)
		begin
			flag3=1;
			out3=out3+1;
		end
		else
		out3=out3+1;
	end
	else if(flag3==1) 
	begin
	if(out3!=num3)
		out3=out3+1;
	else
		flag3=2;
	end	
	else if(flag3==2)
		begin
		out3=out3;
		t3=out3;
		end
	end
	end

always @(posedge in)
begin


if(t1==t2 && t2==t3)
	begin
	tip=~tip; 
	end
end
	
endmodule

仿真阶段testbench文件(.vt文件)

// Copyright (C) 2018  Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions 
// and other software and tools, and its AMPP partner logic 
// functions, and any output files from any of the foregoing 
// (including device programming or simulation files), and any 
// associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License 
// Subscription Agreement, the Intel Quartus Prime License Agreement,
// the Intel FPGA IP License Agreement, or other applicable license
// agreement, including, without limitation, that your use is for
// the sole purpose of programming logic devices manufactured by
// Intel and sold by Intel or its authorized distributors.  Please
// refer to the applicable agreement for further details.

// *****************************************************************************
// This file contains a Verilog test bench template that is freely editable to  
// suit user's needs .Comments are provided in each section to help the user    
// fill out necessary details.                                                  
// *****************************************************************************
// Generated on "06/14/2019 08:40:20"
                                                                                
// Verilog Test Bench template for design : lhj
// 
// Simulation tool : ModelSim (Verilog)
// 

`timescale 1 ps/ 1 ps
module lhj_vlg_tst();
// constants                                           
// general purpose registers
reg eachvec;
// test vector input registers
reg cheat;
reg in;
reg stop;
reg [2:0] r1;
reg [2:0] r2;
reg [2:0] r3;
reg [2:0] rand;
integer seed;
// wires                                               
wire [2:0]  out1;
wire [2:0]  out2;
wire [2:0]  out3;
wire tip;

// assign statements (if any)                          
lhj i1 (
// port map - connection between master ports and signals/registers   
	.cheat(cheat),
	.in(in),
	.r1(r1),
	.r2(r2),
	.r3(r3),
	.out1(out1),
	.out2(out2),
	.out3(out3),
	.stop(stop),
	.tip(tip),
	.rand(rand)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin                          
in=1'b0;
stop=0;
seed=1;
cheat=0;
forever #20 in=~in;            
// --> end                                             
$display("Running testbench");                       
end                                                    
always                                                 
// optional sensitivity list                           
// @(event1 or event2 or .... eventn)                  
begin                                                  
// code executes for every event on sensitivity list   
// insert code here --> begin   
#53 cheat=1;                 
#156 stop=1;                                
// --> end                                             
end  
always @(posedge in)
begin
r1<={$random(seed)}%8;
r2<={$random(seed)}%8;
r3<={$random(seed)}%8;
rand<={$random(seed)}%8;
end
                                                  
endmodule

上机源文件(.v文件,内含注释)

module lhj ( 
//input 
input                    cheat,    //作弊信号
input                    stop,     //停止信号和开始信号
input                    sys_clk        ,//系统时钟
input                    sys_rst_n      ,//复位时钟

//output 
output wire              seg_c1         ,//数码管位选信号
output wire              seg_c2         ,
output wire              seg_c3         ,
output wire              seg_c4         ,
output reg               tip,           //闪烁提示灯
output reg               seg_a          ,//数码管段选信号
output reg               seg_b          ,
output reg               seg_c          ,
output reg               seg_e          ,
output reg               seg_d          ,
output reg               seg_f          ,
output reg               seg_g          ,
output reg               seg_h          
				  
              );

//parameter define 
parameter WIDTH2 = 26;
parameter WIDTH = 5;
parameter SIZE  = 8;
reg[2:0] out1,out2,out3;
reg[2:0] a1,a2,a3;
//reg define 
reg    [3:0]             counter                ;
reg    [WIDTH2-1:0]      count                  ;
reg    [ 3:0]            disp_data              ;

reg    [SIZE-1:0]        dat                    ;

reg                      disp_clk               ;

reg    [25:0]            clk_cnt                ;
reg    [25:0]            clk_cnt1                ;
reg    [25:0]            clk_cnt2                ;

reg    [15:0]            scan_cnt                ;
reg    [ 3:0]            segled_bit_sel          ;


reg                     segled_a          ;
reg                     segled_b          ;
reg                     segled_c          ;
reg                     segled_e          ;
reg                     segled_d          ;
reg                     segled_f          ;
reg                     segled_g          ;
reg                     segled_h          ;
integer flag1=0,flag2=0,flag3=0;//标志,判断当前数字是否与随机数相等,并且使当前数字在经过一轮变化
integer num1,num2,num3;//最后停在的数字
integer t1,t2,t3;//记录最后停在的数字
integer n1=0,n2=0,n3=0;
integer r1,r2,r3;//随机数
reg[18:0] c;//记录停止前的时间
reg[18:0] rand;//作弊信号的记录时间
reg seed;
reg seed1,seed2,seed3;
parameter half_sec = 25'd25_000_000;
reg [24:0] countt;


initial  //将所有值初始化
begin
out1=0;
out2=0;
out3=0;
c=0;
t1=-1;//由于要判断tip,先将三个输出置为不同值
t2=-2;
t3=-3;
tip=1'b1;
seed=1;
seed1=0;
seed2=0;
seed3=0;
end
//wire define 

/*******************************************************************************************************
**                              Main Program    
**  主要功能为:设计一个游戏机,有三位数码管显示0—7之间的数码,按下按钮,三个数码管循环显示,抬起按钮,显示停止,当显示内容相同时,为赢。  要求:  
(1)三个数码管循环显示的速度不同 
(2)停止时的延迟时间也要不同 
(3)游戏胜利是,发光二极管闪烁提示
(4)有“作弊”功能,按下该功能按键后,每次都能赢
********************************************************************************************************/


// clk cnt for DISP data increase
always @(posedge sys_clk or negedge sys_rst_n) begin //在复位时钟为1时使scan_cnt+1
   if (sys_rst_n ==1'b0)  
       scan_cnt <= 16'b0;
   else 
	    scan_cnt <= scan_cnt + 16'b1;
end

//  gen segled bit sel by cnt high 2 bit
always @(posedge sys_clk or negedge sys_rst_n) begin //通过scan_cnt来选择数码管的位选
   if (sys_rst_n ==1'b0)  
       segled_bit_sel <= 4'b0001;
	else if ( scan_cnt[15:14] == 2'b00 )
       segled_bit_sel <= 4'b0001;
   else if ( scan_cnt[15:14] == 2'b01 )
       segled_bit_sel <= 4'b0010;
	else if ( scan_cnt[15:14] == 2'b10 )
       segled_bit_sel <= 4'b0100;
   else if ( scan_cnt[15:14] == 2'b11 )
       segled_bit_sel <= 4'b1000;		 
   else ;
end
 
// clk cnt for DISP data increase
always @(posedge sys_clk or negedge sys_rst_n) begin //将时钟分频,目的是使三个数码管的速度不同
   if (sys_rst_n ==1'b0)  
       clk_cnt <= 26'b0;
   else if ( clk_cnt == 26'd10000000 )
       clk_cnt <= 26'b0;
	else
       clk_cnt <= clk_cnt + 26'b1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin 
   if (sys_rst_n ==1'b0)  
       clk_cnt1 <= 26'b0;
   else if ( clk_cnt1 == 26'd20000000 )
       clk_cnt1 <= 26'b0;
	else
       clk_cnt1 <= clk_cnt1 + 26'b1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin 
   if (sys_rst_n ==1'b0)  
       clk_cnt2 <= 26'b0;
   else if ( clk_cnt2 == 26'd30000000 )
       clk_cnt2 <= 26'b0;
	else
       clk_cnt2 <= clk_cnt2 + 26'b1;
end

always @(posedge sys_clk or negedge sys_rst_n) begin //记录开始时到stop为1时的时间,作为随机数的种子
	if (sys_rst_n ==1'b0)  
        c <= 4'd0;
    else if ( clk_cnt == 26'd10000000 ) begin
	 c<=c+1;
	 end
	 end
always @(posedge sys_clk or negedge sys_rst_n) begin //记录开始时到cheat为1时的时间,作为作弊随机数的种子
	if (sys_rst_n ==1'b0)  
        rand <= 4'd0;
    else if ( clk_cnt == 26'd10000000 ) begin
	 if(cheat==0)
	 rand<=rand+1;
	 else
	 rand<=rand;
	 end
	 end
/*以下三个always为控制数码管,在stop为0时使数字一直加1,当stop为1时,flag为0表示未到达随机数位置继续加1,
flag为1表示当前数字已达到随机数但是还需要继续循环显示一轮,以延迟停止,flag为2表示已达到延迟显示的要求,之后的输出不再变化*/
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (sys_rst_n ==1'b0)  
        out1 <= 4'd0;
    else if ( clk_cnt == 26'd10000000 ) begin
	 if(stop==0) 
	 begin
	 t1=-1;
	 flag1=0;
        out1 <= out1+4'b1;
		  if(cheat==0)
		  begin
		  r1=(c*123)%8;//使用时间作为种子,将该数加倍并取余
			num1=r1;
			end
			else if(cheat==1)
			num1=rand%8;
			end
	else if(stop==1)
	begin
	if(flag1==0)
	begin
		if(out1==num1)
		begin
			flag1=1;
			out1<=out1+4'b1;
		end
		else
		out1<=out1+4'b1;
	end
	else if(flag1==1) 
	begin
	if(out1!=num1)
		out1<=out1+4'b1;
	else
		flag1=2;
	end	
	else if(flag1==2)
		begin
		out1<=out1;
		t1<=out1;//记录最后的输出,作为tip闪烁提示的判断条件
		end
	end
	else ;
	end
	 else ;
	 end
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (sys_rst_n ==1'b0)  
        out2 <= 4'd0;
    else if ( clk_cnt1 == 26'd20000000 ) begin
	 if(stop==0) 
	 begin
	 t2=-2;
			flag2=0;
        out2 <= out2+4'b1;
		  if(cheat==0)
		  begin
		  r2=(c*545)%8;
			num2=r2;
			end
			else if(cheat==1)
			num2=rand%8;
			end
	else if(stop==1)
	begin
	if(flag2==0)
	begin
		if(out2==num2)
		begin
			flag2=1;
			out2<=out2+4'b1;
		end
		else
		out2<=out2+4'b1;
	end
	else if(flag2==1) 
	begin
	if(out2!=num2)
		out2<=out2+4'b1;
	else
		flag2=2;
	end	
	else if(flag2==2)
		begin
		out2<=out2;
		t2<=out2;
		end
	end
	else ;
	end
	 else ;
	 end


always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (sys_rst_n ==1'b0)  
        out3 <= 4'd0;
    else if ( clk_cnt2 == 26'd30000000 ) begin
	 if(stop==0) 
	 begin
	 t3=-3;
	 flag3=0;
        out3 <= out3+4'b1;
		  if(cheat==0)begin
		  r3=(c*978)%8;
			num3=r3;end
			else if(cheat==1)
			num3=rand%8;
			end
	else if(stop==1)
	begin
	if(flag3==0)
	begin
		if(out3==num3)
		begin
			flag3=1;
			out3<=out3+4'b1;
		end
		else
		out3<=out3+4'b1;
	end
	else if(flag3==1) 
	begin
	if(out3!=num3)
		out3<=out3+4'b1;
	else
		flag3=2;
	end	
	else if(flag3==2)
		begin
		out3<=out3;
		t3<=out3;
		end
	end
	else ;
	end
	 else ;
	 end

always @(posedge sys_clk or negedge sys_rst_n) begin //对t1,t2,t3进行判断,如果相同则表示老虎机最后三个输出相等,tip闪烁
    if (sys_rst_n ==1'b0)  
        tip <= 4'd0;
    else if ( clk_cnt2 == 26'd30000000 ) begin
		if(t1==t2 && t2==t3 && stop==1)
		tip=~tip;
		else tip=0;
		end
	 end

// sel dsip 4 bit data	
always @(segled_bit_sel) begin //根据位选信号将不同输出赋给不同的数码管
    if ( segled_bit_sel == 4'b0001 ) 
        disp_data =  out1 ;
    else if ( segled_bit_sel == 4'b0010 ) 
        disp_data = out2 ;
    else if (segled_bit_sel == 4'b0100 ) 
        disp_data = out3 ;
	 else 
        disp_data = 8 ;	 
end

// SEGLED decode from disp data			
always @(*) begin //数码管段选判断,将数码管输出置为相应的十进制数字
    case (disp_data)
         7        :     
			            begin
			                segled_a = 1 ;   
								 segled_b = 1 ;   
			                segled_c = 1 ;   
								 segled_d = 0 ;   
								 segled_e = 0 ;   
								 segled_f = 0 ;   
			                segled_g = 0 ;   
								 segled_h = 0 ;   
			            end 
         6        :
			            begin
			                segled_a = 1 ;   
								 segled_b = 0 ;   
			                segled_c = 1 ;   
								 segled_d = 1 ;   
								 segled_e = 1 ;   
								 segled_f = 1 ;   
			                segled_g = 1 ;   
								 segled_h = 0 ;   
			            end 			
         5        :
			            begin
			                segled_a = 1 ;   
								 segled_b = 0 ;   
			                segled_c = 1 ;   
								 segled_d = 1 ;   
								 segled_e = 0 ;   
								 segled_f = 1 ;   
			                segled_g = 1 ;   
								 segled_h = 0 ;   
			            end 			
         4        :
			            begin
			                segled_a = 0 ;   
								 segled_b = 1 ;   
			                segled_c = 1 ;   
								 segled_d = 0 ;   
								 segled_e = 0 ;   
								 segled_f = 1 ;   
			                segled_g = 1 ;   
								 segled_h = 0 ;   
			            end 			
         3        :
			            begin
			                segled_a = 1 ;   
								 segled_b = 1 ;   
			                segled_c = 1 ;   
								 segled_d = 1 ;   
								 segled_e = 0 ;   
								 segled_f = 0 ;   
			                segled_g = 1 ;   
								 segled_h = 0 ;   
			            end 			
         2        : 
			            begin
			                segled_a = 1 ;   
								 segled_b = 1 ;   
			                segled_c = 0 ;   
								 segled_d = 1 ;   
								 segled_e = 1 ;   
								 segled_f = 0 ;   
			                segled_g = 1 ;   
								 segled_h = 0 ;   
			            end 			
         1        :
			            begin
			                segled_a = 0 ;   
								 segled_b = 1 ;   
			                segled_c = 1 ;   
								 segled_d = 0 ;   
								 segled_e = 0 ;   
								 segled_f = 0 ;   
			                segled_g = 0 ;   
								 segled_h = 0 ;   
			            end 			
         0        :  
			            begin
			                segled_a = 1 ;   
								 segled_b = 1 ;   
			                segled_c = 1 ;   
								 segled_d = 1 ;   
								 segled_e = 1 ;   
								 segled_f = 1 ;   
			                segled_g = 0 ;   
								 segled_h = 0 ;   
			            end 			
         default  :      
						   begin
			                segled_a = 0 ;   
								 segled_b = 0 ;   
			                segled_c = 0 ;   
								 segled_d = 0 ;   
								 segled_e = 0 ;   
								 segled_f = 0 ;   
			                segled_g = 0 ;   
								 segled_h = 0 ;   
			            end 
    endcase
end

// assign seg , low active
always @(*) begin //由于开发板的有效信号为0,将所有段选信号置反
    seg_a = ~segled_a ;
    seg_b = ~segled_b ;
    seg_c = ~segled_c ;
    seg_d = ~segled_d ;
    seg_e = ~segled_e ;
    seg_f = ~segled_f ;
    seg_g = ~segled_g ;
    seg_h = ~segled_h ;
end

// assign bit sel to SEGLED pin, low active
assign seg_c1 = ~( segled_bit_sel == 4'b0001 );//同段选信号,将位选信号置反
assign seg_c2 = ~( segled_bit_sel == 4'b0010 );
assign seg_c3 = ~( segled_bit_sel == 4'b0100 );
assign seg_c4 = ~( segled_bit_sel == 4'b1000 );

endmodule
//end of RTL code  

最终显示情况:

1、正常模式下(只打开第一个拨码开关)

    显示结果为随机数字,此次显示三个数字不同,因此没有进行闪烁胜利提示。

   

2、作弊模式下(第一个和第二个拨码开关均打开)

    最终显示数字必定相同到一个确定的随机数字,此次显示为4,因此第五号发光二极管闪烁提示。

  图1、闪烁灯亮                                                             图2、闪烁灯灭

  

 

作为一名AI助手,我可以为您提供关于EDA课设日历电路设计的一些参考信息。请注意,这只是一个参考,您需要根据自己的具体要求进行修改和完善。 首先,您需要确定日历电路的功能和要求,例如: 1. 显示当前日期和时间 2. 支持自动更新时间 3. 支持手动设置日期和时间 4. 支持闹钟功能 接下来,您需要设计电路图和PCB板。这里可以使用EDA软件,如Altium Designer、Eagle PCB等。设计电路图时需要考虑以下几个方面: 1. 时钟电路设计:使用RTC芯片或者晶振+微处理器实现时钟电路。 2. 显示电路设计:使用数码管或者液晶显示屏显示日期和时间。 3. 输入电路设计:使用按钮或者旋钮实现手动设置日期和时间。 4. 控制电路设计:使用微处理器或者逻辑门电路实现控制电路,控制显示、时钟等模块的工作。 在设计PCB板时,需要考虑以下几个方面: 1. PCB尺寸和形状:根据电路图设计合适的PCB尺寸和形状。 2. 元器件布局:合理布局元器件,避免产生干扰和噪音。 3. 电源供应:设计合适的电源供应电路,保证电路正常工作。 4. 线路走向:使线路走向简单明了,便于制造和维护。 最后,您需要进行电路测试和调试,确保电路能够正常工作。这需要使用示波器、信号发生器等仪器进行测试,检查电路的各个模块是否正常工作,是否满足设计要求。 以上是一个简单的EDA课设日历电路设计的大致流程和步骤,希望对您有所帮助。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值