【精品博文】lemonHe分享:NIOS中寄存器映射
我的开发环境:Quartus II 13.1 (64-Bit) + Nios II 13.1 Software Build Tools for Eclipse
设计的初忠是利用Nios接收uart数据,然后通过寄存器的方式映射给逻辑,实现对数字图像帧频以及相关参数的调整。其实直接在逻辑中使用串口就行,还不用这么麻烦,但是由于程序中的串口指令比较复杂,使用了协议,如果用逻辑来做,解析指令太麻烦了。
言归正传,首先,在逻辑中新建一个带时钟、复位、一组avalon信号、一组对外接口的模块,代码如下:
//=============================================================================// File Name : registerMap// Module Name : Same with "File Name"// Function : 完成寄存器映射//============================================================================= module registerMap(//Avalon Clockinput csi_clk,input csi_rst_n,//Avalon-MMinput avs_chipselect,input [7:0] avs_address, //multiple of 4// input [1:0] avs_byteenable_n, //1,2,4,8,16,54,128input avs_write,input [31:0] avs_writedata, //32bit cpuinput avs_read,output [31:0] avs_readdata, //32bit cpu//Avalon Conduit //对外部接口output reg [7:0] Image_Test, output reg [7:0] Parameter1,output reg [7:0] NUC_TwoPoint, output reg [7:0] NUC_ByPass, output reg [7:0] BPR_Bypass, output reg [15:0] Linear_Adjust, output reg [31:0] PHE_Adjust, output reg [7:0] DRC_Select, output reg [23:0] IRControl, output reg [7:0] PowerOn); //write nios中数据写至逻辑reg [7:0] coe_data_r;reg [7:0] coe_data_g; always @(posedge csi_clk or negedge csi_rst_n) begin if (!csi_rst_n) coe_data_r <= 0; else if (avs_chipselect && avs_write) begin case(avs_address) 0: Image_Test <= avs_writedata[7:0]; 1: Parameter1 <= avs_writedata[7:0]; 2: NUC_TwoPoint <= avs_writedata[7:0]; 3: NUC_ByPass <= avs_writedata[7:0]; 4: BPR_Bypass <= avs_writedata[7:0]; 5: Linear_Adjust <= avs_writedata[15:0]; 6: PHE_Adjust <= avs_writedata[31:0]; 7: DRC_Select <= avs_writedata[7:0]; 8: IRControl <= avs_writedata[23:0]; 9: PowerOn <= avs_writedata[7:0]; endcase end end assign coe_data0 = coe_data_r;assign coe_data1 = coe_data_g; //read 逻辑中数据读至niosreg [7:0] avs_readdata_r;always @(posedge csi_clk or negedge csi_rst_n) begin if (!csi_rst_n) avs_readdata_r <= 0; else if (avs_chipselect && avs_read) //for steady state begin case(avs_address) 0:avs_readdata_r <= coe_data0; endcase end endassign avs_readdata = avs_readdata_r; endmodule
在Qsys中将该模块新加到组件,编译。
进行端口分配
Nios中采用中断的方式接收数据,在程序中加收到的数据进行判断,满足一定条件时,给某个寄存器映射一个值,Nios部分代码如下:
static alt_u32 *registerMap = (alt_u16 *)(REGISTERMAP_0_BASE);alt_u32 i = 0; printf("uartTask test is ok!\n"); while(!((IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK))); //发送准备好,发送txdata IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE,txdata); if(rxdata==0x01) { *(registerMap+0) = 1; } if(rxdata==0x02) { *(registerMap+1) = 2; } if(rxdata==0x03) { *(registerMap+2) = 3; } if(rxdata==0x04) { *(registerMap+3) = 4; } if(rxdata==0x05) { *(registerMap+4) = 5; } if(rxdata==0x06) { *(registerMap+5) = 6; } if(rxdata==0x07) { *(registerMap+6) = 7; } if(rxdata==0x08) { *(registerMap+7) = 8; } if(rxdata==0x09) { *(registerMap+8) = 9; } if(rxdata==0x0a) { *(registerMap+9) = 10; } rxdata = 0xaa;
Nios部分代码请参看博文【基于nios的uart核设计】,上面这个例程中使用的是基地址+偏移地址(*(registerMap+i))的方式来映射,我觉得这种方式最简单,并且用起来特别方便。此外,还有结构体方式,在Nios中定义一个结构体,学过c语言的同学都知道,结构体中,数据按照先后顺序在地址空间中存放,如果寄存器较多,使用结构体不是很方便。
参考:
http://www.cnblogs.com/yuphone/archive/2010/04/22/1717779.html