常用NIOS Ⅱ组件概括
目录
1.定时器Timer
Interval timer核的基础特性:
1.Niosll 处理器的Avalon-MM主设备可以通过写控制寄存器 (control register) 来完成:(1)启动和停止定时器;(2)使能/禁止IRQ;(3)明确累减计数一次或重复性累减计数
2.处理器通过读状态寄存器 (status register) ,能够得知定时器所处的状态
3.处理器可以通过给周期寄存器 (period registers) 写数值来指定定时器的周期
4.内部计数器累减到 0,然后会从周期寄存器 (period registers) 获取数值,继续累减计数
5.处理器可以通过一些操作来获取当前计数器 (counter) 的值:先给其中一个捕获寄存器 (snap registers)写数据,然后读捕获寄存器 (snap registers) 来获得完整的值。
6.当计数器计数到 0 的时候,可能会触发:(1)如果IRQ被使能,此时会触发 IRQ;(2)可选的一个时钟周期的脉冲输出;(3)可选的看门狗输出,复位系统
在IP Catalog中搜索Timer添加Interval Timer Intel FPGA IP组件
1.1 预定义硬件配置
Library中提供了预定义的硬件配置:
Simple periodic interrupt (简单周期中断)一一用于只需要周期性地触发 RQ 的系统,固定周期,定时器无法被停止,但IRQ可以被禁止。
Full-featured (全功能) 一一用于要求定时器能被处理器启动或停止,但能禁止IRQ的嵌入式处理器系统
Watchdog(看门狗)一一用于需要“看门狗”定时器去复位停止响应的系统
1.2 超时周期Timeout poriod
超时周期(Timeout Period) 是定时器频率 (Timer Frequency)的整数倍。定时器频率固定为系统时钟的频率。定时器频率设置的单位可以是μs、ms、seconds或者clocks (系统时钟周期个数)
Period定时器周期,没有选中 Fixed period 选项的话,可以在软件中修改。若软件中没有修改操作,period 中的值就会作为超时周期 (Timeout Period)
Units: 周期的单位,可以是μs、ms、seconds、clocks。
1.3 计数器大小Timer counter Size
Counter Size设置决定了定时器的位宽,可以设置成32位或 64 位。
32位的定时器拥有2个16位的period registers (周期寄存器)
64位的定时器拥有4个16位的period registers (周期寄存器)
1.4 寄存器Registers
No Start/Stop controlbits:没有选中该选项时,主设备可以通过写control寄存器中的START和 STOP位来启动或者停止定时器。当选中该选项后,定时器会一直运行。当硬件中使能了“watchdog功能后,无论No Start/Stop control bits选项如何,control寄存器中 START 位有效。
Fixed period:选中该选项后,就无法在软件中更改定时器周期,且定时器周期为Timeout Period处设置的结果;若没有选中该选项,可以通过在软件中给 period registers 赋值来更改定时器周期(timeout Period )
Readable snapshot: 选中该选项后,主设备可以读取当前的计数值。没有选中该选项时,硬件中将不会存在 snap 寄存器,且读 snap 寄存器会返回未定义的值。在这种配置下,计数器 (counter)的状态只能通过status寄存器或IRQ信号之类的来观测
2.串口UART
在IP Catalog中搜索uart添加UART(RS-232 Serial Port) Intel FPGA IP组件
2.1 UART寄存器
UART IP核寄存器信息如下:
注:标号意义如下:
(1) 这些位可能不存在,取决于数据位宽的硬件选项。如果它们不存在,读出的值为0。且如果对它们进行写操作,则没有意义。
(2) 给status (状态) 寄存器写0将清零 dcts,e,toe,roe,brk,fe,and pe等位。
(3) 这些寄存器可能不存在,取决于硬件配置选项。如果寄存器不存在,对它进行读操作会返回未定义的值,且进行写操作则无意义。
2.1.1 rxdata寄存器
rxdata寄存器用于存储RXD输入引脚接收的数据。当一个新的数据被RXD输入引脚完全接收后,会被传输并存储到rxdata寄存器,此时status寄存器(状态寄存器)的rrdy位会被置 1。当rxdata 寄存器中的值被读了之后,status寄存器中的rrdy位会被清零。当rrdy位为1时,又有一个新的字符传输给rxdata寄存器,则会产生溢出错误,状态寄存器的ROE位被置1。不管前一个字符是否被读出,新接收到的字符总是会被自动保存到rxdata寄存器。另外,对rxdata寄存器进行写操作无意义。
2.1.2 txdata寄存器
Avalon主控制器把要发送的字符写入到txdata寄存器中。当一个字符写入txdata寄存时,状态寄存器(status寄存器)的TRDY位会被置0;当字符从txdata寄存器传输到发送移位寄存器时,状态寄存器(status寄存器)的TRDY位被置为1。当TRDY位为0时,将字符写入txdata寄存器的结果是未定义的。读 txdata返回未定义的值。
2.1.3 status寄存器
状态寄存器 (status寄存器)由可以反应UARTIP核状态的独立位组成,任何时候都可以读取状态寄存器,且读操作不会改变寄存器任何位的值。给状态寄存器写0 ,会清零DCTS、E、TOE、ROE、BRK、FE和 PE位。
位 | 名称 | 操作 | 描述 |
0 | PE | 读/清除 | Parity Error。当读取的校验位不正确时会发生校验错误且PE位置1。PE 位为1时,需要通过写status寄存器将其清零。当PE位置时,读取rxdata寄存器会产生未定义值。如果没有选中Parity硬件选项,UARTIP核则没有奇偶校验,并且读PE位总是0。 |
1 | FE | 读/清除 | Framing Error。当接收器没能检测到正确的停止位时,会产生帧错误。当核接收到错误的停止位时,FE位置1。FE 位置1后,直到给status寄存器写数据才会将其清零。当FE位置1时,读rxdata寄存器会返回未定义的值。 |
2 | BRK | 读/清除 | Break Detect。当RXD引脚连续保持低电平 (逻辑 0)的时间大于一个完整字符的时间(数据位,加上起始、停止和校验位) 时,接收逻辑才会检测到间断。当检测到间断时,BRK位置 1。BRK位为1时,需要通过写status寄存器才能将其清零。 |
3 | ROE | 读/清除 | Receive Overrun Error。在读取前一个字符前 (即RRDY位为1时),将一个新的字符传输给rxdata寄存器,会产生接收溢出错误。此时,ROE位置 1,且接收数据寄存器内前一个接收字符被新的接收字符改写。BRK位为1时,需要通过写状态寄存器将其清零。 |
4 | TOE | 读/清除 | Transmit Overrun Error。在前一个字符传输到移位寄存器前,将新字符写入txdata寄存器 (TRDY位为0 时),会产生溢出错误。此时TOE位置1。TOE位置1后,直到给 status寄存器写1才会将其清零。 |
5 | TMT | 读 | Transmit Empty。TMT位提示发送移位寄存器的当前状态。当移位寄存器正将字符从 TXD引脚输出时,TMT位设为 0。当移位寄存器处于空闲时(没有要输出的字符),TMT位为1。Avalon-MM主控制器可以通过检查TMT位来确定发送是否完成。 |
6 | TRDY | 读 | Transmit Ready。TRDY位提示txdata寄存器的当前状态。当txdata寄存器为空时,可以接收新字符且TRDY位为 1。当txdata寄存器为满状态时,TRDY位为 0。Avalon-MM主控制器必须等待TRDY位变为1后,才能新数据写入txdata寄存器中。 |
7 | RRDY | 读 | Receive Character Ready。RRDY位提示rxdata寄存器的当前状态。当rxdata寄存器为空时,RRDY为0,且还不是读取rxdata寄存器的时刻。当新接收的值传输到rxdata 寄存器时,RRDY位置 1。读rxdata寄存器会将RRDY位置零。Avalon-MM主控制器必须等待RRDY位变为1后,才能读取rxdata寄存器。 |
8 | E | 读/清除 | Exception。E位指示发生了错误。E位是TOE、ROE、BRK、FE 和 PE位的逻辑或结果。E位和control寄存器相应的中断使能位 (IE) 给使能/禁止所有错误IRQ提供了便利方法。对status寄存器进行写操作时,E位会置0。 |
10 | DCTS | 读/清除 | Change in Clear to Send (CTS) signal。只要在CTSN输入端口上检测到逻辑电平跳变时(采样与Avalon时钟同步),DCTS位置 1。该位通过CTS N上的上升沿和下降沿跳变设置。DCTS位置1后,直到给status寄存器写入数据将其清零,它的值才会发生变化。 |
11 | CTS | 读 | Clear to Send (CTS) signal。CTS位反映CTSN输入的瞬时状态(采样与Avalon时钟同步)。CTSN输入对发送或接收逻辑没有影响。CTSN输入仅会影响CTS和DCTS位状态,且当control寄存器的idcts位使能时,有可能产生中断。 |
12 | EOP | 读 | End ofPacket。下面任一事件发生时,EOP位置1:向txdata数据寄存器写入EOP字符;从rxdata数据寄存器读取 EOP 字符EOP 字符由endopacket寄存器的内容确定。EOP位保持为1直到给status寄存器写入数据将其清零为止。如果没有选中Include End ofPacket Register硬件选项,读EOP位总是为0。 |
2.1.4 control寄存器
每一个控制寄存器中与状态寄存器对应的位,都可以使能一个 IRQ。当控制寄存器中与状态寄存器对应的位的值都为1时,就会触发一个 IRO。
位 | 名称 | 操作 | 描述 |
0 | IPE | 读写 | 奇偶校验错误中断使能 |
1 | IFE | 读写 | 帧错误中断使能 |
2 | IBRK | 读写 | 间断检测中断使能 |
3 | IROE | 读写 | 接收溢出错误中断使能 |
4 | ITOE | 读写 | 发送溢出错误中断使能 |
5 | ITMT | 读写 | 发送移位寄存器空中断使能 |
6 | ITRDY | 读写 | 发送准备好中断使能 |
7 | IRRDY | 读写 | 接收准备好中断使能 |
8 | IE | 读写 | 错误中断使能 |
9 | TRBK | 读写 | 发送间断。TRBK位允许Avalon-MM主控制器通过TXD输出发送间断字符。当TRBK位设为1时,TXD信号强制设为 0。TRBK位会干扰任何进行中的发送Avalon主控制器必须在适当的间断周期后将TRBK位设回0。 |
10 | IDCTS | 读写 | CTS 信号改变中断使能 |
11 | RTS | 读写 | 请求发送(RTS)信号。RTS位直接连接到RTS_N输出。Avalon-MM主控制器可在任何时候写RTS位。RTS位的值只能影响RTS_N输出;它对发送器或接收器逻辑没有影响。由于 RTS_N输出为负逻辑。当RTS位为1时,RTS_N输出逻辑低电平0。 |
12 | IEOP | 读写 | 结束符中断使能 |
2.1.5 divisor寄存器
divisor寄存器是可选的,其中的值用来产生波特率时钟。当不存在divisor寄存器时对其进行写操作没有作用,读它返回一个未定义的值。
2.2 基础设置Basic settings
2.2.1 奇偶校验Parity
Partity有None (无)、Even (偶)、Odd (奇) 三个选项
用来确定UART是否发送有奇偶校验的字符,以及它是否期望接收到的有奇偶校验的字符。
2.2.2 数据为Data bits
Data bits有7、8、9三个可设置选项,这个设置决定了txdata、rxdata、endofpacket三个寄存器的位宽。
2.2.3 停止位Stop bits
Stop bits有 1、2两个选项,决定了IP 核在传输每一个字符时,是有一个还是两个停止位。
UART IP 核总是在接收到第一个停止位的时候,就停止接收操作,忽略掉附带的停止位,无论什么设置。
2.2.4 其他
Synchronizer Stages与寄存器的长度以及亚稳态事件相关,一般使用默认设置。
Include CTSRTS选择是否使用串口的“流控”功能,一般很少使用
Include end-of-packet选择是否设置数据流的结束标志 (end-of-packet),一般很少使用
2.3 波特率设置Baud rate
UART 内核可实现RS-232标准中的任意波特率。
波特率可配置为:
固定的波特率一一波特率在系统生成时被确定,且不能通过 Avalon 从控制器端口改变它的值。
可变的波特率一一基于divisor寄存器中存储的时钟分频值,波特率是可变的。主控制器通过向divisor寄存器中写入新值来改变波特率。
波特率的计算依赖于 Avalon-MM 接口提供的时钟频率。在硬件改变系统时钟频率,却没有重新生成UART IP 核会导致错误的信号。
Baud Rate设置决定了复位后的波特率。Baud Rate选项提供了标准的预设值。也允许用户输入任何非标准波特率。为了实现所需要的波特率,通常根据波特率计算时钟分频系数。
波特率与分频系数的关系如下.
除数=int ( (时钟频率) / (波特) + 0.5 )
波特率=(时钟频率) / (divisor+1)
当选择Fixed baud rate时,UART 硬件中不再包括divisor寄存器。UART硬件使用固定的波特率分频系数,且在系统生成后无法改变。
当不选择Fixed baud rate时,硬件中会在地址偏移值4生成一个 16 位的divisor寄存器。divisor寄存器是可写的,可以通过向分频寄存器写入新值来改变波特率。
3.SDRAM
在IP Catalog中搜索sdram添加SDRAM Controller Intel FPGA IP组件
SDRAM 控制器 IP核产生于 FPGA 内部,它带有接口引脚、控制逻辑、以及Avalon从机接口。
接口引脚用来连接外部 SDRAM 芯片管脚,这些接口引脚通过Altera FPGA上的I/0 引脚连接到 SDRAM芯片管脚上。
控制逻辑用来实现SDRAM操作,比如SDRAM 初始化,自刷新,突发读写等,这些全都是控制逻辑来完成的,当生成 SDRAM 控制器 IP 核之后,控制逻辑会自动生成。
Avalon从机接口用来连接CPU,Avalon从机接口是SDRAM控制器IP核中仅为用户可见的部分。从控制器端口提供一个线性存储器空间。Avalon接口作为存储器接口操作,SDRAM芯片必须和Avalon接口一样以相同的时钟来驱动,片内锁相环(PLL)就是用来调整 SDRAM 控制器与SDRAM 芯片之间的时钟相位差。
在较低的时钟频率下,可能不需要 PLL。在较高的时钟频率下,当信号在引脚上有效时,需要 PLL 来调整SDRAM时钟相位。PLI并没有包括在 SDRAM 控制器内。如果需要PLL,设计者必须在生成Qsys系统模块以外手动添加 PLL。
Presets列表提供几个预定义的SDRAM配置。如果实际使用的SDRAM芯片型号与列表中的一致,可直接选用而不用设置其他选项。选择不同的预配置,SDRAM IP核将自动改变Memory Profile和 Timing 选项卡上的值来匹配指定的配置。如果实际使用的 SDRAM 芯片与列表中的不相同,则可以根据 SDRAM芯片数据手册的参数来设置 Memory Profile 和 Timing标签上的值。
3.1 Memory Profile
数据宽度Data Width,有8、16、32、64四个可选项(SDRAM数据总线宽度),确定dq(数据)总线和dqm总线的宽度。
体系结构Architecture:
片选chip select,有1、2、4、8四个可选项(SDRAM 芯片的数目),通过使用多个片选信号,SDRAM控制器可组合多个SDRAM芯片为一个存储器子系统。
Banks,有2、4两个可选项(Bank 的数量),该值确定连接到SDRAM的 ba (Bank 地址) 总线宽度。
地址宽度Address Width:
行row,有11、12、13、14四个可选项,行地址线的宽度,该值确定addr总线的宽度
列column,≥8且小于行值,列地址线的宽度
Generic Memory model,当打开选项时,Qsys创建SDRAM芯片的功能仿真模型,仅用于仿真。
上述参数值可参照使用的 SDRAM 手册来设置,设置完毕后会显示SDRAM预期的内存容量。
3.2 Timing
设置 SDRAM 芯片的时序规范
4. 自定义IP核
首先要使用硬件描述语言描述硬件逻辑,一个典型的IP核的硬件逻辑一般由三个功能模块组成:
接口文件:作为顶层文件,定义总线接口信号;
寄存器文件:完成该IP核与外部信号进行通信,有了寄存器文件,用户就可以通过Avalon接口采用基地址+地址偏移量的方式来访问组件内部各寄存器;
硬件逻辑文件:实现IP核的硬件功能。
4.1自定义IP核实现动态数码管显示
4.1.1 创建工程及功能文件
创建Quartus工程,创建三个功能文件
顶层文件segled_controller.v
module segled_controller(
input clk, // 时钟信号
input rst_n, // 复位信号
//Avalon-MM 接口
input [ 1:0] avs_address, // Avalon 地址总线
input avs_write, // Avalon 写请求
input [31:0] avs_writedata, // Avalon 写数据
//数码管接口
output [ 5:0] sel, // 数码管位选
output [ 7:0] seg_led // 数码管段选
);
//wire define
wire [19:0] data; // 6 个数码管要显示的数值
wire [ 5:0] point; // 小数点显示的位置,从高(左)到低(右),高电平有效
wire sign; // 显示符号位(高电平显示负号)
wire en; // 数码管使能信号
//*****************************************************
//** main code
//*****************************************************
//数码管寄存器文件
segled_register u_segled_register(
.clk (clk),
.rst_n (rst_n),
//Avalon-MM 接口
.avs_address (avs_address),
.avs_write (avs_write),
.avs_writedata (avs_writedata),
//用户接口
.data (data),
.point (point),
.sign (sign),
.en (en),
);
//数码管逻辑功能文件
segled_logic u_segled_logic(
.clk (clk),
.rst_n (rst_n),
//用户接口
.data (data),
.point (point),
.sign (sign),
.en (en),
//数码管接口
.sel (sel),
.seg_led (seg_led)
);
endmodule
硬件逻辑文件segled_logic.v
module segled_logic(
//module clock
input clk , // 时钟信号
input rst_n , // 复位信号(低有效)
//seg_led interface
output reg [5:0] sel , // 数码管位选端(选择的数码管)
output reg [7:0] seg_led, // 数码管段选端(数码管数值显示的段)
//user interface
input [19:0] data , // 6 个数码管要显示的数值
input [ 5:0] point , // 小数点显示的位置,从左到右,高电平有效
input sign , // 显示符号位(高电平显示“-”号)
input en // 数码管使能信号
);
//parameter define
localparam MAX_NUM = 13'd5000 ; // 1ms 计数值
localparam CLK_DIVIDE = 4'd10 ; // 时钟分频
//reg define
reg [12:0] cnt0 ; // 1ms 计数
reg flag ; // 1ms 计满标志信号
reg [2:0] cnt ; // 切换显示数码管用
reg [3:0] num1 ; // 送给要显示的数码管,要亮的灯
reg point1 ; // 要显示的小数点
reg [23:0] num ; // 24 位 bcd 码用寄存器
reg [ 3:0] clk_cnt ; // 时钟计数
reg dri_clk ; // 驱动数码管操作的驱动时钟
//wire define
wire [3:0] data0 ; // 十万位数
wire [3:0] data1 ; // 万位数
wire [3:0] data2 ; // 千位数
wire [3:0] data3 ; // 百位数
wire [3:0] data4 ; // 十位数
wire [3:0] data5 ; // 个位数
//*****************************************************
//** main code
//*****************************************************
assign data5 = data[19:0] / 17'd100000; // 十万位数
assign data4 = data[19:0] / 14'd10000 % 4'd10; // 万位数
assign data3 = data[19:0] / 10'd1000 % 4'd10 ; // 千位数
assign data2 = data[19:0] / 7'd100 % 4'd10 ; // 百位数
assign data1 = data[19:0] / 4'd10 % 4'd10 ; // 十位数
assign data0 = data[19:0] % 4'd10; // 个位数
//生成数码管的驱动时钟用于驱动数码管的操作
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dri_clk <= 1'b1;
clk_cnt <= 4'd0;
end
else if(clk_cnt == CLK_DIVIDE/2 - 1'd1) begin
clk_cnt <= 4'd0;
dri_clk <= ~dri_clk;
end
else
clk_cnt <= clk_cnt + 1'b1;
end
//将 20 位 2 进制数转换为 8421bcd 码
always @ (posedge dri_clk or negedge rst_n) begin
if (!rst_n)
num <= 24'b0;
else begin
if (data5 || point[5]) begin
num[23:20] <= data5;
num[19:16] <= data4;
num[15:12] <= data3;
num[11:8] <= data2;
num[ 7:4] <= data1;
num[ 3:0] <= data0;
end
else begin
if (data4 || point[4]) begin
num[19:0] <= {data4,data3,data2,data1,data0};
if(sign)
num[23:20] <= 4'd11;
else
num[23:20] <= 4'd10;
end
else begin
if (data3 || point[3]) begin
num[15: 0] <= {data3,data2,data1,data0};
num[23:20] <= 4'd10;
if(sign)
num[19:16] <= 4'd11;
else
num[19:16] <= 4'd10;
end
else begin
if (data2 || point[2]) begin
num[11: 0] <= {data2,data1,data0};
num[23:16] <= {2{4'd10}};
if(sign)
num[15:12] <= 4'd11;
else
num[15:12] <= 4'd10;
end
else begin
if (data1 || point[1]) begin
num[ 7: 0] <= {data1,data0};
num[23:12] <= {3{4'd10}};
if(sign)
num[11:8] <= 4'd11;
else
num[11:8] <= 4'd10;
end
else begin
num[3:0] <= data0;
if(sign)
num[23:4] <= {{4{4'd10}},4'd11};
else
num[23:4] <= {5{4'd10}};
end
end
end
end
end
end
end
//计数 1ms
always @ (posedge dri_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
flag <= 1'b0;
cnt0 <= 13'b0;
end
else if (cnt0 < MAX_NUM - 1'b1) begin
flag <= 1'b0;
cnt0 <= cnt0 + 1'b1;
end
else begin
flag <= 1'b1;
cnt0 <= 13'b0;
end
end
//计数器,用来计数 6 个状态(因为有 6 个灯)
always @ (posedge dri_clk or negedge rst_n) begin
if (rst_n == 1'b0)
cnt <= 3'b0;
else if(flag) begin
if(cnt < 3'd5)
cnt <= cnt + 1'b1;
else
cnt <= 3'b0;
end
end
//6 个数码管轮流显示,完成刷新( 从右到左)
always @ (posedge dri_clk or negedge rst_n) begin
if(!rst_n) begin
sel <= 6'b000000;
num1 <= 4'b0;
end
else begin
if(en) begin
case (cnt)
3'd0: begin
sel <= 6'b111110;
num1 <= num[3:0] ;
point1 <= ~point[0] ;
end
3'd1: begin
sel <= 6'b111101;
num1 <= num[7:4] ;
point1 <= ~point[1] ;
end
3'd2: begin
sel <= 6'b111011;
num1 <= num[11:8];
point1 <= ~point[2] ;
end
3'd3: begin
sel <= 6'b110111;
num1 <= num[15:12];
point1 <= ~point[3] ;
end
3'd4: begin
sel <= 6'b101111;
num1 <= num[19:16];
point1 <= ~point[4];
end
3'd5: begin
sel <= 6'b011111;
num1 <= num[23:20];
point1 <= ~point[5];
end
default: begin
sel <= 6'b000000;
num1 <= 4'b0;
point1 <= 1'b1;
end
endcase
end
else
sel <= 6'b111111;
end
end
//数码管显示数据
always @ (posedge dri_clk or negedge rst_n) begin
if (!rst_n)
seg_led <= 7'h40;
else begin
case (num1)
4'd0 : seg_led <= {point1,7'b1000000};
4'd1 : seg_led <= {point1,7'b1111001};
4'd2 : seg_led <= {point1,7'b0100100};
4'd3 : seg_led <= {point1,7'b0110000};
4'd4 : seg_led <= {point1,7'b0011001};
4'd5 : seg_led <= {point1,7'b0010010};
4'd6 : seg_led <= {point1,7'b0000010};
4'd7 : seg_led <= {point1,7'b1111000};
4'd8 : seg_led <= {point1,7'b0000000};
4'd9 : seg_led <= {point1,7'b0010000};
4'd10: seg_led <= 8'b11111111;
4'd11: seg_led <= 8'b10111111;
default : seg_led <= {point1,7'b1000000};
endcase
end
end
endmodule
寄存器文件segled register.v
module segled_register(
input clk, // 时钟信号
input rst_n, // 复位信号(低有效)
//Avalon-MM 接口
input [ 1:0] avs_address, // Avalon 地址
input avs_write, // Avalon 写请求
input [31:0] avs_writedata, // Avalon 写数据
//用户接口
output reg [19:0] data, // 6 个数码管要显示的数值
output reg [ 5:0] point, // 小数点显示的位置,从左到右,高电平有效
output reg sign, // 显示符号位(高电平显示“-”号)
output reg en // 数码管使能信号
);
//*****************************************************
//** main code
//*****************************************************
//用于给进行赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data <= 20'd0; //显示数值寄存器
point <= 6'd0; //小数点位置寄存器
sign <= 1'b0; //符号使能寄存器
en <= 1'b0; //显示使能寄存器
end
else if(avs_write) begin
case(avs_address)
2'd0: //地址 0:显示数值寄存器
data <= avs_writedata[19:0];
2'd1: //地址 1:小数点位置寄存器
point <= avs_writedata[5:0];
2'd2: //地址 2:符号使能寄存器
sign <= avs_writedata[0];
2'd3: //地址 3:显示使能寄存器
en <= avs_writedata[0];
endcase
end
end
endmodule
4.1.2 使用IP核编辑器封装硬件逻辑
打开Platform Designer,选择New Component
在Component Type中填入相关信息
Name(名称) 、Display name(显示名称)、Version(版本号) 、Group(分组) 、Description(描述) 、Created by(创建者) 、Icon(组件图标)、Documentation(组件文档连接)
在Files中
首先点击Add File..将三个功能文件添加进来,如果没有选择顶层顶层文件还要在Attributes下no attributes的设置顶层文件,然后点击Analyze Synthesis Files对三个文件进行分析
如果代码没有问题就会分析成功
但还是会报错,这些错误后悔会进行解决
在 在Parameters页面中可以设置组件源码中定义的参数是否用户加载组件时可配置
在Signals&Interfaces中,
avalon_slave_0是Avalon-MM 总线的信号接口,Signals Type中要指定各个信号对应的类型
conduit_end是输出到Qsys系统外部的接口,是Qsys系统和外部接口的信号,通常是连接到FPGA引脚上的信号,它的 Signal Type 固定为 *(export)
clock_sink 为时钟信号,reset_sink 为复位信号
rst_n信号出现在了avalon_slave_0的interface中,这样就不能设置其Sign Type
因此添加Reset Input,然后把rst_n拖动到该Interface中,然后将Sign Type选择为reset
同理添加Conduit Interface,将sel和sel_led拖入,点击conduit_end,设置其Associated Reset为reset_sink,然后再设置seg_led和sel的Sign Type为export
这里会有一个export信号类型问题,expert信号需要自定义名字,每个名字只能对应一个端口,需要给每个export分配不同名字
同理设置avalon_slave的Associated Reset为reset_sink,至此就没有报错,点击下方finish生成自定义IP核