实验(二)基于BASYS3平台的FPGA流水灯实验

枯藤老树昏鸦,小桥流水人家。                                   — — — —《天净沙.秋思》马致远

文章目录  

  • 前言
  • 一、实验内容
  • 二、实验平台
  • 设计思路与方案
  • 四、RTL代码设计
  • 五、仿真测试程序设计
  • 六、电路与仿真结果
  • 七、管脚规划
  • 八、板子上电演示
  • 总结


前言

大四毕业后白嫖了电子创新实验室的一块FPGA,这块板子适合做数电实验,为了物尽其用,趁这个暑假搭配特权同学做的《深入浅出玩转FPGA》视频学习入门一下,用它整点活。

一、实验内容

让板载的8颗LED灯每隔1秒依次点亮,全亮后又每隔1秒依次熄灭,循环。

二、实验平台

RTL代码编写平台:Vivado 2019.1

FPGA开发板:Xilinx  BASYS3

芯片型号:Artix家族  xc7a35tcpg236-1

三、设计思路与方案

1.总体构想

如下图所示,我的构想由计时模块和类38线译码器模块组合而成,时钟和复位信号输入,8颗LED灯作为输出,计时模块处理LED灯亮灭的时序逻辑,产生1Hz方波进行计数,由于计数值为0~7共8位,所以联想到38译码器,这样可以通过3位二进制数作为地址输出给后级模块去控制8颗LED灯(模拟成8位二进制数),LED状态的刷新受到计时模块时钟的控制。

2.计时模块设计

查看BASYS3开发板的原理图可知,系统时钟由DSC1033CC1-100.0000T晶振产生,为100Mhz,如下图所示。

为了达到“每隔1秒亮一次”,需要利用系统时钟产生1Hz 的方波(周期为1s),通过对系统时钟上升沿的计数可以实现,由于(100MHz/100 000 000=1Hz),所以当从0计到99 999 999时就得到1Hz的频率,并且在一周期内对半周期前后的电平翻转就可以得到1Hz、占空比50%的延时时钟。

在产生了延时时钟后,需要再对这个时钟的下降沿进行计数,如下图所示,从0计数到7,每一个计数值对应了一个3位的地址,依次对应着8颗LED灯的一种亮灭状态;计数过了7后清零,并且翻转片选信号,片选信号为0时运行的是“8颗LED灯每隔1秒依次点亮”的过程,为1时运行的是“每隔1秒依次熄灭”的过程。

3.类3-8译码器的设计

模块的真值表如下图所示,地址和片选共同作用使8位LED值输出对应的电平信号,高电平点亮LED,低电平熄灭LED。

 

四、RTL代码设计

1.计时模块leds程序

module leds(
 input clk,                               //100Mhz系统时钟
 input rst,                               //复位信号,高电平有效
 output reg [2:0] ctrl_data,              //控制数据,输出到后级译码器中
 output  led_clk,                         //1Hz时钟
 output  led_cs                           //片选信号,输出到后级译码器用于选择状态
    );
 reg[27:0] cnt;                           //计数值,用于产生1Hz信号
 parameter cnt_max = 28'd99_999_999;     //计数最大值
 parameter cnt_half = 28'd49_999_999;    //计数中值
 reg led_clk_r;                          //1Hz方波时钟
 reg led_cs_r;                           //片选信号
 
 /****产生1Hz的方波****/
always @ (posedge clk or posedge rst)
 begin
    if(rst) cnt <= 28'd0;
    else if(cnt < cnt_max) cnt <= cnt+1'b1;
    else cnt <= 28'd0;
 end
 
always @ (posedge clk or posedge rst)
begin
    if(rst) led_clk_r <= 1'b0;
    else if(cnt < cnt_half) led_clk_r <= 1'b0;
    else led_clk_r <= 1'b1;
end

assign led_clk = led_clk_r;

/****在1Hz方波时钟信号下计数****/
always @ (negedge led_clk or posedge rst)
begin
    if(rst) 
    begin
        ctrl_data <= 3'd0;
        led_cs_r <= 1'b0;
    end
    else if(ctrl_data < 3'd7) ctrl_data <= ctrl_data+1'b1;
    else 
     begin 
        ctrl_data <= 3'd0;
        led_cs_r <= ~led_cs_r;
     end
end

assign led_cs = led_cs_r;

endmodule

2.译码模块code程序

module code(
    input clk,                      //100Mhz系统时钟
    input rst,                      //复位信号,高电平有效
    output reg [7:0] leds_out       //输出8个LED信号
    );
    
    wire [2:0] ctrl;                //前级输入的控制地址
    wire cs;                        //前级输入的片选信号

/****leds模块例化语句****/
    leds myleds(
        .clk(clk),
        .rst(rst),
        .ctrl_data(ctrl),
        .led_cs(cs)
    );
    
/****类3-8线译码器的设计****/
    always @ (ctrl or cs or rst)
     begin
     if(rst)  leds_out = 8'b0000_0000;
     else
      begin
        if(!cs)
        begin
             case(ctrl)
            3'b000: leds_out = 8'b0000_0001;
            3'b001: leds_out = 8'b0000_0011;
            3'b010: leds_out = 8'b0000_0111;
            3'b011: leds_out = 8'b0000_1111;
            3'b100: leds_out = 8'b0001_1111;
            3'b101: leds_out = 8'b0011_1111;
            3'b110: leds_out = 8'b0111_1111;
            3'b111: leds_out = 8'b1111_1111;
            endcase
        end
        else
        begin
            case(ctrl)
            3'b000: leds_out = 8'b1111_1110;
            3'b001: leds_out = 8'b1111_1100;
            3'b010: leds_out = 8'b1111_1000;
            3'b011: leds_out = 8'b1111_0000;
            3'b100: leds_out = 8'b1110_0000;
            3'b101: leds_out = 8'b1100_0000;
            3'b110: leds_out = 8'b1000_0000;
            3'b111: leds_out = 8'b0000_0000;
            endcase
        end
      end
        
     end
    
endmodule

五、仿真测试程序设计

注意,板子上的按钮为摁下接到高电平,松开接到低电平,原理图如下所示,这里我们用到的是5个中的1个,在后续小节会讲到如何分配管脚,所以在设计仿真测试程序时要让rst信号由低电平跳上高电平然后过一点点时间再拉低。

 1.leds计时模块仿真测试程序

module leds_sim;
 reg clk;
 reg rst;
 wire [2:0] ctrl_data;
 wire led_clk;
 wire led_cs;
 
 leds text_leds(
    .clk(clk),
    .rst(rst),
    .ctrl_data(ctrl_data),
    .led_clk(led_clk),
    .led_cs(led_cs)
 );
 
 initial begin
    clk = 0;
    rst = 0;
    #1000 rst = 1;
    #1000 rst = 0;
  end
  
  always #5 clk = ~clk;  //输出100Mhz方波信号,每隔5ns翻转一次电平
 
endmodule

2.计时&译码仿真测试程序

module cod_sim;
    reg clk;
    reg rst;
    wire [7:0] leds_out;
    
    code text_code(
        .clk(clk),
        .rst(rst),
        .leds_out(leds_out)
    );
    
 initial begin
    clk = 0;
    rst = 0;
    #1000 rst = 1;
    #1000 rst = 0;
  end
  
  always #5 clk = ~clk;
endmodule

六、电路与仿真结果

下图为leds计时模块的行为仿真结果。

下图为leds&code总模块的仿真结果。

下图为综合后总模块的RTL原理图。

 

七、管脚规划

由下图所示,100Mhz系统时钟输入到了W5引脚中,所以我们给clk引脚配置为W5。

 

rst复位引脚我们配置为T17,原理图如下图所示。

 8颗LED灯管脚号如下图所示,从右往左位数依次升高。

 总的管脚配置文件如下所示。

set_property PACKAGE_PIN T17 [get_ports rst]
set_property PACKAGE_PIN U16 [get_ports {leds_out[0]}]
set_property PACKAGE_PIN E19 [get_ports {leds_out[1]}]
set_property PACKAGE_PIN U19 [get_ports {leds_out[2]}]
set_property PACKAGE_PIN V19 [get_ports {leds_out[3]}]
set_property PACKAGE_PIN W18 [get_ports {leds_out[4]}]
set_property PACKAGE_PIN U15 [get_ports {leds_out[5]}]
set_property PACKAGE_PIN U14 [get_ports {leds_out[6]}]
set_property PACKAGE_PIN V14 [get_ports {leds_out[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports rst]

set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]

八、板子上电演示

仿真、综合、布局布线、分配管脚后,可以生成bit文件,通过USB线给开发板上电,vivado连上器件xc7a35tcpg236-1后将bit文件烧录至开发板。

实验运行视频如下所示。

QQ视频20230709170724

总结

 

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值