硬件培训_实验1_嵌入式环境搭建

Design Name:嵌入式环境搭建

Project Name:实现二分频电路

Tool Version:ISE 14.3 + Win7 64位 + 12G内存

里面包含了一些平常用到的实例,然后自己加的备注

1 首先是设计文件和激励文件的撰写

1.1 首先是设计文件

module top(clk,rst,clk_div2)//这里定义了一个名为top的模块
    input clk,rst;//定义:clk、rst为输入
    output clk_div2;//定义:clk_div2为输出
    reg[15:0] count = 1'b0;//定义了一个大小为16位的计数器count
    assign clk_div2 = count[0];//分配count[0]给clk_div2f
    always @(posedge clk)//一旦clk信号的上升沿出现,则执行下面
        begin            //begin end 相当于花括号,把多条语句包含进来
            if(!rst)     //如果rst是0则执行"count <= 1'b0"
                count <=1'b0;
            else         //否则的话,执行"count <=count + 1'b1"
                count <=count + 1'b1;
        endendmodule
module top(clk59m,rst,txd,rxd,send_over,dout);


endmodule
1.1.1 关于assign

语法:assign <寄存器类型变量> = <赋值表达式>;

比如:assign clk_div2=count[0]表示把count[0]中的数赋值给clk_div2

1.1.2 关于always

always所包括的所有的行为语句共同构成了一个always语句块,这个语句块从仿真的0时刻开始执行其中的行为语句,当最后一条语句执行完毕之后,重新从第一条语句开始读取,像这样循环往复,直到整个仿真的结束。所以,always常常用于一组需要反复运行的活动,比如时间信号的发生,或者是每半个时钟周期时钟信号翻转一次这样的。

因此:

从c语言的角度看,always就像是for循环一样。


1.1.3 书上说的

always过程快是由always过程语句以及语句块组成的,语法格式如下

always @ <敏感信号表达式>
    语句块
其中语句块的格式为:
    <块定义语句1>
    时间控制1   行为语句1;
    ...
    时间控制n   行为语句n;
    <块定义语句2>

其中,@ <敏感信号表达式>可有可无,如果有敏感事件的话,就可以加上,表示这个always语句是由这个敏感事件所触发的。

<块定义语句1>和<块定义语句2>构成了一组块定义语句,它们可以是“begin-end”或者是“fork-join”

行为语句包括:

  1. 过程赋值语句
  2. 过程连续赋值语句
  3. if条件分支语句
  4. case条件分支语句
  5. 循环控制语句(forever、repeat、while、for循环控制语句)
  6. wait等待语句
  7. disable中断语句
  8. 事件触发语句
  9. 任务调用语句 下面对于上面这个程序进行大致说明

首先我们定义了3个参数,clk,rst,clk_div2,然后我们定义clk和rst为输入,clk_div2为输出,然后定义一个大小为16位的计数器,将这个计数器的最末位赋值给clk_div2,接着如果clk信号的上升沿出现了,就执行always中的语句,即如果rst为0的话,将0赋给count,如果rst为1的话,就让count+1,事实上,count的初始值为0,加了一次之后,变为1,再加一次之后变为10,此时因为clk_div2的值是count的第一位,所以此时clk_div2为0.

1.2 下面是第一个实例的激励文件

下面就是第一个实例的激励文件:

module top1;

    // Inputs
    reg clk;
    reg rst;

    // Outputs
    wire clk_div2;

    // Instantiate the Unit Under Test (UUT)
    top uut (
        .clk(clk), 
        .rst(rst), 
        .clk_div2(clk_div2)
    );

    initial 
    begin
        // Initialize Inputs
        clk = 0;
        rst = 0;

        // 从这里往下是自己写的

        #30 rst = 1;    //30个时间单位之后,rst为1
        forever         //然后一直保持
        #20 clk = ~clk; //20个单位之后clk翻转    
    end

    always #20 clk = ~clk;//这一句和前面的forever #20 clk=~clk;是实现的相同的功能endmodule

首先解释一下什么是激励文件

根据书上的定义:在完成工程的设计后,通常要对设计的正确性进行测试,这就需要对设计文件施加激励,通过检查其输出来验证功能的正确性。完成测试功能的模块称为激励文件

通常需要将激励文件与设计文件分开设计。激励文件一般称为测试台testbench

讲一下里面的一些关键词的用法

1.2.1 initial

initial介绍

initial里面的语句是顺序运行的

1.2.2 always与initial的不同点

always和initial的不同点在于,initial语句只执行一次,而always语句则是不断地重复执行,直到仿真过程结束。

1.2.3 forever

forever与always这两者的功能其实是差不多的,比如说用这两个关键词生成时钟

首先是forever

initial 
foreverbegin
    #0 clk <= 0;
    #5 clk <= 1;
    #5 clk <= 0;
end

然后是always

initialbegin
    clk = 0;
endalwaysbegin
    #5 clk=~clk;
end

说明: forever 意思为保持,它所保持的是它下面的那一条语句,而不是说上面那条语句完了,然后一直保持。但是他与always还是有区别的,forever循环语句常用于产生周期性的波形,用来作为仿真测试信号。它与always语句不同之处在于不能独立写在程序中,而必须写在initial块中。

1.2.4 testbench的基本结构
module test_bench;
    信号或变量定义说明;
    使用initial或always语句来产生激励波形;
    实例化设计模块;
    监控和比较输出响应;
endmodule

常用的激励信号通常会包括:时钟信号复位信号

1.2.5 普通时钟信号

普通时钟信号就是占空比为50%的时钟信号。

(1) 使用initial生成时钟信号
parameter period = 20;
reg clk;
initial         //产生时钟信号,并且每隔10个时间单位就翻转一次begin
    clk = 1'b0;
    forever
        #(period/2) clk=~clk;
end
(2) 使用always生成时钟信号
parameter period = 20;
reg clk;
initial clk=1'b0;
always #(peiod/2) clk=~clk;

一定要给时钟信号赋初值,因为信号的默认值为z

2 TOP文件和UCF文件的生成

按照培训大纲上所说:

连接FPGA 仿真器,打开ISE软件,进行连接测试,如果下载线正常识别FPGA 型号,表示硬件开发环境搭建成功。新建工程,然后选择FPGA型号、系列、编程语言、速度等选项,添加TOP文件和UCF文件,Verilog逻辑实现二分频电路,即CLK_OUT=CLK_IN/2,编译程序并生成BIT 文件,在线烧写BIT文件,使用示波 器测量时钟输出频率,并与晶振始终比对。

2.1 首先是TOP文件

TOP文件就是顶层文件,也就是之前的那个设计文件.v

2.2 然后是UCF文件

FPGA中的约束文件共有三种:

  • 用户设计文件(UCF文件)
  • 网表约束文件(NCF文件)
  • 物理约束文件(PCF文件)

这三者的关系为:用户在设计输入阶段编写UCF文件,然后UCF文件和设计文件综合后生成NCF文件,最后再经过实现后生成PCF文件。UCF是用户输入的,而NCF是由综合工具自动生成的,当两者发生冲突时,以UCF为准。

约束文件的建立有两种,一种是通过新建方式,一种是利用过程管理器完成。

UCF中描述引脚分配的语法是

verilog NET "端口名称" LOC = pin num;//pin num是引脚编号

2.2.1 通过新建方式

在sources窗口,单击鼠标右键,选择New Source,然后选择Implementation Constraints File,之后输入UCF的文件名,比如ceshi_ucf,然后点击next按钮、finish即可完成UCF文件的创建。

2.2.2 通过过程管理器

在Sources for窗口的下拉菜单选择 Synthesis/Implementation ,然后在Processes窗口展开User Constraints,双击下面的Create Timing Constraints,这样就可以打开Constraints Editor约束文件编辑器。打开之后,就可以直接输入引脚编号进行引脚分配了。

UCF其实就是将之前top文件中写的那些输入、输出端口与实际的PCB板中的FPGA引脚对应起来。比如这个二分频,UCF文件中一共需要写三个。输入、输出、重置。

下面是该UCF内的三行语句:

NET "clkout" LOC = AC6;// 将FPGA的AC6引脚分配给clkout,作为输出引脚NET "clk" LOC = C14;// C14是时钟:PCB上写着CLKINNET "rst" LOC = D2;// 这是复位按钮

写UCF文件的思想就是,首先找到FPGA中的时钟,本次用的时钟是59MHz,找到时钟对应的引脚之后,将它与我之前写的那个TOP文件中的clk(时钟输入)对应起来,时钟的输入解决之后,再解决输出问题,这里我随便选了一个引脚AC6(也就是PCB图左下角的那一排口)作为输出引脚,然后与TOP文件中的clkout对应起来,这样如果二分频实现了之后,就可以将分完的频(59除以2)通过clkout引脚显示出来,那么怎么显示呢,由于选择了AC6引脚作为输出,将探针一端接入示波器,另一端放到AC6的位置,这样就会发现分完的频率通过AC6在示波器上显示了出来。

2.3 BIT文件生成

在语法检查没有错误之后,双击Processes窗口下的:Generate Programming File选项,就会在项目的目录下面生成.bit文件。

生成完.bit文件之后,就可以按照培训大纲中所说的,在线烧写BIT文件,然后可以通过示波器测量时钟的输出频率了。

2.4 如何烧写

从开始菜单找到iMPACT,单击打开,出现下图:

点击OK,进入下一步:

添加Bit 文件,右键单击xc4vsx55,选中Program 即可完成烧写。

至此,第一个实验结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值