FPGA 06 基础 led流水灯

在这里插入图片描述

FPGA 06 基础 led流水灯

在这里插入图片描述
模块名称: led_flow

主要功能 :每隔一段时间,输出 led[x:0] 所有电平进行循环移位,对外部电路实现控制4个led灯的流水灯效果。

实现(设计)流程: 1、内部使用一个定时器计数器,分两个部分

​ ①计数到设置值,重新开始计数

​ ②计数到设置值,led[x:0]循环左移或者右移,否则保持不变。

​ led_r <= {led_r[2:0],led_r[3]}; //使用位拼接的方式进行移位操作

  • led_flow.v 文件

module led_flow(
 
 //端口列表
  clk50M ,
  Rst_n  ,
 
  led
);  
// 这里类似与 C 语言的函数定义,也可以使用类似于C语言的定义,如下所示:
// module led_flash(input clk50M ,input Rst_n , reg [3:0]led);  
// 上述可以看到


//端口定义
 input clk50M ;
 input Rst_n  ;
 
 //output wire [3:0]led ; //定义的是一个【线网】类型的信号
 output [3:0]led ; //定义的是一个寄存器输出的端口
 
 //传参,修改定时器的值,方便在后续的参数传递时
 //仅仅只需要修改一个参数变量即可
 // 1、减少修改文件的数目
 // 2、减少修改出现的错误
 parameter CNT_MAX = 25'd24_999_999 ; //类似与  C 语言的 #define
 
 reg [24:0]cnt ;  //定义一个25位的寄存器,用做计数
 
 //always 语句分析  
 // 总是关注 clk50M 信号的上升沿或者 Rst_n 的下降边沿,那么就会
 // 执行 always 里面的语句
 // always 语句,是不断在执行和处理的,
 // 个人理解: always 会不断执行alway 里面到下一个always 块之前的语句
 // 这里面属于一个单独的always 块,相当于分片进行设计和操作
 // 此外,always 和另外一个always 是互不影响的
 
 //第一个always块
	 always@(posedge clk50M or negedge Rst_n) 
	 //  posedge : 上升沿   negedge: 下降沿
	 if(!Rst_n) //判断 复位引脚是否位低电平,如果是,则进入if语句执行一些操作
		cnt <=25'd0 ;  //进入if语句,表示Rst_n是低电平,则进入复位
	 else if(cnt == CNT_MAX) //判断是否到达定时器的值,到了,对cnt 清零
		cnt <= 25'd0 ;
	 else //未满足上面的条件,则表示既没有复位,计数器的值也没有达到设定的值
		cnt <= cnt +1'b1 ; // cnt++
	
//第二个always 块,不影响其他always块的执行
/*  ① flow 流水灯操作
	 reg [3:0]led_r ; //定义一个4位的寄存器
	 always@(posedge clk50M or negedge Rst_n) 
	 if(!Rst_n)
		led_r <= 4'b0001;  // 4'b 表示的是四位的二进制数赋值 
	 else if(cnt == CNT_MAX) begin //进入 else if 执行的语句
		if(led_r ==  4'b0000) //判断是否全部左移完成
			led_r <= 4'b0001 ; //执行 赋值 0001
		else
			led_r <= led_r <<1 ; //否则左移一位
	 end  //表示的是 eles if 判断执行的语句
	 else //定时器没到,保持当前状态
		led_r <=led_r ; //对寄存器进行操作 
		
	 assign led = ~ led_r ; //寄存器的值取反 赋值给 led 灯
	 // assign: 对应的是连线,是组合逻辑输出, 此时这里的 [3:0]led  必须保证是 wire [3:0]led   类型的才可以直接连接
	 // 如果是 reg  [3:0]led ,则使用assign 是会出错
*/

//  ②flow 流水灯操作
	 reg [3:0]led_r ; //定义一个4位的寄存器
	 always@(posedge clk50M or negedge Rst_n) 
	 if(!Rst_n)
		led_r <= 4'b0001;  // 4'b 表示的是四位的二进制数赋值 
	 else if(cnt == CNT_MAX) begin //进入 else if 执行的语句
		if(led_r ==  4'b0000) //判断是否全部左移完成
			led_r <= 4'b0001 ; //执行 赋值 0001
		else
			led_r <= {led_r[2:0],led_r[3]}; //否则左移一位,使用位拼接的方式进行移位操作
	 end  //表示的是 eles if 判断执行的语句
	 else //定时器没到,保持当前状态
		led_r <=led_r ; //对寄存器进行操作 
		
	 assign led = ~ led_r ; //寄存器的值取反 赋值给 led 灯
	 // assign: 对应的是物理世界中的连线,是组合逻辑输出, 此时这里的 [3:0]led  必须保证是 wire [3:0]led   类型的才可以直接连接
	 // 如果是 reg  [3:0]led ,则使用assign 是会出错


 endmodule
 
 
 // 编辑完成上述步骤后,进行分析和综和进行编译 按钮  start Analysie & Synthesis
 
 
  • led_flow_tb.v文件

`timescale 1ns/1ns
//建议上面直接复制粘贴,不然容易出错
`define clock_period 20  //定义一个仿真的时钟周期的时间是20ns

module led_flow_tb;
 //端口模块测试的端口定义
 //测试模块编写流程
 reg clk50M ;
 reg Rst_n  ; 
 //output wire [3:0]led ; //定义的是一个【线网】类型的信号
 wire [3:0]led ; //定义的是一个寄存器输出的端口

 //测试模块函数,重定义了一个新的 测试模块名称: led_flash0
 //传递参数进入
  //测试模块函数
 led_flow 
 #(
	.CNT_MAX(25'd249)   // 这里表示,在我们仿真的时候修改
								// led_flash 模块里面的 CNT_MAX 修改为 25’d2499 进行仿真测试
								// 参数传递的好处,不需要修改源文件的蚕食
								// 保证实际电路的输出效果时不会出错
  )
 //加入测试接口和函数
 led_flow0(
  .clk50M(clk50M) ,
  .Rst_n(Rst_n)   ,
  .led(led)
);  

/*
//实际电路仿真, CNT_MAX 的参数不可更改 ,若 CNT_MAX参数,则实际电路仿真时会出错
//其余和逻辑仿真保持一致即可,注: 可以和上面的近对比。
 led_flow 
 //加入测试接口和函数
 led_flow0(
  .clk50M(clk50M) ,
  .Rst_n(Rst_n)   ,
  .led(led)
);  
*/
 
//设定初始状态
	initial clk50M =1 ; //初始化 clk50M = 1 定义一个
//
// always #10   clk50M = ~clk50M ; //延时10ns,时钟翻转一次,这样的话,时钟周期就是 20ns
// 也可以使用下面的方式进行操作 ,一个周期有 10ns 的低电平,10ns的高电平
// 每个电平持续时间是 10ns , 则一个总的时钟信号周期就是 20ns
	always #(`clock_period/2) clk50M = ~clk50M ;
	
// 初始化信号,(begin   end)
// 出现begin  后面必须有 end
// 开机执行一次

	initial begin
		Rst_n = 0 ;
		#(`clock_period*20+1);
		Rst_n =1 ; //延时20个周期+1,避免异步对准(齐)
		
		#(`clock_period*25000+1); //仿真的延时时间
		
		$stop ; //仿真停止
		
	end
 
endmodule
 
 // 编写完成测试后,设置该源代码位仿真代码
 // Assigment->Settings --> EDA Tool Settings 
 // --> Simulation --> Compile test bench 
 // 添加测试的文件 (点击 Test Benches --> New)
 // 点击Filename 后面跟随的(...)--> 添加自己的测试文件
 // 添加完成以后,在TestBench 里面添加 测试的文件名称(不要添加.v这个后缀) 即可
 // 保存--> Ok--> apply 即可
 
 // 主界面 --> Tools -->  Run Simulation --> RTL Simulation or Gate Level Simulation
 
 // 重新仿真操作
 // 仿真出错 --> 修改好文件 -> 在仿真软件 ->Library -> Recompile  
 //  Reset --> Run All
 // 出现仿真时间过长--> break 进行停止
 
 
 // 电路图视图 操作: 看内部实际电路的连接方式
 // Tools -> NetList Viwers -> RTL Viewer 
 
 
 // 逻辑仿真和模拟实际情况下的仿真 的对比(不同点)
 
 // #(.CNT_MAX(25'd249)) 在逻辑电路可以传递参数
 // 实际电路中不可以传递参数
 
 // 最后,配置IO 口进行下载到芯片中
 // 2种方式
 // 方式1、选择Pin planner  配置选中对应的IO口   Assigment->Pin Planner 
 // 方式2、	①编写自动化脚本文件 new -> File -> Tcl_script.tcl 文件 (针对IO口较多的情况)
 //        	②编写完成后, Tools -> Tcl_script --> 导入 --> run  执行编写的脚本文件
 
 
 
 

.tcl 脚本文件

set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clk50M
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to Rst_n
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to led[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to led[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to led[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to led[3]

set_location_assignment PIN_E1 -to clk50M
set_location_assignment PIN_E16 -to Rst_n 
set_location_assignment PIN_A2 -to led[0]
set_location_assignment PIN_B3 -to led[1]
set_location_assignment PIN_A4 -to led[2]
set_location_assignment PIN_A3 -to led[3]
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值