SOPC之NiosⅡ系统(三)

常用NIOS Ⅱ组件概括

目录

1.定时器Timer

1.1 预定义硬件配置

1.2 超时周期Timeout poriod

1.3 计数器大小Timer counter Size

1.4 寄存器Registers

2.串口UART

2.1 基础设置Basic settings

2.1.1 奇偶校验Parity

2.1.2 数据为Data bits

2.1.3 停止位Stop bits

2.1.4 其他

2.2 波特率设置Baud rate

3.SDRAM

3.1 Memory Profile

3.2 Timing

4. 自定义IP核


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位。

名称操作描述
0PE读/清除Parity Error。当读取的校验位不正确时会发生校验错误且PE位置1。PE 位为1时,需要通过写status寄存器将其清零。当PE位置时,读取rxdata寄存器会产生未定义值。如果没有选中Parity硬件选项,UARTIP核则没有奇偶校验,并且读PE位总是0。
1FE读/清除Framing Error。当接收器没能检测到正确的停止位时,会产生帧错误。当核接收到错误的停止位时,FE位置1。FE 位置1后,直到给status寄存器写数据才会将其清零。当FE位置1时,读rxdata寄存器会返回未定义的值。
2BRK读/清除Break Detect。当RXD引脚连续保持低电平 (逻辑 0)的时间大于一个完整字符的时间(数据位,加上起始、停止和校验位) 时,接收逻辑才会检测到间断。当检测到间断时,BRK位置 1。BRK位为1时,需要通过写status寄存器才能将其清零。
3ROE读/清除Receive Overrun Error。在读取前一个字符前 (即RRDY位为1时),将一个新的字符传输给rxdata寄存器,会产生接收溢出错误。此时,ROE位置 1,且接收数据寄存器内前一个接收字符被新的接收字符改写。BRK位为1时,需要通过写状态寄存器将其清零。
4TOE读/清除Transmit Overrun Error。在前一个字符传输到移位寄存器前,将新字符写入txdata寄存器 (TRDY位为0 时),会产生溢出错误。此时TOE位置1。TOE位置1后,直到给 status寄存器写1才会将其清零。
5TMTTransmit Empty。TMT位提示发送移位寄存器的当前状态。当移位寄存器正将字符从 TXD引脚输出时,TMT位设为 0。当移位寄存器处于空闲时(没有要输出的字符),TMT位为1。Avalon-MM主控制器可以通过检查TMT位来确定发送是否完成。
6TRDYTransmit Ready。TRDY位提示txdata寄存器的当前状态。当txdata寄存器为空时,可以接收新字符且TRDY位为 1。当txdata寄存器为满状态时,TRDY位为 0。Avalon-MM主控制器必须等待TRDY位变为1后,才能新数据写入txdata寄存器中。
7RRDYReceive Character Ready。RRDY位提示rxdata寄存器的当前状态。当rxdata寄存器为空时,RRDY为0,且还不是读取rxdata寄存器的时刻。当新接收的值传输到rxdata 寄存器时,RRDY位置 1。读rxdata寄存器会将RRDY位置零。Avalon-MM主控制器必须等待RRDY位变为1后,才能读取rxdata寄存器。
8E读/清除Exception。E位指示发生了错误。E位是TOE、ROE、BRK、FE 和 PE位的逻辑或结果。E位和control寄存器相应的中断使能位 (IE) 给使能/禁止所有错误IRQ提供了便利方法。对status寄存器进行写操作时,E位会置0。
10DCTS读/清除Change in Clear to Send (CTS) signal。只要在CTSN输入端口上检测到逻辑电平跳变时(采样与Avalon时钟同步),DCTS位置 1。该位通过CTS N上的上升沿和下降沿跳变设置。DCTS位置1后,直到给status寄存器写入数据将其清零,它的值才会发生变化。
11CTSClear to Send (CTS) signal。CTS位反映CTSN输入的瞬时状态(采样与Avalon时钟同步)。CTSN输入对发送或接收逻辑没有影响。CTSN输入仅会影响CTS和DCTS位状态,且当control寄存器的idcts位使能时,有可能产生中断。
12EOPEnd 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。

名称操作描述
0IPE读写奇偶校验错误中断使能
1IFE读写帧错误中断使能
2IBRK读写间断检测中断使能
3IROE读写接收溢出错误中断使能
4ITOE读写发送溢出错误中断使能
5ITMT读写发送移位寄存器空中断使能
6ITRDY读写发送准备好中断使能
7IRRDY读写接收准备好中断使能
8IE读写错误中断使能
9TRBK读写发送间断。TRBK位允许Avalon-MM主控制器通过TXD输出发送间断字符。当TRBK位设为1时,TXD信号强制设为 0。TRBK位会干扰任何进行中的发送Avalon主控制器必须在适当的间断周期后将TRBK位设回0。
10IDCTS读写CTS 信号改变中断使能
11RTS读写请求发送(RTS)信号。RTS位直接连接到RTS_N输出。Avalon-MM主控制器可在任何时候写RTS位。RTS位的值只能影响RTS_N输出;它对发送器或接收器逻辑没有影响。由于 RTS_N输出为负逻辑。当RTS位为1时,RTS_N输出逻辑低电平0。
12IEOP读写结束符中断使能

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核

自定义seg_decoder

首先要使用硬件描述语言描述硬件逻辑,一个典型的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..将三个功能文件添加进来,如果没有选择顶层顶层文件还要在Attributesno 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核

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值