FPGA学习笔记(二):时序逻辑之计数器

与组合逻辑(给定输入,输出是确定的,与时间无关)相比较,时序逻辑不仅仅与输入信号相关,还与时钟信号相关。

D触发器:在上升沿时(CLK)才将输出(Q)修改为当前的输入值(D),具有存储的性质。

1s 闪烁的 LED 灯

注意根据时钟频率计算计数量。

时序逻辑使用 posedge 表示时钟信号。

module led_flash (
    clk,
    reset_n,
    led
);
    input clk, reset_n;
    output reg led;
    
    reg [24:0] counter;
    
    // ÍÆŒö·ÖΪÁœžö always£¬ÓÐÖúÓÚ·ÖÎö×ÛºÏ
    
    always@(posedge clk or negedge reset_n) // œöœöʱÖÓÉÏÉýÑصœÀŽ»òÕßžŽÎ»ÐźŲúÉú²Å»áŒ€»îÏÂÃæµÄŽúÂë¿é
        if(!reset_n)
                counter <= 0; // ·Ç×èÈûž³Öµ
        else if(counter == 25000000) // ×¢ÒâÕâÀïÓŠžÃ 25000000 - 1
                counter <= 0; // ºÍÉÏÃæÒ»ÐÐÒ»Æð×ö£¬ÐèҪʹÓÃbegin¿éʵÏÖ
        else
            counter <= counter + 1'd1;
        
    always@(posedge clk or negedge reset_n) // œöœöʱÖÓÉÏÉýÑصœÀŽ»òÕßžŽÎ»ÐźŲúÉú²Å»áŒ€»îÏÂÃæµÄŽúÂë¿é
        if(!reset_n)
                led <= 0;
        else if(counter == 25000000) 
                led <= !led;
        else
            counter <= counter + 1'd1;
endmodule

二者差值并非绝对的 500ms,问题出在计数变量的初始化上。
FPGA学习笔记(二):时序逻辑之计数器_第1张图片

时序逻辑的 test_bench 怎么写?

`timescale 1ns/1ns

module led_flush_tb();
    
    reg clk;
    reg reset_n;
    wire led;
    
    led_flash led_flash_example (
        .clk(clk),
        .reset_n(reset_n),
        .led(led)
    );

    initial clk = 1;
    always #10 clk = ~clk; // ÊŒÖÕ10ns·­×ªÒ»ŽÎ
    
    initial begin
        reset_n = 0;
        #201
        reset_n = 1;
        #2000000000;
        $stop;
    end

endmodule

AXU3EG LED 灯实验

LED 灯控制实验,每秒钟控制开发板上的 LED 灯翻转一次。

Zynq 相比较其它 ARM 平台,其可以使用 PL 端资源定制很多 ARM 端的外设。

LED 硬件介绍

开发板的 PL 端连接了一个红色的 LED 灯,完全由 PL 端控制。如果 PL_LED1 为高电平,三极管导通,灯会亮,否则熄灭。

FPGA学习笔记(二):时序逻辑之计数器_第2张图片
扩展板:确定 LED 和 PL 管脚的绑定关系。
FPGA学习笔记(二):时序逻辑之计数器_第3张图片

核心板:
FPGA学习笔记(二):时序逻辑之计数器_第4张图片

创建 Vivado 工程

在这里插入图片描述
FPGA学习笔记(二):时序逻辑之计数器_第5张图片
FPGA学习笔记(二):时序逻辑之计数器_第6张图片
输入工程名和工程存放目录,工程路径不能有中文空格。
FPGA学习笔记(二):时序逻辑之计数器_第7张图片
工程类型中选择 RTL Project。
FPGA学习笔记(二):时序逻辑之计数器_第8张图片
目标语言选择 Verilog,VHDL 也可以使用,支持多语言混合编程,并可以在这里创建文件。
FPGA学习笔记(二):时序逻辑之计数器_第9张图片
FPGA学习笔记(二):时序逻辑之计数器_第10张图片
FPGA学习笔记(二):时序逻辑之计数器_第11张图片
FPGA学习笔记(二):时序逻辑之计数器_第12张图片
选择器件。
FPGA学习笔记(二):时序逻辑之计数器_第13张图片
FPGA学习笔记(二):时序逻辑之计数器_第14张图片
点击 Finish 完成工程创建。
FPGA学习笔记(二):时序逻辑之计数器_第15张图片
在弹出的模块定义中可以指定端口,这里暂不指定。
FPGA学习笔记(二):时序逻辑之计数器_第16张图片
FPGA学习笔记(二):时序逻辑之计数器_第17张图片
双击 led2.v 文件编写,这里定义了一个 32 位寄存器 timer,用于循环计数 0~199999999(1秒钟),计数到 199999999 的时候,寄存器 timer 变为 0,并翻转四个 LED,原来 LED 是灭的话就会点亮,如果原来 LED 为亮的话,就会熄灭。由于输入时钟为 200MHz 的差分时钟,因此需要添加 IBUFDS 原语连接差分信号。

`timescale 1ns / 1ps 
module led(
//Differential system clock
    input sys_clk_p,
    input sys_clk_n,
    input rst_n,
(* MARK_DEBUG="true" *)    output reg  led
    );
(* MARK_DEBUG="true" *)reg[31:0] timer_cnt;
wire sys_clk ;

IBUFDS IBUFDS_inst (
      .O(sys_clk),   // 1-bit output: Buffer output
      .I(sys_clk_p),   // 1-bit input: Diff_p buffer input (connect directly to top-level port)
      .IB(sys_clk_n)  // 1-bit input: Diff_n buffer input (connect directly to top-level port)
   );

always@(posedge sys_clk)
begin
    if (!rst_n)
    begin
      led <= 1'b0 ;
      timer_cnt <= 32'd0 ;
    end
    else if(timer_cnt >= 32'd199_999_999)   //1 second counter, 200M-1=199999999
    begin
        led <= ~led;
        timer_cnt <= 32'd0;
    end
    else
    begin
        led <= led;
        timer_cnt <= timer_cnt + 32'd1;
    end
    
end
//Instantiate ila in source file
//ila ila_inst(
//  .clk(sys_clk),
//  .probe0(timer_cnt),
//  .probe1(led)
//  );


endmodule

添加管脚约束

Vivado 使用的约束文件格式为 xdc 文件。xdc 文件里主要是完成管脚的约束、时钟的约束、以及组的约束。这里我们需要对 led.v 程序中的输入输出端口分配到 FPGA 的真实管脚上。

FPGA学习笔记(二):时序逻辑之计数器_第18张图片

  • Open Elaborated Design:将RTL源代码翻译转换成对应的电路。
  • Run Synthesis:同样提供了显示详细电路的功能,相比较前者,更偏向于显示 Xilinx 中已封装好的库。

FPGA学习笔记(二):时序逻辑之计数器_第19张图片
FPGA学习笔记(二):时序逻辑之计数器_第20张图片
时钟

FPGA学习笔记(二):时序逻辑之计数器_第21张图片
核心板:
FPGA学习笔记(二):时序逻辑之计数器_第22张图片
核心板:
FPGA学习笔记(二):时序逻辑之计数器_第23张图片
扩展板:

FPGA学习笔记(二):时序逻辑之计数器_第24张图片
扩展板:

FPGA学习笔记(二):时序逻辑之计数器_第25张图片
核心板:

FPGA学习笔记(二):时序逻辑之计数器_第26张图片

在 I/O Ports 中可以看到管脚分配情况。
FPGA学习笔记(二):时序逻辑之计数器_第27张图片
将复位信号 rst_n 绑定到 PL 端的按键,给 LED 和时钟分配管脚、电平标准,完成后 Ctrl + S,弹出窗口,保存约束文件,文件类型默认为 XDC。

FPGA学习笔记(二):时序逻辑之计数器_第28张图片

打开生成的 led2.xdc 文件,最基本的 XDC 编写语法:

普通 IO 口只需要约束引脚号和电压,管脚约束:

set_property PACKAGE_PIN "引脚编号" [get_ports "端口名称"]

电平信号约束:

set_property IOSTANDARD "电平标准" [get_ports "端口名称"]

电平标准中 ”LVCMOSS33“ 后面的数字指 FPGA 的 BANK 电压,LED 所在 BANK 电压为 3.3 伏,Vivado 默认要求为所有 IO 分配正确的电平标准和管脚编号。

添加时序约束

先分析综合,然后点击 Constraints Wizard:

FPGA学习笔记(二):时序逻辑之计数器_第29张图片
FPGA学习笔记(二):时序逻辑之计数器_第30张图片
时序约束向导分析出设计中的时钟,这里把 sys_clk_p 频率设置为 200MHz,然后点击 Skip to Finish,结束时序约束向导。
FPGA学习笔记(二):时序逻辑之计数器_第31张图片
FPGA学习笔记(二):时序逻辑之计数器_第32张图片
这个时候 led.xdc 文件已经更新,点击 Reload 重新加载文件,并保存文件。
FPGA学习笔记(二):时序逻辑之计数器_第33张图片
FPGA学习笔记(二):时序逻辑之计数器_第34张图片

生成 BIT 文件

FPGA学习笔记(二):时序逻辑之计数器_第35张图片
查看目前状态:
FPGA学习笔记(二):时序逻辑之计数器_第36张图片

Vivado 仿真

利用 Vivado 自带的仿真工具输出波形验证流水灯程序设计结果:

  1. 设置 VIvado 的仿真配置:

FPGA学习笔记(二):时序逻辑之计数器_第37张图片
2. 在 Simulation Settings 窗口中进行如下配置,这里设置成 50ms,其它默认。
FPGA学习笔记(二):时序逻辑之计数器_第38张图片
3. 添加激励测试文件,点击 Project Manager 下的 Add Sources 图标:

FPGA学习笔记(二):时序逻辑之计数器_第39张图片
FPGA学习笔记(二):时序逻辑之计数器_第40张图片
FPGA学习笔记(二):时序逻辑之计数器_第41张图片
FPGA学习笔记(二):时序逻辑之计数器_第42张图片
不添加 IO 端口,

  1. 编辑内容,首先定义输入和输出信号,实例化 led_test 模块,让 led_test 程序作为本测试程序的一部分,再添加复位和时钟的激励。
`timescale 1ns / 1ps
//
// Module Name: vtf_led_test
//

module vtf_led_test;
// Inputs
reg sys_clk_p;
reg rst_n ;
wire sys_clk_n;
// Outputs
wire led;

// Instantiate the Unit Under Test (UUT)
led uut (
    .sys_clk_p(sys_clk_p),  
    .sys_clk_n(sys_clk_n),     
    .rst_n(rst_n),
    .led(led)
 );

initial 
begin
// Initialize Inputs
    sys_clk_p = 0;
    rst_n = 0;
// Wait for global reset to finish
	#1000;
    rst_n = 1; 
end
//Create clock
always #2.5 sys_clk_p = ~ sys_clk_p;  
assign  sys_clk_n = ~sys_clk_p ;
endmodule 
  1. 点击 Run Simulation ,选择 Run Behavioral Simulation,进行行为级仿真。

下载

连接 JTAG 线缆,调整到 JTAG 模式启动,开发板上电、

在 HARDWARE MANAGER 界面,点击 Auto Connect 自动连接设备。

选择 FPGA 芯片,右键选择 Program Device,点击 Program。

下载完成后,可以看到 PL LED 每秒钟变化一次。

只有 PL 工程不能直接烧写 Flash。

你可能感兴趣的:(Xilinx,FGPA,学习,fpga开发,UltraScale,Xilinx,Zynq)