lemonHe

主要关注FPGA信号处理和数字图像处理技术,欢迎交流 邮箱:heliminlemon@163.com

NIOS中寄存器映射

1
阅读(1426)

我的开发环境: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 Clock
input                                           csi_clk,
input                                           csi_rst_n,
//Avalon-MM
input                                           avs_chipselect,
input                 [7:0]                  avs_address,        //multiple of 4
//    input    [1:0]    avs_byteenable_n,    //1,2,4,8,16,54,128
input                                           avs_write,
input                 [31:0]       avs_writedata,        //32bit cpu
input                                           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      逻辑中数据读至nios
reg   [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
         end
assign avs_readdata = avs_readdata_r;
 
endmodule

在Qsys中将该模块新加到组件,编译。

clip_image002

进行端口分配

clip_image004

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部分代码请参看博文【基于niosuart核设计】,上面这个例程中使用的是基地址+偏移地址(*(registerMap+i))的方式来映射,我觉得这种方式最简单,并且用起来特别方便。此外,还有结构体方式,在Nios中定义一个结构体,学过c语言的同学都知道,结构体中,数据按照先后顺序在地址空间中存放,如果寄存器较多,使用结构体不是很方便。


参考:

http://www.cnblogs.com/yuphone/archive/2010/04/22/1717779.html