(原创)Avalon master接口的简易写法(基于Avalon总线的简易dma的实现)

参照张老师的一个例程,练习了下写Avalon master。整个例子有3个接口,一个从端口,两个主端口。其中两个主端口一个用于读,另一个用于写。从端口对整个模块进行控制。整个模块实现了一个简易dma的功能(不带fifo)。主要的控制信号有源地址S_addr,目的地址D_addr,以及数据搬运的长度Longth。

代码
` include   " sdram_master_defines.v "
/*
hl.ren.pub@gmail.com
*/


module  sdram_master(
    
//  signals to connect to an Avalon clock source interface
    clk,
    reset,
    
    
//  signals to connect to an Avalon-MM slave interface
    avs_s1_chipselect,
    avs_s1_address,
    avs_s1_read,
    avs_s1_write,
    avs_s1_readdata,
    avs_s1_writedata,
    avs_s1_byteenable,
    avs_s1_waitrequest,

    
//  read master port interface
    avm_read_address,
    avm_read_read,
    
// avm_read_byteenable,
    avm_read_readdata,
    avm_read_waitrequest,
    
    
//  write master port interface
    avm_write_address,
    avm_write_write,
    
// avm_write_byteenable,
    avm_write_writedata,
    avm_write_waitrequest

    );
    
input     clk;
input      reset;
input      avs_s1_chipselect;
input      [ 2 : 0 ]     avs_s1_address;
input      avs_s1_read;
output       reg  [ 31 : 0 ]     avs_s1_readdata;
input      avs_s1_write;
input      [ 31 : 0 ]     avs_s1_writedata;
input      [ 3 : 0 ]     avs_s1_byteenable;
output     avs_s1_waitrequest;

    
//  read master port interface
output      reg     [ 31 : 0 ]    avm_read_address;
output      reg     avm_read_read;
// output    reg    [3:0]    avm_read_byteenable;
// input    [31:0]    avm_read_readdata;
input     [ 15 : 0 ]    avm_read_readdata;
input     avm_read_waitrequest;
    
    
//  write master port interface
output      reg     [ 31 : 0 ]    avm_write_address;
output      reg     avm_write_write;
// output    reg    [3:0]    avm_write_byteenable;
// output    reg    [31:0]    avm_write_writedata;
output      reg     [ 15 : 0 ]    avm_write_writedata;
input     avm_write_waitrequest;

reg     [ 31 : 0 ]    S_addr; // source address
reg     [ 31 : 0 ]    D_addr; // destination  address
reg     [ 31 : 0 ]    Longth;

reg     Status;

// reg     [31:0]     DMA_DATA;
reg      [ 15 : 0 ]     DMA_DATA;

reg      [ 31 : 0 ]    DMA_Cont;

reg     avs_s1_read_last;
always @( posedge  clk)
begin
    avs_s1_read_last 
<=  avs_s1_read;
end

wire     avs_s1_waitrequest;
assign     avs_s1_waitrequest  =   ~ (avs_s1_read_last  |  avs_s1_write);

// read and write regs
always @( posedge  clk  or   posedge  reset)
begin
        
if (reset)  begin
            S_addr         
<=   32 ' h0;    
            D_addr          <=   32 ' h0;    
            Longth          <=   32 ' h0;
         end
        
else       begin
            
if ((avs_s1_chipselect == 1 ' b1) && (avs_s1_write==1 ' b1))  begin
                
case (avs_s1_address)
                    `S_ADDR:            S_addr         
<=  avs_s1_writedata;
                    `D_ADDR:            D_addr         
<=  avs_s1_writedata;
                    `LONGTH:            Longth         
<=  avs_s1_writedata;
                
endcase
            
end
            
else      begin
                
if ((avs_s1_chipselect == 1 ' b1) && (avs_s1_read==1 ' b1))  begin
                    
case (avs_s1_address)
                        `S_ADDR:            avs_s1_readdata 
<=  S_addr;
                        `D_ADDR:            avs_s1_readdata 
<=  D_addr;
                        `LONGTH:            avs_s1_readdata 
<=  Longth;
                        `STATUS_ADDR:    avs_s1_readdata 
<=  { 31 ' h0,Status};
                         default :             avs_s1_readdata  <=   32 ' h0;
                     endcase
                
end
            
end
        
end
end


// start signal
reg     start;
always @( posedge  clk  or   posedge  reset)
begin
    
if (reset)
        start         
<=   1 ' b0;
     else       if ((avs_s1_chipselect == 1 ' b1) & (avs_s1_write==1 ' b1)  &  (avs_s1_address  ==  `START_ADDR))    
                start     
<=   1 ' b1;
             else  start      <=   1 ' b0;
end

// status signal
reg     done;
reg  done_last;
always @( posedge  clk)
begin
    
if (reset)     done_last          <=   1 ' b0;
     else          done_last          <=  done;
end


always @( posedge  clk)
begin
    
if (reset)
    
begin
        Status 
<=   1 ' b0;
     end
    
else       if ((avs_s1_chipselect == 1 ' b1) &  (avs_s1_write==1 ' b1)   &  (avs_s1_address  ==  `START_ADDR) )    
            
begin
                Status 
<=   1 ' b0;
             end
            
else       if ( (done_last  ==   1 ' b0 )&( done == 1 ' b1) )
                    
begin
                        Status 
<=   1 ' b1;
                     end
end

// FSM

reg     [ 5 : 0 ]    DMA_state;

parameter     DMA_IDLE                 =      0 ;
parameter     READ                     =      1 ;
parameter     WAIT_READ                 =      2 ;
parameter     WRITE                 =      3 ;
parameter     WAIT_WRITE             =      4 ;
parameter     CALC_NEXT                 =      5 ;
parameter     DMA_DONE                 =      6 ;

always @( posedge  clk)
begin
    
if (reset)  begin
        DMA_state 
<=  DMA_IDLE;
        DMA_Cont     
<=   32 ' h0;
     end
    
else   begin
        
case (DMA_state)
            DMA_IDLE: 
begin
                DMA_Cont 
<=   32 ' h0;
                done                  <=   1 ' b0;
                 if (start) 
                    DMA_state         
<=  READ;
            
end
            READ: 
begin
                avm_read_address 
<=  S_addr  +  DMA_Cont;
                
// avm_read_byteenable <= 4'b0001; 
                avm_read_read  <=   1 ' b1;
                DMA_state     <=  WAIT_READ;
            
end
            WAIT_READ: 
begin
                
if (avm_read_waitrequest  ==   1 ' b0 )
                 begin
                    avm_read_read 
<=   1 ' b0;
                    DMA_DATA  <=  avm_read_readdata;
                    DMA_state 
<=  WRITE;
                
end
            
end
            WRITE: 
begin
                avm_write_address 
<=  D_addr  +  DMA_Cont;
                
// avm_write_byteenable <= 4'b0001;
                avm_write_write  <=   1 ' b1;
                avm_write_writedata  <=  DMA_DATA;
                
// avm_write_writedata <= DMA_Cont; // temp test
                DMA_state  <=  WAIT_WRITE;
            
end
            WAIT_WRITE: 
begin
                
if (avm_write_waitrequest  ==   1 ' b0 )
                     begin
                        DMA_Cont 
<=  DMA_Cont  +   32 ' h2;
                         // avm_write_address <= 0;
                        avm_write_write  <=   1 ' b0;
                         if (DMA_Cont  <  Longth)
                            DMA_state 
<=  READ;
                        
else
                            DMA_state 
<=  DMA_DONE;
                            
                    
end
            
end
            DMA_DONE: 
begin
                done 
<=   1 ' b1;
                DMA_state  <=  DMA_IDLE;
            
end
            
default begin
                DMA_state 
<=  DMA_IDLE;
            
end             
        
endcase
    
end
end
endmodule

 

 整个运行过程由一个状态机DMA_state来控制。sdram_master_defines.v定义了一些从端口的地址。

 编写段简易的程序来驱动和验证这个simple-dma。

 代码

/*
 * "Hello World" example.
 *
 * This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
 * the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
 * designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT
 * device in your system's hardware.
 * The memory footprint of this hosted application is ~69 kbytes by default
 * using the standard reference design.
 *
 * For a reduced footprint version of this template, and an explanation of how
 * to reduce the memory footprint for a given application, see the
 * "small_hello_world" template.
 *
 
*/
#include 
< stdio.h >
#include 
" sdram_master.h "
#include 
" system.h "
#include 
" io.h "

int  main()
{
    unsigned 
char  i,j;
    
int  temp;
    
for (i = 0 ;i < 100 ;i ++ )
        IOWR_8DIRECT(SDRAM_U1_BASE,i,i);
    
    IOWR(SDRAM_MASTER_INST_BASE,S_ADDR,SDRAM_U1_BASE);
    IOWR(SDRAM_MASTER_INST_BASE,D_ADDR,SDRAM_U2_BASE);
    IOWR(SDRAM_MASTER_INST_BASE,LONGTH,
100 );
    IOWR(SDRAM_MASTER_INST_BASE,START_ADDR,
1 );
    
    temp
= IORD(SDRAM_MASTER_INST_BASE,S_ADDR);
    printf(
" S_ADDR:w,r==%d,%d\n " ,SDRAM_U1_BASE,temp);
    temp
= IORD(SDRAM_MASTER_INST_BASE,D_ADDR);
    printf(
" D_ADDR:w,r==%d,%d\n " ,SDRAM_U2_BASE,temp);    
    temp
= IORD(SDRAM_MASTER_INST_BASE,LONGTH);
    printf(
" LONGTH:w,r==%d,%d\n " , 100 ,temp);    
    
    
while (IORD(SDRAM_MASTER_INST_BASE,STATUS_ADDR) != 1 ){
    printf(
" waiting...!\n " );
    
// break;
    };
    
    
for (i = 0 ;i < 100 ;i ++ ){
        j
= IORD_8DIRECT(SDRAM_U1_BASE,i);
        printf(
" SDRAM_U1:i,j == %d, %d\n " ,i,j);
    }
    
for (i = 0 ;i < 100 ;i ++ ){
        j
= IORD_8DIRECT(SDRAM_U2_BASE,i);
        printf(
" SDRAM_U2:i,j == %d, %d\n " ,i,j);
    }    
        
    
  printf(
" Hello from Nios II!\n " );

  
return   0 ;
}

 

 运行结果和设想的一样,没有错误。

本文中所设计模块的全部代码可以以下方式取得(linux下需安装git,windows下可安装msysgit):

git clone git://github.com/orlunix/simple-dma.git 

转载于:https://www.cnblogs.com/lunix/archive/2010/08/28/simple-dma.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值