模块架构:
自定义Component:
(1)点击new component
(2)在"Component Type"中为自己的component定义Group;
(3)在"Files"中添加自己的.v文件,然后点击"Aanlyze Synthesis Files";
(4) 定义.v文件中的接口的类型以及接口参数;1、2、3、4分别为Avalon Slave端口,时钟接口,外部信号接口,复位接口;紫色框中需要将时钟和复位信号关联;Parameters设置需要注意Adress units;
(5)至此,Component所有参数全部设置完成,点击Finish,等待Component生成
系统各模块添加 :
如图,红色框中为自己定义的Component;该模块需要通过Avalon-MM连接到NIOS II(cpu);pio_irq用来检测ram写满信号上升沿以产生中断
Verilog部分代码:
module avs_sram_ctrl
(
//sram port
input wire user_rd_clk,
output wire user_rd_req,
output wire [15:0] user_rd_addr,
input wire [15:0] user_rd_data,
input wire user_rd_valid,
//avalon-MM slave
input wire avs_clk,
input wire avs_rst_n,
input wire avs_chipselect_n,
input wire [8:0] avs_address,
input wire [3:0] avs_byteenable,
input wire avs_read_req,
output wire avs_read_valid,
output wire [32:0] avs_read_data,
input wire avs_write_req,
input wire [32:0] avs_write_data
);
assign user_rd_req = (avs_chipselect_n==1'b0) ? avs_read_req : 1'b0;
assign user_rd_addr = (avs_chipselect_n==1'b0) ? {7'd0,avs_address} : 16'd0;
assign avs_read_valid = user_rd_valid;
assign avs_read_data = user_rd_data;
endmodule
软核部分代码:
在软核代码中,地址以4递增,是因为在自定义Component部分,Address units设置的为WORDS;内部地址每次递增4,自定义Component部分输出的user_rd_addr才会每次递增1
//该部分代码使用基地址+4进行访问
#include <stdio.h>
#include <sys/unistd.h>
#include <string.h>
#include <sys/alt_irq.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_dma.h"
#include <sys/alt_cache.h>
#define DATA_LEN 288 //读取数据数量
void irq_init();
void irq_execute();
unsigned int buffer[DATA_LEN];
int main()
{
printf("Hello from Nios II!\n");
int m=0;
while(m<6)
{
irq_init();
printf("1");
usleep(1*1000*100);
m++;
printf("%d\n",m);
}
printf("OK");
return 0;
}
void irq_init(void)
{
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_IRQ_BASE,0x01);//使能中断
alt_ic_isr_register(PIO_IRQ_IRQ_INTERRUPT_CONTROLLER_ID, PIO_IRQ_IRQ, irq_execute,NULL,0x00);
}
void irq_execute(void)
{
int i;
int j;
int n=0;
unsigned int base_addr=AVS_SRAM_CTRL_BASE;//读取地址
// unsigned int * base_addr=AVS_SRAM_CTRL_BASE;//此处将base_addr定义为指针类型
for(j=0;j<DATA_LEN;j++)
{
buffer[j]=IORD_16DIRECT(base_addr,0);//IORD_16DIRECT()读取sram中的数据;
base_addr = base_addr + 4; //当base_addr为unsigned时每次递增4
// base_addr = base_addr + 1; //当base_addr为指针时,每次递增1
}
printf("\n====Start print data====\n");
for(i=0;i<DATA_LEN;i++)
{
printf("buffer[%d]=%d\t",i,buffer[i]);
}
printf("\n====End print data====\n");
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_IRQ_BASE,0x00);//清中断边沿寄存器
}
//该部分代码使用偏移地址+4进行访问
#include <stdio.h>
#include <sys/unistd.h>
#include <string.h>
#include <sys/alt_irq.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_dma.h"
#include <sys/alt_cache.h>
#define DATA_LEN 288 //读取数据数量
void irq_init();
void irq_execute();
unsigned int buffer[DATA_LEN];
int main()
{
printf("Hello from Nios II!\n");
int m=0;
while(m<6)
{
irq_init();
printf("1");
usleep(1*1000*100);
m++;
printf("%d\n",m);
}
printf("OK");
return 0;
}
void irq_init(void)
{
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_IRQ_BASE,0x01);//使能中断
alt_ic_isr_register(PIO_IRQ_IRQ_INTERRUPT_CONTROLLER_ID, PIO_IRQ_IRQ, irq_execute,NULL,0x00);
}
void irq_execute(void)
{
int i;
int j=0;
int n=0;
unsigned int base_addr = AVS_SRAM_CTRL_BASE;
for(j=0;j<DATA_LEN;j++)
{
buffer[j]=IORD_16DIRECT(base_addr ,n);//IORD_16DIRECT()读取sram中的数据;
n=n+4;
}
printf("\n====Start print data====\n");
for(i=0;i<DATA_LEN;i++)
{
printf("buffer[%d]=%d\t",i,buffer[i]);
}
printf("\n====End print data====\n");
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_IRQ_BASE,0x00);//清中断边沿寄存器
}
数据打印:
使用singal tap进行数据抓取:
(1)软核中,如果IORD_16DIRECT()地址以2递增,波形如下,可以发现:输出的user_rd_addr前后两次都是19
(2)软核代码中,读取地址如果以4递增,波形如下,可以发现:输出的user_rd_addr递增1