OpenRisc-33-关于用户空间程序直接访问ipcore问题的分析与解决

引言

在实现内核程序(driver)和硬件(ipcore)的memory共享时,需要解决的主要问题是如何将用kmalloc()函数获得的内核逻辑地址转换成物理地址,以供硬件(ipcore)使用,最终实现DMA操作。

内核空间的程序(driver)和ipcore的memory的共享问题已经解决,请参考:

http://blog.csdn.net/rill_zhen/article/details/9121009

这时,如果用户空间的程序(AP)想向ipcore传递数据,可以在内核空间的driver部分的read/write函数的实现时通过copy_from_user和copy_to_user两个函数与用户空间程序实现数据交换,然后通过上面的方式,再与ipcore实现数据交换。

这样做可以实现AP和ipcore的数据交换,并且在数据量比较小时队系统的影响也不大。但是,如果AP和ipcore交换的数据较大时,就会严重影响系统性能。甚至,如果不用DMA,后果就更严重。

本小节就解决这个问题。


1,三种方式的数据流向

为了更清晰的说明在AP和ipcore间的数据交换的具体过程,我假设了三种方式:


1>方式a:

1》AP和kernel通过copy_from_user和copy_to_user两个函数实现数据交换。

2》kernel和ipcore之间通过io_read32/io_write32两个函数实现数据交换。

3》CPU需要进行2次数据拷贝。

2>方式b:

1》AP和kernel通过copy_from_user和copy_to_user两个函数实现数据交换。

2》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过DMA的方式实现数据交换。

3》CPU需要进行1次数据拷贝。

3>方式c:

1》AP和kernel通过mmap()函数将ipcore的物理地址(也可以是内核空间的逻辑地址)映射到用户空间。

如果是内核空间的逻辑地址(ipcore和内核共享SDRAM):不带显存的显卡采用的就是这种方式(framebuffer)。

2.1》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过DMA的方式实现数据交换。

如果是ipcore的地址(ipcore有local RAM,不与内核共享SDRAM):带显存的显卡采用的就是这种方式(framebuffer)

2.2》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过可以直接访问本地数据的方式实现数据交换。

3》CPU需要进行0次数据拷贝,即CPU不进行数据拷贝,可以完全从大量数据拷贝工作中解脱出来。


注:上述3中方式均不考虑最初的那次数据拷贝(从文件(disk)到内存(SDRAM))。


对比上述三种情况,很显然第三种效率最高,前两种方式我们之前都采用过,分别是:

采用方式a的情况:

http://blog.csdn.net/rill_zhen/article/details/8722664

采用方式b的情况:

http://blog.csdn.net/rill_zhen/article/details/8849149

而本小节就是采用方式c中ipcore有local RAM,不与内核共享SDRAM的情况。


采为了更直观的表示上述三种情况,我做了如下对比图:



2,软件部分

1>功能概述

为了实现上面所述的方式c2的情况,软件部分的工作如下:

1》在驱动层实现mmap函数,将mkg_slave的地址空间映射给用户(主要调用io_remap_pfn_range()函数实现将ipcore的物理地址映射到用户空间)

2》在用户层调用mmap()获得对应的虚拟地址

3》用户程序直接操作这个虚拟地址,就可以实现直接操作my_ram这个ipcore

2>验证

将之前驱动部分的工作(调用io_read32()/io_write32())交给用户层来做,如果ipcore工作良好,则说明这个方式是成功的。

具体信息请参考之前其他blog中的driver的内容。


3>代码实现

1》驱动层代码

3个文件:ip_mkg.c,ip_mkg.h,makefile


ip_mkg.c:


/*
*
* rill mkg driver
*
*/
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* get_user and put_user */
//#include <linux/clk.h>
//#include <linux/ioport.h>
#include <asm/io.h> /*ioremap*/
#include <linux/platform_device.h> /*cleanup_module*/
#include <linux/delay.h>
#include <asm-generic/io.h>

#include "ip_mkg.h"



void	__iomem 	*g_mkg_mem_base = NULL;
void  __iomem   *g_mkg_core_base = NULL;

static int device_open(struct inode *inode, struct file *file)
{
	g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
	g_mkg_core_base = ioremap (MKG_CORE_BASE, MKG_CORE_LEN);
	
	if(NULL == g_mkg_mem_base)
	{
		printk(KERN_ERR "mkg mem open ioremap error!\n");
		return -1;
	}
	else
	{
		printk("mkg mem ioremap addr:%d!\n",(int)g_mkg_mem_base);
	} 
		if(NULL == g_mkg_core_base)
	{
		printk(KERN_ERR "mkg core open ioremap error!\n");
		return -1;
	}
	else
	{
		printk("mkg core ioremap addr:%d!\n",(int)g_mkg_core_base);
	}
 
	return 0;
}

static int device_release(struct inode *inode, struct file *file)
{
	return 0;
}


static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
{
	/*int ret_val = 0;

	char * data = NULL;
	
	data = (char*)kmalloc(4, GFP_KERNEL);
	if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) 

	ioread32(g_mkg_mem_base+length);
	printk("============read:%d\n",);*/
	
	return 1;
}

static ssize_t device_write(struct file *filp, const char *buffer, size_t count, loff_t *offset)
{
	//iowrite32(2,g_mkg_mem_base);
	return 1;
}

long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
#if 0

   int ret_val = 0;
   unsigned int ret = 0;
   struct reg_data *new_regs;
   printk("ioctl======\n");

   switch(ioctl_num)
   {
      case IOCTL_REG_SET:
	  {
		 new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL);
		 if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) 
		 	{
			    kfree(new_regs);
			    printk(KERN_ERR " error copy line_datafrom user.\n");
				return -1;
		 	}

			//iowrite16(new_regs->value,g_mkg_mem_base+new_regs->addr);
		 kfree(new_regs);
     }
	 break;

	case IOCTL_REG_GET:
	{
	 new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL);
	 if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) 
	 	{
		    kfree(new_regs);
		    printk(KERN_ERR " error copy line_datafrom user.\n");
			return -1;
	 	}

		//ret = ioread16(g_mkg_mem_base+new_regs->addr);
	 	kfree(new_regs);
		return ret;
	}
	break;
      
   }
#endif

  return -1;
}
void device_vma_open (struct vm_area_struct * vma)
{
	printk("ip_mkg vma open ,virt 0x%x, phy  0x%x\n",vma->vm_start,vma->vm_pgoff<<PAGE_SHIFT);
}
void device_vma_close(struct vm_area_struct * vma)
{
 	printk("ip_mkg vma close \n");
}

static struct vm_operations_struct device_remap_vm_ops =
{
	.open = device_vma_open,
	.close = device_vma_close,
};
static int device_mmap (struct file * filp,struct vm_area_struct * vma)
{

 unsigned long off;
 unsigned long start;
 if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 {
  printk("vm_pgoff is wrong !\n");
  return -EINVAL;
 }
 start=0x97000000;
 start &= PAGE_MASK;
 printk("start is 0x%x \n",start);
 off=vma->vm_pgoff<<PAGE_SHIFT;
 off+=start;
 printk("off is 0x%x   \n",off);
 vma->vm_pgoff=off>>PAGE_SHIFT;
 vma->vm_flags |=VM_IO | VM_RESERVED;
 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
 printk(" vm_start: 0x%x ,off : 0x%x \n ",vma->vm_start,off>>PAGE_SHIFT);
 if(io_remap_pfn_range(vma,vma->vm_start,off >> PAGE_SHIFT,vma->vm_end-vma->vm_start,vma->vm_page_prot))
 { printk("remap_pfn_range error \n");
	return - EAGAIN;
}
 printk("remap success \n");
 
//  vma->vm_ops = & device_remap_vm_ops;
//  device_vma_open( vma);
 return 0;
}
struct file_operations our_file_ops = {
  .unlocked_ioctl = device_ioctl,
  .read = device_read,
  .write = device_write,
  .open = device_open,
  .release = device_release,
  .mmap = device_mmap,
  .owner = THIS_MODULE,
};



int ToBigEndian(int lit_End)
{
   char * p=(char *)&lit_End;
   
   return (int)(p[0]<<24)+(int)(p[1]<<16)+(int)(p[2]<<8)+(int)(p[3]);
}
void test(void)
{  
 /*
  int write_data[256]={
  	0x69016901, 0x8b014401, 0xa7011a01, 0xbd01ee00, 0xcd01bf00, 0xd7018f00, 0xdb015e00, 0xd8012e00, 0xcf010000, 
  	0xc101d403, 0xad01ab03, 0x94018603, 0x78016503, 0x58014803, 0x35013203, 0x11012003, 0xec001403, 0xc7000e03, 
  	0xa3000c03, 0x80001003, 0x5f001903, 0x42002503, 0x28003603, 0x12004803, 0x00005e03, 0xf3037403, 0xe9038b03,
  	0xe403a303, 0xe303b903, 0xe603ce03, 0xec03e203, 0xf503f203, 0x00000000, 0x0d000a00, 0x1c001200, 0x2b001700, 
  	0x3a001800, 0x49001600, 0x56001100, 0x62000900, 0x6c000000, 0x7400f503, 0x7900e803, 0x7c00db03, 0x7b00cd03, 
  	0x7800c003, 0x7300b303, 0x6b00a803, 0x61009f03, 0x56009703, 0x4a009203, 0x3c008f03, 0x2f008e03, 0x21009003,
  	0x15009503, 0x09009c03, 0x0000a403, 0xf803af03, 0xf203ba03, 0xef03c603, 0xee03d303, 0xef03e003, 0xf303ec03, 
  	0xf903f703, 0x00000000, 0x09000700, 0x14000d00, 0x20001100, 0x2d001200, 0x3a001100, 0x46000e00, 0x52000800, 
  	0x5c000000, 0x6400f703, 0x6b00eb03, 0x7000df03, 0x7200d103, 0x7100c403, 0x6e00b603, 0x6900aa03, 0x61009f03, 
  	0x58009503, 0x4d008d03, 0x40008803, 0x33008503, 0x25008403, 0x18008703, 0x0b008c03, 0x00009403, 0xf7039e03,
  	0xef03aa03, 0xea03b703, 0xe803c603, 0xe903d503, 0xee03e403, 0xf603f303, 0x00000000, 0x0e000b00, 0x1e001400,
  	0x32001a00, 0x47001d00, 0x5d001c00, 0x75001700, 0x8c000d00, 0xa2000000, 0xb800ee03, 0xcb00d803, 0xdb00be03, 
  	0xe700a103, 0xf0008003, 0xf4005d03, 0xf2003903, 0xec001403, 0xe000ef02, 0xcf00cb02, 0xb800a802, 0x9b008802, 
  	0x7a006c02, 0x55005302, 0x2c003f02, 0x00003102, 0xd2032802, 0xa2032502, 0x71032902, 0x41033302, 0x12034302,
  	0xe6025902, 0xbc027502, 0x97029702, 0x7502bc02, 0x5902e602, 0x43021203, 0x33024103, 0x29027103, 0x2502a203,
  	0x2802d203, 0x31020000, 0x3f022c00, 0x53025500, 0x6c027a00, 0x88029b00, 0xa802b800, 0xcb02cf00, 0xef02e000,
  	0x1403ec00, 0x3903f200, 0x5d03f400, 0x8003f000, 0xa103e700, 0xbe03db00, 0xd803cb00, 0xee03b800, 0x0000a200, 
  	0x0d008c00, 0x17007500, 0x1c005d00, 0x1d004700, 0x1a003200, 0x14001e00, 0x0b000e00, 0x00000000, 0xf303f603, 
  	0xe403ee03, 0xd503e903, 0xc603e803, 0xb703ea03, 0xaa03ef03, 0x9e03f703, 0x94030000, 0x8c030b00, 0x87031800, 
  	0x84032500, 0x85033300, 0x88034000, 0x8d034d00, 0x95035800, 0x9f036100, 0xaa036900, 0xb6036e00, 0xc4037100,
  	0xd1037200, 0xdf037000, 0xeb036b00, 0xf7036400, 0x00005c00, 0x08005200, 0x0e004600, 0x11003a00, 0x12002d00, 
  	0x11002000, 0x0d001400, 0x07000900, 0x00000000, 0xf703f903, 0xec03f303, 0xe003ef03, 0xd303ee03, 0xc603ef03, 
  	0xba03f203, 0xaf03f803, 0xa4030000, 0x9c030900, 0x95031500, 0x90032100, 0x8e032f00, 0x8f033c00, 0x92034a00, 
  	0x97035600, 0x9f036100, 0xa8036b00, 0xb3037300, 0xc0037800, 0xcd037b00, 0xdb037c00, 0xe8037900, 0xf5037400, 
  	0x00006c00, 0x09006200, 0x11005600, 0x16004900, 0x18003a00, 0x17002b00, 0x12001c00, 0x0a000d00, 0x00000000, 
  	0xf203f503, 0xe203ec03, 0xce03e603, 0xb903e303, 0xa303e403, 0x8b03e903, 0x7403f303, 0x5e030000, 0x48031200, 
  	0x36032800, 0x25034200, 0x19035f00, 0x10038000, 0x0c03a300, 0x0e03c700, 0x1403ec00, 0x20031101, 0x32033501, 
  	0x48035801, 0x65037801, 0x86039401, 0xab03ad01, 0xd403c101, 0x0000cf01, 0x2e00d801, 0x5e00db01, 0x8f00d701, 
  	0xbf00cd01, 0xee00bd01, 0x1a01a701, 0x44018b01
  	}; 
  int read_rslt[256];
  int loop1=	0;
  int loop2=	0;
  int loop3=	0;
  int loop4=  0;
  int loop5=  0;
  int temp=		0;
  
  printk("<----ip_mkg test start---->\n");
  for(loop1=0;loop1<256;loop1++)
  read_rslt[loop1]=0x98766789;
  printk("<----the initialization of result --->\n");
  
  for(loop2=0;loop2<256;loop2++)
   {
     iowrite32(write_data[loop2],g_mkg_mem_base+(loop2*4));
   }
   printk("<----write orignal data --->\n");
   iowrite32(0x01000000,g_mkg_core_base+0x4);
   printk("<---write control data --->\n"); */
    unsigned int  * virt_adr;
    unsigned int phy_adr;
    int write_done=0,read_done=0,read_value=0;
    unsigned int final_phy_adr;
    char *p;
    int read=0;
    virt_adr=kmalloc(4,GFP_DMA);
    if(!virt_adr)
    printk("apply for kernel memory fails !\n");
     
    phy_adr=virt_to_phys(virt_adr);
    printk("virtual address !0x%x \n ",virt_adr);		
     printk("original physical address !0x%x \n",phy_adr); /*
    p=(char *)&phy_adr;
    final_phy_adr=(unsigned int)(p[3]<<24);
 printk("final physical address !0x%x \n ",final_phy_adr);
    final_phy_adr=final_phy_adr+(unsigned int)(p[2]<<16);
 printk("final physical address !0x%x \n ",final_phy_adr);
     final_phy_adr=final_phy_adr+(unsigned int)(p[1]<<8);
 printk("final physical address !0x%x \n ",final_phy_adr);
    final_phy_adr=final_phy_adr+(unsigned int)(p[0]);
 
    printk("final physical address !0x%x \n ",final_phy_adr);   */

 //  final_phy_adr= (int)(p[0]<<24)+(int)(p[1]<<16)+(int)(p[2]<<8)+(int)(p[3]);
 /*  *virt_adr=0x6789abcd;
    iowrite32(final_phy_adr,g_mkg_core_base+0x4);
    printk("read address done !\n");
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value); */

    *virt_adr=0x6789bcdf;
    final_phy_adr=phy_adr;
 //   final_phy_adr=0x98000040;
    printk("final physical address !0x%x \n ",final_phy_adr); 
//  test begin
//  write first number : final_phy_adr
    printk("test begin \n write first number : final_phy_adr\n");
    iowrite32(final_phy_adr,g_mkg_core_base+0x4);
    printk("write address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("write address : 0x%x \n",read);
    iowrite32(0x3956abcd,g_mkg_core_base+0x8);
    printk("write value done !\n");
    read=ioread32(g_mkg_core_base+0x8);
    printk("write value : 0x%x \n",read);
    iowrite32(0x01000000,g_mkg_core_base+0x18);
    printk("write command done !\n");
    printk("write two number:  final_phy_adr+4 \n");
//  write two number:  final_phy_adr+4
iowrite32(final_phy_adr+4,g_mkg_core_base+0x4);
    printk("write address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("write address : 0x%x \n",read);
    iowrite32(0x3956abcd,g_mkg_core_base+0x8);
    printk("write value done !\n");
    read=ioread32(g_mkg_core_base+0x8);
    printk("write value : 0x%x \n",read);
    iowrite32(0x01000000,g_mkg_core_base+0x18);
    printk("write command done !\n");
//  write third number: final_phy_adr-4
    printk("write third number: final_phy_adr-4 \n");
    iowrite32(final_phy_adr-4,g_mkg_core_base+0x4);
    printk("write address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("write address : 0x%x \n",read);
    iowrite32(0x3956abcd,g_mkg_core_base+0x8);
    printk("write value done !\n");
    read=ioread32(g_mkg_core_base+0x8);
    printk("write value : 0x%x \n",read);
    iowrite32(0x01000000,g_mkg_core_base+0x18);
    printk("write command done !\n");
//  write forth number:	0x98000040
    printk("write forth number: 98000040 \n");
   iowrite32(0x98000040,g_mkg_core_base+0x4);
    printk("write address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("write address : 0x%x \n",read);
    iowrite32(0x3956abcd,g_mkg_core_base+0x8);
    printk("write value done !\n");
    read=ioread32(g_mkg_core_base+0x8);
    printk("write value : 0x%x \n",read);
    iowrite32(0x01000000,g_mkg_core_base+0x18);
    printk("write command done !\n");
    read=ioread32(g_mkg_core_base+0x18);
    printk("write command : 0x%x \n",read);
     write_done=ioread32(g_mkg_core_base+0x0c);
//   read first number : final_phy_adr
  printk("read first number : final_phy_adr\n");
     iowrite32(final_phy_adr,g_mkg_core_base+0x4);
    printk("read address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("read address : 0x%x \n",read);
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    read=ioread32(g_mkg_core_base+0x18);
    printk("read command : 0x%x \n",read);
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<write_done flag: 0x%x   >\n",write_done);
    printk("<read from or1200: 0x%x  >\n",*virt_adr); 
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value); 
printk(" read second number	: final_phy_adr+4\n");
//  read second number	: final_phy_adr+4
    iowrite32(final_phy_adr+4,g_mkg_core_base+0x4);
    printk("read address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("read address : 0x%x \n",read);
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    read=ioread32(g_mkg_core_base+0x18);
    printk("read command : 0x%x \n",read);
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value);
printk("  read third number 	: final_phy_adr-4\n");
//  read third number 	: final_phy_adr-4
    iowrite32(final_phy_adr-4,g_mkg_core_base+0x4);
    printk("read address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("read address : 0x%x \n",read);
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    read=ioread32(g_mkg_core_base+0x18);
    printk("read command : 0x%x \n",read);
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value);
 	printk(" read forth number	: 0x98000040\n");
// read forth number	: 0x98000040
    iowrite32(0x98000040,g_mkg_core_base+0x4);
    printk("read address done !\n");
    read=ioread32(g_mkg_core_base+0x4);
    printk("read address : 0x%x \n",read);
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    read=ioread32(g_mkg_core_base+0x18);
    printk("read command : 0x%x \n",read);
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value);
   
  /*
    iowrite32(0x40000098,g_mkg_core_base+0x4);
    printk("write address done !\n");
    iowrite32(0x1234abcd,g_mkg_core_base+0x8);
    printk("write value done !\n");
    iowrite32(0x01000000,g_mkg_core_base+0x18);
    printk("write command done !\n");
    iowrite32(0x40000098,g_mkg_core_base+0x4);
    printk("read address done !\n");
    iowrite32(0x02000000,g_mkg_core_base+0x18);
    printk("read commnad done !\n");
    write_done=ioread32(g_mkg_core_base+0x0c);
    read_done=ioread32(g_mkg_core_base+0x10);
    read_value=ioread32(g_mkg_core_base+0x14);
    printk("<write_done flag: 0x%x   >\n",write_done);
    printk("<read_done  flag: 0x%x   >\n",read_done);
    printk("<read_value flag: 0x%x   >\n",read_value);
*/
   //printk("<----write control data: 0x01000000 end value:0x%x ---->\n",ioread32(g_mkg_core_base+4));
  // iowrite32(0x03000000,g_mkg_core_base+0x8);
  // printk("<----write control data: 0x03000000 end value:0x%x---->\n",ioread32(g_mkg_core_base+8));
   //  mdelay(100);
   //  mdelay(100);
   //  mdelay(100);
   //  mdelay(100);
   //   printk("<----delay ends ---->\n"); 
   // temp=ioread32(g_mkg_core_base);
   // printk("<-------my core status:0x%x--->\n",temp);
   /*
  while(1)
  {
  	temp=ioread32(g_mkg_mem_base+0x804);
  	if(temp==0x10101010)
  		break;
        printk("<-------my core status:0x%x--->\n",temp);
  	mdelay(1);	
  } 
      printk("<----waiting ends ---->\n");
  
   mdelay(100);   
   printk("<----delay ends ---->\n"); 

  for(loop3=0;loop3<256;loop3++)
  {
  	read_rslt[loop3]=ioread32(g_mkg_mem_base+0x00000400+(loop3*4));
  }

     printk("<----read rslt from ram ---->\n");
      temp=ioread32(g_mkg_mem_base+0x00000800);
    printk("<-------my clock cnt:0x%x--->\n",temp);
    for(loop4=0;loop4<256;loop4++)
  {
  	  printk("====mem read addr==0x%x==mem value:0x%x==\n",loop4,read_rslt[loop4]);
  }

    */


  

  
	/*
         for(loop2=0;loop2<256;loop2++)
    {
         temp=ioread32(temp_addr);
        printk("====mem read addr==0x%x==mem value:0x%x==\n",temp_addr,temp);
		temp_addr=temp_addr+4;
    
    }
	 udelay(1000);
    printk("<----ip_mkg read initial value ends---->\n");
	
    temp_addr=g_mkg_mem_base;
    for(loop=0;loop<256;loop++)
    {
    	
    	iowrite32(loop,temp_addr);
    	printk("====mem write addr==0x%x==mem value:0x%x==\n",temp_addr,loop);
		temp_addr=temp_addr+4;
    }
        udelay(1000);
	printk("<----ip_mkg write end---->\n\n\n");
	temp_addr=g_mkg_mem_base;
	
      for(loop1=0;loop1<256;loop1++)
    {
      temp=ioread32(temp_addr);
        printk("====mem read addr==0x%x==mem value:0x%x==\n",temp_addr,temp);
		temp_addr=temp_addr+4;
    
    }
    printk("<----ip_mkg test end---->\n");
    #endif
    
	int loop = 0;
	unsigned int phy_addr1 = 0;
	unsigned int phy_addr2 = 0;
	int * virtual_addr1 = NULL;
	int * virtual_addr2 = NULL;



	printk("<----ip_mkg test start---->\n");

	//=====ip_mkg reg test========================================================
	#if 1
	printk("reg test start==\n");
	iowrite32(0x11223344,g_mkg_mem_base);

	iowrite32(0x00000097,g_mkg_mem_base+0x10);
	iowrite32(0x03000000,g_mkg_mem_base+4);

	printk("reg test start1==\n");
	printk("reg test start2==\n");
	printk("reg test start3==\n");

	for(loop=0;loop<7;loop++)
	printk("====reg addr==0x%x==reg value:0x%x==\n",loop*4,ioread32(g_mkg_mem_base+4*loop));
	#endif
	//=========================================================================

	//============mem write test
	#if 0
	printk("mem write test start==\n");
	iowrite32(0x97000004,g_mkg_mem_base);
	
	iowrite32(0x2,g_mkg_mem_base+0xc);
	printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc));
	printk("======reg:14 value:0x%x==\n",ioread32(g_mkg_mem_base+0x14));
	printk("======reg:18 value:0x%x==\n",ioread32(g_mkg_mem_base+0x18));
	printk("======reg:1c value:0x%x==\n",ioread32(g_mkg_mem_base+0x1c));
	printk("======reg:20 value:0x%x==\n",ioread32(g_mkg_mem_base+0x20));
	printk("======reg:24 value:0x%x==\n",ioread32(g_mkg_mem_base+0x24));
	
	for(loop = 0;loop<10;loop++)
	printk("wait=write=\n");
	printk("wait=write=\n");
	iowrite32(0x1,g_mkg_mem_base+0xc);
	printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc));
	for(loop = 0;loop<10;loop++)
	printk("wait=read=\n");
	printk("wait=read=\n");
	
	printk("======reg:10 value:0x%x==\n",ioread32(g_mkg_mem_base+0x10));

	printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc));
	#endif

	//============mem read test
	#if 0
	printk("mem read test start==\n");
	virtual_addr1 = (int *)kmalloc(sizeof(int), GFP_KERNEL);
	virtual_addr2 = (int *)kmalloc(sizeof(int), GFP_KERNEL);
	*virtual_addr1 = 0x55;
	*virtual_addr2 = 0x66;
	
	phy_addr1 = virt_to_phys(virtual_addr1);
	phy_addr2 = virt_to_phys(virtual_addr2);

	
	printk("virtual addr1:0x%x==phy addr1:0x%x==\n",(int)virtual_addr1,phy_addr1);
	printk("virtual addr2:0x%x==phy addr2:0x%x==\n",(int)virtual_addr2,phy_addr2);



	iowrite32(phy_addr1,g_mkg_mem_base);
	iowrite32(0x1,g_mkg_mem_base+0xc);
	printk("wait=read=\n");
	printk("======reg:0 value:0x%x==\n",ioread32(g_mkg_mem_base));
	printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc));
	printk("====phy addr1==0x%x==ram value:0x%x==\n",phy_addr1,ioread32(g_mkg_mem_base+0x10));
	printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc));



	iowrite32(phy_addr2,g_mkg_mem_base);
	iowrite32(0x1,g_mkg_mem_base+0xc);
	printk("wait=2=\n");
	printk("======reg:0 value:0x%x==\n",ioread32(g_mkg_mem_base));
	printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc));
	printk("====phy addr2==0x%x==ram value:0x%x==\n",phy_addr2,ioread32(g_mkg_mem_base+0x10));
	printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc));


	
	kfree(virtual_addr1);
	kfree(virtual_addr2);
	#endif
	printk("<----ip_mkg test end---->\n");  */

}






int init_module()
{
	int ret_val;
	int ret;
	int ret2;
	void __iomem *ret_from_request;
	void __iomem *ret_from_request2;


	//=== Allocate character device 
	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &our_file_ops);
	if (ret_val < 0)
	{
		printk(KERN_ALERT " device %s failed(%d)\n", DEVICE_NAME, ret_val);
		return ret_val;
	}

	ret = check_mem_region(MKG_MEM_BASE, MKG_MEM_LEN);
	if (ret < 0) 
	{
		printk(KERN_ERR "mkg check_mem_region bussy error!\n");
		return -1;
	}

	ret_from_request = request_mem_region(MKG_MEM_BASE, MKG_MEM_LEN, "ip_mkg");
	
	ret2 = check_mem_region(MKG_CORE_BASE, MKG_CORE_LEN);
	if (ret2 < 0) 
	{
		printk(KERN_ERR "mkg check_mem_region bussy error!\n");
		return -1;
	}

	ret_from_request2 = request_mem_region(MKG_CORE_BASE, MKG_CORE_LEN, "ip_mkg");

	//===ioremap mkg registers

	g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
	if(NULL == g_mkg_mem_base)
	{
		printk(KERN_ERR "mkg mem ioremap error!\n");
		return -1;
	}
	else
	{
		;//printk("mkg ioremap addr:%d!\n",(unsigned int)g_mkg_mem_base);
	}
	
	g_mkg_core_base = ioremap(MKG_CORE_BASE,MKG_CORE_LEN);
	if(NULL == g_mkg_core_base)
	{
		printk(KERN_ERR "mkg core ioremap error!\n");
		return -1;
	}
	else
	{
		;//printk("mkg ioremap addr:%d!\n",(unsigned int)g_mkg_mem_base);
	}

	
  
	printk("mkg module init done!\n");


//	test();

	return 0;
}

void cleanup_module()
{
	release_mem_region(MKG_MEM_BASE, MKG_MEM_LEN);
  release_mem_region(MKG_CORE_BASE,MKG_CORE_LEN);
	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rill zhen:rill_zhen@126.com");





ip_mkg.h:


#ifndef __IP_MKG_H__
#define __IP_MKG_H__

#define MAJOR_NUM	102
#define DEVICE_NAME	"ip_mkg"
#define MKG_MEM_BASE 0x98000000
#define MKG_MEM_LEN	1024
#define MKG_CORE_BASE 0x97000000
#define MKG_CORE_LEN 1024
#define IOCTL_REG_SET 0
#define IOCTL_REG_GET 1



struct reg_data 
{
	unsigned short addr;
	int value;
};

#endif



makefile:


# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifeq ($(KERNELRELEASE),)

    # Assume the source tree is where the running kernel was built
    # You should set KERNELDIR in the environment if it's elsewhere
    KERNELDIR ?= /home/openrisc/soc-design/linux
    # The current directory is passed to sub-makes as argument
    PWD := $(shell pwd)

modules:
	make -C $(KERNELDIR) M=$(PWD) modules ARCH=openrisc CROSS_COMPILE=or32-linux-

modules_install:
	make -C $(KERNELDIR) M=$(PWD) modules_install ARCH=openrisc CROSS_COMPILE=or32-linux-

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers

.PHONY: modules modules_install clean

else
    # called from kernel build system: just declare what our modules are
    obj-m := ip_mkg.o
endif


2》用户层代码

main.c:


#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
int main()
{
  int mkg_fd=0;
  mkg_fd=open("/dev/ip_mkg",O_RDWR);
  char * mkg_p=0;
  if(!mkg_fd)
  {
    printf("Error: cant open ip_mkg device.\n");
   exit(1);
    }
  printf("The ip_mkg device is open now .\n");
  mkg_p=(char *)mmap(0,sizeof(int)*256,PROT_READ | PROT_WRITE,MAP_SHARED,mkg_fd,0);
  if((int)mkg_p ==-1)
  {
    printf("Error: fail to map device to memory .\n");
    exit(4);
   }
    printf("Map succuss!\n");
    printf("mkg_p is 0x%x \n",mkg_p);
    *((unsigned int *)(mkg_p+0x4))=0x98000040;
    printf("write address! 0x%x !\n",*((unsigned int *)(mkg_p+0x4)));
    *((unsigned int *)(mkg_p+0x8))=0x6789bcdf;
    printf("write value ! 0x%x  !\n",*((unsigned int *)(mkg_p+0x8)));
    *((unsigned int *)(mkg_p+0x18))=0x00000001;
    printf("write command ! 0x%x ~\n",*((unsigned int *)(mkg_p+0x18)));
    
    *((unsigned int *)(mkg_p+0x4))=0x98000040;
    printf("read address! 0x%x !\n",*((unsigned int *)(mkg_p+0x4)));
    *((unsigned int * )(mkg_p+0x18))=0x00000002;
    printf("read command ! 0x%x ~\n",*((unsigned int *)(mkg_p+0x18)));
    printf(" read done flag ! 0x%x \n",*((unsigned int *)(mkg_p+0x10)));
    printf(" read value ! 0x%x  \n", *((unsigned int *)(mkg_p+0x14)));
    printf("write done flag ! 0x%x \n",*((unsigned int *)(mkg_p+0xc)));

   
   munmap(mkg_p,sizeof(int)*256);
   close(mkg_fd);
   return 0;
}



3,硬件部分

硬件部分和之前的内容差异不大,详细信息请参考之前的内容,为了保持小节的独立性,这里直接贴出完整rtl:mycore.v,mymaster.v,myslave.v,myram.v:


mycore.v:


/*
* rill create 2013-06-25
* rillzhen@gmail.com
*/


module mycore
(   
	//===slave interface signals
	wb_clk,			
	wb_rst,		

	wbs_d_mycore_dat_o,
	wbs_d_mycore_ack_o,
	wbs_d_mycore_err_o,
	wbs_d_mycore_rty_o,

	wbs_d_mycore_adr_i,
	wbs_d_mycore_dat_i,
	wbs_d_mycore_sel_i,
	wbs_d_mycore_we_i,
	wbs_d_mycore_cyc_i,
	wbs_d_mycore_stb_i,
	wbs_d_mycore_cti_i,
	wbs_d_mycore_bte_i,	

	
	
	
	//===master interface signals

	wbm_d_mycore_dat_i,
	wbm_d_mycore_ack_i,
	wbm_d_mycore_err_i,
	wbm_d_mycore_rty_i,

	wbm_d_mycore_adr_o,
	wbm_d_mycore_dat_o,
	wbm_d_mycore_sel_o,
	wbm_d_mycore_we_o,
	wbm_d_mycore_cyc_o,
	wbm_d_mycore_stb_o,
	wbm_d_mycore_cti_o,
	wbm_d_mycore_bte_o
);
	input 				 wb_clk;
	input				   wb_rst;
	output	[31:0]	wbs_d_mycore_dat_o;
	output				wbs_d_mycore_ack_o;
	output				wbs_d_mycore_err_o;
	output				wbs_d_mycore_rty_o;

	input	[31:0]	wbs_d_mycore_adr_i;
	input	[31:0]	wbs_d_mycore_dat_i;
	input	[3:0]		wbs_d_mycore_sel_i;
	input				wbs_d_mycore_we_i;
	input				wbs_d_mycore_cyc_i;
	input				wbs_d_mycore_stb_i;
	input	[2:0]		wbs_d_mycore_cti_i;
	input	[1:0]		wbs_d_mycore_bte_i;
	
	input	[31:0]	wbm_d_mycore_dat_i;
	input				wbm_d_mycore_ack_i;
	input				wbm_d_mycore_err_i;
	input				wbm_d_mycore_rty_i;

	output	[31:0]	wbm_d_mycore_adr_o;
	output	[31:0]	wbm_d_mycore_dat_o;
	output	[3:0]		wbm_d_mycore_sel_o;
	output				wbm_d_mycore_we_o;
	output				wbm_d_mycore_cyc_o;
	output				wbm_d_mycore_stb_o;
	output	[2:0]		wbm_d_mycore_cti_o;
	output	[1:0]		wbm_d_mycore_bte_o;
	
	wire 		[31:0]	address;
	wire		[31:0]	value;
	wire					write;
	wire					read;
	wire					read_ack;
	wire					write_ack;
	wire		[31:0]	value_ack;
	myslave myslave0
	(
	.wb_clk(wb_clk),
	.wb_rst(wb_rst),
	.wb_adr_i(wbs_d_mycore_adr_i),
	.wb_dat_i(wbs_d_mycore_dat_i),
	.wb_sel_i(wbs_d_mycore_sel_i),
	.wb_we_i(wbs_d_mycore_we_i),
	.wb_cyc_i(wbs_d_mycore_cyc_i),
	.wb_stb_i(wbs_d_mycore_stb_i),
	.wb_cti_i(wbs_d_mycore_cti_i),
	.wb_bte_i(wbs_d_mycore_bte_i),
   
	.wb_dat_o(wbs_d_mycore_dat_o),   
	.wb_ack_o(wbs_d_mycore_ack_o),
	.wb_err_o(wbs_d_mycore_err_o),
	.wb_rty_o(wbs_d_mycore_rty_o),
	.address_o(address),
	.value_o(value),
	.write_o(write),
	.read_o(read),
	.write_ack(write_ack),
	.read_ack(read_ack),
	.value_ack(value_ack)
	); 
	mymaster mymaster0
	(
	.wb_clk (wb_clk),			
	.wb_rst (wb_rst),

	.wb_adr_o (wbm_d_mycore_adr_o),
	.wb_dat_o (wbm_d_mycore_dat_o),
	.wb_sel_o (wbm_d_mycore_sel_o),
	.wb_we_o (wbm_d_mycore_we_o),
	.wb_cyc_o (wbm_d_mycore_cyc_o),
	.wb_stb_o (wbm_d_mycore_stb_o),
	.wb_cti_o (wbm_d_mycore_cti_o),
	.wb_bte_o (wbm_d_mycore_bte_o),
  
	.wb_dat_i (wbm_d_mycore_dat_i),
	.wb_ack_i (wbm_d_mycore_ack_i),
	.wb_err_i (wbm_d_mycore_err_i),
	.wb_rty_i (wbm_d_mycore_rty_i),
	
//internal signals
	.write_i (write),
	.read_i (read),
	.address_i (address),
	.value_i (value),
	.write_ack (write_ack),
	.read_ack (read_ack),
	.value_o (value_ack)
	);
endmodule


/************** EOF ****************/



mymaster:


module mymaster
(   
	wb_clk,			
	wb_rst,		

	wb_adr_o,
	wb_dat_o,
	wb_sel_o,
	wb_we_o,
	wb_cyc_o,
	wb_stb_o,
	wb_cti_o,
	wb_bte_o,
  
	wb_dat_i,
	wb_ack_i,
	wb_err_i,
	wb_rty_i,
	
	
	write_i ,
	read_i ,
	address_i,
	value_i ,
	write_ack ,
	read_ack,
	value_o 
	
);

//wishbone interface
input							wb_clk;			
input							wb_rst;

input							wb_ack_i; 
input							wb_err_i; 
input							wb_rty_i;
input	[31:0]				wb_dat_i;

output	reg [31:0]		wb_adr_o;
output	reg [31:0]		wb_dat_o;
output	reg 				wb_cyc_o; 
output	reg				wb_stb_o;
output	reg [3:0]		wb_sel_o;
output	reg 				wb_we_o;
output	reg [2:0]		wb_cti_o;
output	reg [1:0]		wb_bte_o;
input							write_i;
input							read_i;
input		 [31:0]		address_i;
input		 [31:0]		value_i;
output	reg [31:0]	value_o;
output 	reg 			write_ack;
output	reg 			read_ack;

parameter	m_idle			=	9'b000000001;
parameter   m_write_ready	=  9'b010000000;
parameter	m_read_ready	=	9'b100000000;
parameter	m_write_begin	=	9'b000000010;
parameter	m_write_wait	=	9'b000000100;
parameter	m_write_done	=	9'b000001000;
parameter	m_read_begin	=	9'b000010000;
parameter	m_read_wait		=	9'b000100000;
parameter 	m_read_done		=	9'b001000000;
parameter cti_default	= 3'b000;
parameter bte_default	= 2'b00;
parameter sel_default	= 4'b1111;
		
reg [8:0] 	state,next_state;

always @(posedge wb_clk)
	if(wb_rst)
		state<=m_idle;
	else
		state<=next_state;

always @(*)
	case(state)
		m_idle:
			begin
				if(write_i)
					next_state=m_write_ready;
				else if(read_i)
					next_state=m_read_ready;
				else 
					next_state=m_idle;
			end
		m_write_ready:
			begin
			next_state=m_write_begin;
			end
		m_read_ready:
			begin
			next_state=m_read_begin;
			end
		m_write_begin:
			begin
				next_state=m_write_wait;
			end
		m_write_wait:
			begin
				if(wb_ack_i)
				next_state=m_write_done;
				else
				next_state=m_write_wait;
			end
		m_write_done:
			begin
			next_state=m_idle;
			end
		m_read_begin:
			begin
			next_state=m_read_wait;
			end
		m_read_wait:
			begin
			if(wb_ack_i)
				next_state=m_read_done;
			else
				next_state=m_read_wait;
			end
		m_read_done:
			begin
				next_state=m_idle;
			end
		default:
			begin
				next_state=m_idle;
			end
	endcase

always @ (posedge wb_clk)
if(wb_rst)
	begin
	wb_adr_o<=0;
	wb_dat_o<=0;
	wb_sel_o<=sel_default;
	wb_we_o<=0;
	wb_cyc_o<=0;
	wb_stb_o<=0;
	wb_cti_o<=cti_default;
	wb_bte_o<=bte_default;
	write_ack<=0;
	read_ack<=0;
	value_o <=0;
	end
else
	begin
		case(next_state)
			m_idle:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_sel_o<=sel_default;
				wb_we_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_cti_o<=cti_default;
				wb_bte_o<=bte_default;
				write_ack<=0;
				read_ack<=0;
				value_o <=0;
				end
			m_write_ready:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_we_o<=0;
				end
			m_read_ready:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_we_o<=0;
				 end
			m_write_begin:
				begin
				wb_adr_o<=address_i;
				wb_dat_o<=value_i;
				wb_cyc_o<=1'b1;
				wb_stb_o<=1'b1;
				wb_we_o<=1'b1;
				end
			m_write_wait:
				begin
				wb_adr_o<=wb_adr_o;
				wb_dat_o<=wb_dat_o;
				wb_cyc_o<=wb_cyc_o;
				wb_stb_o<=wb_stb_o;
				wb_we_o<=wb_we_o;
				end
			m_write_done:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_we_o<=0;
				write_ack<=1'b1;
				end
			m_read_begin:
				begin
				wb_adr_o<=address_i;
				wb_dat_o<=0;
				wb_cyc_o<=1'b1;
				wb_stb_o<=1'b1;
				wb_we_o<=0;
				end
			m_read_wait:
				begin
				wb_adr_o<=wb_adr_o;
				wb_dat_o<=wb_dat_o;
				wb_cyc_o<=wb_cyc_o;
				wb_stb_o<=wb_stb_o;
				wb_we_o <=0;
				end
			m_read_done:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_we_o<=0;
				read_ack<=1'b1;
				value_o<=wb_dat_i;
				end
			default:
				begin
				wb_adr_o<=0;
				wb_dat_o<=0;
				wb_sel_o<=sel_default;
				wb_we_o<=0;
				wb_cyc_o<=0;
				wb_stb_o<=0;
				wb_cti_o<=cti_default;
				wb_bte_o<=bte_default;
				write_ack<=0;
				read_ack<=0;
				value_o <=0;
				end
			endcase
	end
endmodule
				



myslave.v:


module myslave
(   
	wb_clk,			
	wb_rst,		
		
	wb_dat_i,			
	wb_adr_i,			
	wb_sel_i,		
	wb_cti_i,	
	wb_bte_i,		
	wb_we_i,		
	wb_cyc_i,		
	wb_stb_i,	
		
	wb_dat_o,		
	wb_ack_o,		
	wb_err_o,                 
	wb_rty_o,
	
	address_o,
	value_o,
	write_o,
	read_o,
	write_ack,
	read_ack,
	value_ack
);

input 			      		    wb_clk;
input 			          		 wb_rst;

input [31:0]      				 wb_adr_i;
input 			    			    wb_stb_i;
input 			    			    wb_cyc_i;
input [2:0] 				       wb_cti_i;
input [1:0] 				       wb_bte_i;
input [31:0] 					    wb_dat_i;
input [3:0] 					    wb_sel_i;
input 								 wb_we_i;
	
output reg [31:0] 		 	    wb_dat_o;
output reg 			      	 	 wb_ack_o;
output 		               	 wb_err_o;
output  					 	       wb_rty_o;

output reg [31:0]					 address_o;
output reg [31:0]					 value_o;
output reg 							 write_o;
output reg							 read_o;
input									 write_ack;
input									 read_ack;
input  		[31:0]				 value_ack;

parameter	address_adr		=8'h04;
parameter   value_adr		=8'h08;
parameter   wr_adr			=8'h18;
parameter   write_done_adr =8'h0c;
parameter   read_done_adr	=8'h10;
parameter   value_ack_adr	=8'h14;
parameter   err_code			=32'habcd_1234;
parameter   default_code   =32'h4875_efad;

parameter   read_command	=32'h0000_0002;
parameter	write_command	=32'h0000_0001;

parameter 	s_idle			=9'b000000001;
parameter   s_write_done	=9'b000000010;
parameter   s_read_done 	=9'b000000100;
parameter 	s_read			=9'b000001000;
parameter	s_write			=9'b000010000;
parameter	s_read_pause	=9'b000100000;
parameter	s_write_pause1 =9'b001000000;
parameter   s_write_pause2	=9'b010000000;
parameter 	s_write_pause3	=9'b100000000;

reg [8:0]	state,next_state;
reg [31:0]	value_reg;
reg 			write_done;
reg			read_done;
reg [31:0]	address_reg;
reg [31:0]	value_i_reg;
reg [31:0]	wr_reg;
reg [31:0]  write_ack_done;
always @(posedge wb_clk)
if(wb_rst)
write_ack_done<=0;
else if(write_ack)
write_ack_done<=32'h1;
else if(write_o)
write_ack_done<=0;

assign wb_err_o=0;
assign wb_rty_o=0;

always @(posedge wb_clk)
	if(wb_rst)
		state<=s_idle;
	else
		state<=next_state;
		
always @(*)
	begin
	case(state)
		s_idle:
			begin
				if(write_ack)
					next_state=s_write_done;
				else if(read_ack)
					next_state=s_read_done;
				else if(wb_stb_i && wb_cyc_i && wb_we_i)
					next_state=s_write;
				else if(wb_stb_i && wb_cyc_i && !wb_we_i)
					next_state=s_read;
				else
					next_state=s_idle;
			end
		s_write_done:
			begin
				next_state=s_idle;
			end
		s_read_done:
			begin
				next_state=s_idle;
			end
		s_write:
			begin
				next_state=s_write_pause1;
			end
		s_write_pause1:
			begin
				next_state=s_write_pause2;
			end
		s_read:
			begin
				next_state=s_read_pause;
			end
		s_read_pause:
			begin
				next_state=s_idle;
			end
		s_write_pause2:
			begin
				next_state=s_write_pause3;
			end
		s_write_pause3:
			begin
				next_state=s_idle;
			end
		default:
			begin
				next_state=s_idle;
			end
	endcase
 end

 always @(posedge wb_clk)
 if(wb_rst)
	begin
		address_o<=0;
		value_o	<=0;
		write_o	<=0;
		read_o	<=0;
		
		value_reg<=0;
		read_done<=0;
		write_done<=0;
		address_reg<=0;
		value_i_reg<=0;
		wr_reg	<=0;
		
		//wb_dat_o<=0;
	//	wb_dat_o<=err_code;
	   wb_dat_o<=default_code;
		wb_ack_o<=0;
	end
else
	begin
	case(next_state)
		s_idle:
			begin
				address_o<=0;
				value_o	<=0;
				write_o	<=0;
				read_o	<=0;
		
			//	wb_dat_o<=0;
			 //  wb_dat_o<=err_code;
			   wb_dat_o<=default_code;
				wb_ack_o<=0;
			 end
		s_read_done:
			begin
				address_o<=0;
				value_o	<=0;
				write_o	<=0;
				read_o	<=0;
		
				//wb_dat_o<=0;
				//wb_dat_o<=err_code;
				wb_dat_o<=default_code;
				wb_ack_o<=0;  
				
				read_done<=1'b1;
				value_reg<=value_ack;
				
			end
		s_write_done:
			begin
				address_o<=0;
				value_o	<=0;
				write_o	<=0;
				read_o	<=0;
		
			//	wb_dat_o<=0;
			 //  wb_dat_o<=err_code;
			   wb_dat_o<=default_code;
				wb_ack_o<=0;  
				
				write_done<=1'b1;	

			end
		s_read:
			begin
				if(wb_adr_i[7:0] == value_ack_adr)
			//		wb_dat_o<={value_reg[7:0],value_reg[15:8],value_reg[23:16],value_reg[31:24]};
				   wb_dat_o<=value_reg;
				// wb_dat_o<={value_reg[7:0],value_reg[15:8],value_reg[23:16],wb_adr_i[7:0]};
				else if(wb_adr_i[7:0] == write_done_adr)
				//	wb_dat_o<={write_done,23'b0,wb_adr_i[7:0]};
				 wb_dat_o<=write_ack_done;
			//	wb_dat_o<={write_done,23'b0,wb_adr_i[7:0]};
				else if(wb_adr_i[7:0] == read_done_adr)
					wb_dat_o<={read_done,31'b0};
			//	wb_dat_o<={read_done,23'b0,wb_adr_i[7:0]};
				else if(wb_adr_i[7:0] == address_adr)
			//	wb_dat_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
			    wb_dat_o<=address_reg;
				//wb_dat_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],wb_adr_i[7:0]};
				else if(wb_adr_i[7:0] == wr_adr)
					wb_dat_o<=wr_reg;
			//	wb_dat_o<={wr_reg[23:0],wb_adr_i[7:0]};
				else if(wb_adr_i[7:0] == value_adr)
					wb_dat_o<=value_i_reg;
				//wb_dat_o<={value_i_reg[31:8],wb_adr_i[7:0]};
				else
				//	wb_dat_o<=wb_adr_i;
				 wb_dat_o<=err_code;
					wb_ack_o<=0;
					
					address_o<=0;
					value_o	<=0;
					write_o	<=0;
					read_o	<=0;
			end
		s_read_pause:
			begin
				//	wb_dat_o<=wb_dat_o;
				wb_dat_o<=wb_dat_o;
					wb_ack_o<=1'b1;
					
					address_o<=0;
					value_o	<=0;
					write_o	<=0;
					read_o	<=0;		
			end
		s_write:
			begin
				if(wb_adr_i[7:0]== address_adr)
			//		address_reg<={wb_dat_i[7:0],wb_dat_i[15:8],wb_dat_i[23:16],wb_dat_i[31:24]};
				   address_reg<=wb_dat_i;
				else if(wb_adr_i[7:0] == value_adr)
					value_i_reg<=wb_dat_i;
				else if(wb_adr_i[7:0] == wr_adr) 
					wr_reg	<= wb_dat_i;
					
					wb_ack_o <=0;
			//		wb_dat_o	<=0;
					wb_dat_o<=err_code;
					address_o<=0;
					value_o	<=0;
					write_o	<=0;
					read_o	<=0;		
			end
		s_write_pause1:
			begin
				if(wr_reg == read_command)
					begin
						read_o<=1'b1;
						address_o<=address_reg;
//						wb_ack_o<=1'b1;
//						wb_dat_o<=0;
//						address_reg<=0;
//						wr_reg<=0;
//						value_reg<=0;
//						read_done<=0;
					end
				else if(wr_reg == write_command)
					begin
						write_o<=1'b1;
//						address_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
						address_o<=address_reg;
						value_o<=value_i_reg;
//						wb_ack_o<=1'b1;
//						wb_dat_o<=0;
//						value_i_reg<=0;
//						address_reg<=0;
//						wr_reg	<=0;
//						write_done<=0;
					end
				else
					begin
						write_o<=0;
						read_o<=0;
					//	wb_ack_o<=1'b1;
					//	wb_dat_o<=0;
						address_o<=0;
						value_o<=0;
					end
				end
			s_write_pause2:
			begin
				if(wr_reg == read_command)
					begin
						read_o<=1'b1;
						address_o<=address_reg;
//						wb_ack_o<=1'b1;
//						wb_dat_o<=0;
//						address_reg<=0;
//						wr_reg<=0;
//						value_reg<=0;
//						read_done<=0;
					end
				else if(wr_reg == write_command)
					begin
						write_o<=1'b1;
					//	address_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
						address_o<=address_reg;
						value_o<=value_i_reg;
//						wb_ack_o<=1'b1;
//						wb_dat_o<=0;
//						value_i_reg<=0;
//						address_reg<=0;
//						wr_reg	<=0;
//						write_done<=0;
					end
				else
					begin
						write_o<=0;
						read_o<=0;
					//	wb_ack_o<=1'b1;
					//	wb_dat_o<=0;
						address_o<=0;
						value_o<=0;
					end
				end	
		s_write_pause3:
				begin
				  if(wr_reg == read_command)
				  begin
						read_o<=0;
						address_o<=0;
						
						
					
						wb_ack_o<=1'b1;
					//	wb_dat_o<=0;
					   wb_dat_o<=err_code;
						address_reg<=0;
						wr_reg<=0;
						value_reg<=0;
						read_done<=0;
				  end
				  else if(wr_reg  == write_command)
				  begin
						write_o<=0;
						address_o<=0;
						value_o<=0;
						
					
						wb_ack_o<=1'b1;
					//	wb_dat_o<=0;
						wb_dat_o<=err_code;
						address_reg<=0;
						wr_reg<=0;
						value_i_reg<=0;
					//	write_done<=0;
					end	
					else
					begin
						write_o<=0;
						read_o<=0;
						
						wb_ack_o<=1'b1;
					//	wb_dat_o<=0;
						wb_dat_o<=err_code;
						address_o<=0;
						value_o<=0;
					end

				end
		
		default:
			begin
				address_o<=0;
				value_o	<=0;
				write_o	<=0;
				read_o	<=0;
		
				value_reg<=0;
				read_done<=0;
				write_done<=0;
				address_reg<=0;
				value_i_reg<=0;
				wr_reg	<=0;
			    wb_dat_o<=default_code;
			//	wb_dat_o<=0;
				wb_ack_o<=0;			
			end
		endcase
	end
endmodule
				
				   
	 
	



myram.v:


module myram
  (
	wb_clk,			
	wb_rst,		
		
	wb_dat_i,			
	wb_adr_i,			
	wb_sel_i,		
	wb_cti_i,	
	wb_bte_i,		
	wb_we_i,		
	wb_cyc_i,		
	wb_stb_i,	
		
	wb_dat_o,		
	wb_ack_o,		
	wb_err_o,                    
	wb_rty_o
	);
input 			      		     wb_clk;
input 			          		 wb_rst;

input [31:0]      				 wb_adr_i;
input 			    			       wb_stb_i;
input 			    			       wb_cyc_i;
input [2:0] 				       wb_cti_i;
input [1:0] 				       wb_bte_i;
input [31:0] 					     wb_dat_i;
input [3:0] 					      wb_sel_i;
input 								       wb_we_i;
	
output reg [31:0] 		 	    wb_dat_o;
output reg 			      	 	   wb_ack_o;
output 		               	 wb_err_o;
output  					 	           wb_rty_o;

parameter   myram_adr       =32'h9800_0040;
parameter   err_code        =32'h1234_3456;

parameter   ram_idle  = 4'b0001;
parameter   ram_read  = 4'b0010;
parameter   ram_write = 4'b0100;

reg [3:0] state, next_state;
reg [31:0] value;

assign wb_err_o = 0 ;
assign wb_rty_o = 0;

always @(posedge wb_clk)
if(wb_rst)
  state <= ram_idle;
else
  state <= next_state;
  
always @(*)
  case(state)
    ram_idle:
      begin
      if(wb_stb_i && wb_cyc_i && wb_we_i && (wb_adr_i == myram_adr))
        next_state = ram_write;
      else if (wb_stb_i && wb_cyc_i && !wb_we_i && (wb_adr_i == myram_adr))
        next_state = ram_read;
      else
        next_state = ram_idle;
      end
    ram_write:
      begin
        next_state = ram_idle;
      end
    ram_read:
      begin
        next_state = ram_idle;
      end
    default:
      begin
        next_state = ram_idle;
     end
  endcase
always @ (posedge wb_clk)
  if(wb_rst)
    begin
     wb_ack_o <=0;
     wb_dat_o <=0;
     value    <=err_code;
    end
  else
    begin
      case(next_state)
        ram_idle:
          begin
          wb_ack_o<=0;
          wb_dat_o<=0;
          end
        ram_write:
          begin
          wb_ack_o<=1'b1;
          wb_dat_o<=0;
          value<=wb_dat_i;
          end
        ram_read:
          begin
          wb_ack_o<=1'b1;
          wb_dat_o<=value;
         end
        default:
          begin
            wb_ack_o <= 0;
            wb_dat_o <= 0;
            value    <= err_code;
         end
     endcase
  end
endmodule
        
        




4,验证

经过上述的分析和实现,在进行综合,烧板,起linux,insmod,mknod,./a.out之后,就可以看到验证结果了,如下图,可以看出,AP层程序可以直接控制ipcore:

注:在AP层编写程序时,不存在大小端转换的问题,所以本小节的所有代码(包括硬件/软件)中,均没有大小端转换的内容,这是与之前内容的最大不同。



5,小结

本小节实现了用户程序直接访问ipcore的地址空间,减少了CPU的数据搬运操作,可有效提供系统的性能。

enjoy!



  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值