14 0

10.FPGA入门程序(新手入门) [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-7-29
最后登录
2018-7-29

楼主
喜欢你的双眼 发表于 2025-12-4 07:03:48 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

一、编码设计

FPGA或数字电路的顶层模块设计主要涵盖两大功能模块:

  • LED灯控制:通过实例化4个独立的子模块,分别实现对4个LED灯亮灭模式的精准控制;
  • 3-8译码器实例化:硬件接口已预留(当前未启用)。

1. 模块参数定义

采用参数化设计方法,定义了一个名为CLK_DIV的常量(其值为99999999),用于向子模块传递“分频系数”。由于系统时钟频率较高(例如50MHz),直接驱动LED会导致闪烁过快,人眼无法识别,因此需通过分频降低输出频率以实现可见效果。

说明:参数类似于“全局配置项”,在实例化子模块时可灵活调整。例如,在仿真阶段可将其设为较小数值以加快验证速度。

module top#
(
    parameter RATE = 32'd99_999_999  //分频时钟计数参数
)
parameter
RATE

2. 端口定义

模块包含以下端口信号:

  • 输入信号:clk(时钟)、rst_n(复位,低电平有效);
  • 输出信号:led(控制LED状态);
  • led为4位总线结构,每位对应一个独立的LED灯(其中led[0]连接第一个LED,依次类推)。
(
    input          I_sysclk,      // 系统时钟(比如50MHz)
    input          I_rstn,        // 全局复位(低电平有效)
    output [3:0]   O_led          // 4个LED输出
);
input
output
O_led[3:0]
O_led[0]

3. LED控制部分(核心逻辑)

通过实例化四个相同的led_ctrl子模块来分别驱动四个LED灯。每个子模块接收不同的参数配置,从而实现多样化的显示效果(如快闪、慢闪、呼吸灯等)。

实例化语法如下所示:

子模块名 #(参数传递) 实例名 (端口连接)

其中,modedir是子模块的关键控制信号:

  • mode决定LED的工作模式(如闪烁或常亮);
  • dir设定亮灭变化的方向。

初学者理解提示:每一个led_ctrl相当于一个独立的“LED控制器”,顶层模块为其提供时钟与复位信号,并通过设置不同的参数(如分频系数)使其表现出差异化行为。

run_led
run_led
O_led[0]~O_led[3]
run_led #(.RATE(RATE)) led0 (
    .I_sysclk(I_sysclk),
    .I_rstn(I_rstn),
    .mode(1'b0),       //模式选择0
    .switch(1'b0),     //开关选择0
    .led_out(O_led[0])
);

run_led #(.RATE(RATE)) led1 (
    ...
    .mode(1'b0),
    .switch(1'b1),     //开关选择1
    .led_out(O_led[1])
);

run_led #(.RATE(RATE)) led2 (
    ...
    .mode(1'b1),       //模式选择1
    .switch(1'b0),
    .led_out(O_led[2])
);

run_led #(.RATE(RATE)) led3 (
    ...
    .mode(1'b1),
    .switch(1'b1),
    .led_out(O_led[3])
);
mode
switch
mode/switch

4. 3-8译码器部分(预留扩展功能)

该部分声明了寄存器类型变量decode_in和线网类型信号decode_out,完成了3-8译码器的基本连接结构。

功能说明:该译码器接收3位二进制输入(如3'b001),输出对应的8位独热码(例如仅decode_out[1]为高,其余为低)。

目前该模块并未实际使用——因为输入信号decode_in未被赋值(默认保持为0),故整个译码器处于闲置状态。此设计属于前瞻性布局,便于后续功能拓展(例如利用LED状态动态控制译码器输入)。

// 定义译码器的输入输出寄存器/线网
reg TOP_A0;
reg TOP_A1;
reg TOP_A2;

wire TOP_Y0;
wire TOP_Y1;
...
wire TOP_Y7;

// 例化3-8译码器
decoder_3_8 decoder(
    .A0(TOP_A0),
    .A1(TOP_A1),
    .A2(TOP_A2),
    .Y0(TOP_Y0),
    ...
    .Y7(TOP_Y7)
);
reg
wire
A2A1A0
000
Y0=1
TOP_A0~TOP_A2

设计思路总结

  • 模块化拆分:将LED控制与译码器功能分离为独立子模块,顶层仅负责互联,体现数字电路“分层设计”理念——先构建整体架构,再填充具体逻辑;
  • 参数化复用:借助parameter CLK_DIV = 99999999机制,使子模块具备可配置性,既满足实际硬件运行需求(大分频比),又支持仿真调试(小分频比);
  • 功能预留设计:虽已例化3-8译码器但暂不激活,为未来功能升级预留硬件通路(如扩展更多LED或外设控制)。

源代码:

// 顶层模块
//module top
//(
//    input          I_sysclk,      // 系统时钟信号
//    input          I_rstn,        // 全局复位
//    output [3:0]   O_led                                           //LED灯输出
//);


module top#
(
    parameter RATE = 32'd99_999_999                      //分频时钟计数,初始时钟过快,人眼观察会导致LED常亮
)
(
    input          I_sysclk,      // 系统时钟信号
    input          I_rstn,        // 全局复位
    output [3:0]   O_led                                           //LED灯输出
);

//1.控制led灯
/////////////////////////////////////LED控制部分begin/////////////////////////////////////////////////////////////
run_led #
(
.RATE(RATE)       //设置一个较小的时钟计数参数,可以大大缩小我们仿真需要的时间
)
led0 (
    .I_sysclk(I_sysclk),
    .I_rstn(I_rstn),
    .mode(1'b0),
    .switch(1'b0),
    .led_out(O_led[0])
);

run_led #(
.RATE(RATE)       //设置一个较小的时钟计数参数,可以大大缩小我们仿真需要的时间
) 
led1 (
    .I_sysclk(I_sysclk),
    .I_rstn(I_rstn),
    .mode(1'b0),
    .switch(1'b1),
    .led_out(O_led[1])
);


run_led #(
.RATE(RATE)       //设置一个较小的时钟计数参数,可以大大缩小我们仿真需要的时间
) 
led2 (
    .I_sysclk(I_sysclk),
    .I_rstn(I_rstn),
    .mode(1'b1),
    .switch(1'b0),
    .led_out(O_led[2])
);


run_led #(
.RATE(RATE)       //设置一个较小的时钟计数参数,可以大大缩小我们仿真需要的时间
)  
led3(
    .I_sysclk(I_sysclk),
    .I_rstn(I_rstn),
    .mode(1'b1),
    .switch(1'b1),
    .led_out(O_led[3])
);

/////////////////////////////////////LED控制部分end/////////////////////////////////////////////////////////////

//2.38译码器组合逻辑电路
//
reg TOP_A0;
reg TOP_A1;
reg TOP_A2;

wire TOP_Y0;
wire TOP_Y1;
wire TOP_Y2;
wire TOP_Y3;
wire TOP_Y4;
wire TOP_Y5;
wire TOP_Y6;
wire TOP_Y7;

decoder_3_8 decoder(
    .A0(TOP_A0),
    .A1(TOP_A1),
    .A2(TOP_A2),
    .Y0(TOP_Y0),
    .Y1(TOP_Y1),
    .Y2(TOP_Y2),
    .Y3(TOP_Y3),
    .Y4(TOP_Y4),
    .Y5(TOP_Y5),
    .Y6(TOP_Y6),
    .Y7(TOP_Y7)
    );



endmodule

二、程序框架分析

分析FPGA程序不应沿用传统软件编程的思维模式,而应基于电路原理图的分析方式,重点关注信号的连接关系与传输路径。也就是说,FPGA代码的解读方式应当等同于阅读电路图。

分析要点如下:

  • 输入信号包括复位信号和外部晶振提供的时钟信号(频率为100MHz);
  • 内部集成了4个独立的LED控制电路,各自驱动一个LED灯;
  • 3-8译码器电路未与其他模块建立连接,因此当前无实际作用。

三、仿真结果

仿真波形显示结果符合预期设计目标。

四、总结

通过本次实践,成功完成了首个FPGA程序的编写与板级验证,深入剖析了程序的整体架构,同时熟悉了基本开发流程。尽管示例较为基础,尚未编写Testbench进行RTL级仿真,也未涉及XDC等硬件约束文件的创建——这些环节在完整的FPGA工程中至关重要。

完成第一个项目意味着正式迈入FPGA领域的大门,同时也掌握了开发工具的基本操作流程。若能持续采用此类实践方法积累经验,长期坚持,必将逐步掌握FPGA核心技术。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:FPGA 新手入门 Parameter paramete switch

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-9 06:15