OpenRisc-22-添加自己的DMA-like ipcore到ORSoC并测试

引言
之前写了一个wishbone接口的slave,work的很好。
但是要想实现一个功能完成的ipcore,必然要有master接口。
这次就写一个ipcore(mycore),既包含slave,又包含master。
一个具有类似DMA功能的ip core。

 

另:本小节中省略了一些virtualbox下的操作细节,请参考上一篇文章:

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

 

1,控制流程
1>mycore的linux下的driver写slave
2>slave根据driver发来的指令控制master
3>master进行相应操作,并返回给slave
4>mycore的linux下的driver读slave

2,功能概述
2.1 master写功能
 1》driver向slave的num_1寄存器里写入0x11223344
 2》driver向slave的write_address寄存器里写入0x00000097.(这是让master 写的地址,其实就是num_1)
 3》driver向slave的num_2寄存器里写入0x03000000.(这是让master开始写)
 4》打印
 5》driver读slave,验证master写入的值是否正确。

 

2.1.0 模块总连接图

 


2.1.1 代码修改流程说明:跟单独包含slave的ipcore差不多
 1》编写符合wishbone master接口和相应内部逻辑的ip core:mycore
 2》d_bus的arbiter增加master接口:master2
 3》修改master的仲裁优先级
 4》例化本ipcore
 5》编写linux下的driver并测试验证
 
2.1.2 code list:mycore.v,mkg_master.v,mkg_slave.v
 1》mycore.v

 

/*
*
* mycore.v
*
* rill create 2013-04-02
*
*/


`include "orpsoc-defines.v"


module mycore
(   
	//===slave interface signals
	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,
	
	
	
	//===master interface signals

	m_adr,
	m_din,
	m_dout,
	m_cyc,
	m_stb,
	m_sel,
	m_we,
	m_ack,
	m_err,
	m_rty,
	m_cti,
	m_bte
);

//===slave interface
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 			      		    wb_clk;
input 			          		wb_rst;
input [31:0] 					wb_dat_i;
input [3:0] 					wb_sel_i;
input 							wb_we_i;
	
output  [31:0] 		 			wb_dat_o;
output  			      	 	wb_ack_o;
output                			wb_err_o;
output  					 	wb_rty_o;


//===master interface
input				m_ack; 
input				m_err; 
input				m_rty;
input	[31:0]		m_din;

output	[31:0]		m_adr;
output	[31:0]		m_dout;
output				m_cyc; 
output				m_stb;
output	[3:0]		m_sel;
output				m_we;
output	[2:0]		m_cti;
output	[1:0]		m_bte;

wire [31:0] address;
wire [2:0] flag;
wire [2:0] test;
wire [1:0] done;
//===slave external parameters
parameter addr_width = 32;
parameter mycore_adr = 32'h97;


mkg_slave mkg_slave0
(
	.address (address),
	.flag (flag),
	.test_status (test),
	.test_done (done),
	
	.wb_clk (wb_clk),
	.wb_rst (wb_rst),	
		
	.wb_dat_i (wb_dat_i),
	.wb_adr_i (wb_adr_i),
	.wb_sel_i (wb_sel_i),
	.wb_cti_i (wb_cti_i),
	.wb_bte_i (wb_bte_i),
	.wb_we_i (wb_we_i),
	.wb_cyc_i (wb_cyc_i),
	.wb_stb_i (wb_stb_i),
		
	.wb_dat_o (wb_dat_o),
	.wb_ack_o (wb_ack_o),
	.wb_err_o (wb_err_o),
	.wb_rty_o (wb_rty_o)
);


mkg_master mkg_master
(   
	.address (address),
	.flag (flag),
	.test_status (test),
	.test_done (done),
	
	.wb_clk (wb_clk),
	.wb_rst (wb_rst),

	.wb_adr_o (m_adr),
	.wb_dat_o (m_dout),
	.wb_sel_o (m_sel),
	.wb_we_o (m_we),
	.wb_cyc_o (m_cyc),
	.wb_stb_o (m_stb),
	.wb_cti_o (m_cti),
	.wb_bte_o (m_bte),
  
	.wb_dat_i (m_din),
	.wb_ack_i (m_ack),
	.wb_err_i (m_err),
	.wb_rty_i (m_rty)
);

endmodule


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


 

 

 

 


 
 2》mkg_master.v

 

 

/*
*
* mkg_master.v
*
* rill create 2013-04-02
*
*/



module mkg_master
(   
	address,
	flag,
	test_status,
	test_done,
	
	//wishbone interface
	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
);

input [31:0]		address;
input [2:0] 		flag;
output reg [2:0] test_status;
output reg [1:0] test_done;
//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;


//====master status define
parameter m_idle = 3'b000;
parameter m_wait_ack_read = 3'b001;
parameter m_wait_ack_write = 3'b010;

reg [2:0] status = m_idle;


reg [31:0] ram_data;

always @(posedge wb_clk)
begin
	test_status <= status;
end


always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			wb_cyc_o <= 1'b0;
			wb_stb_o <= 1'b0;
			wb_we_o <= 1'b0;
			wb_adr_o <= 32'h0;
			wb_dat_o <= 32'h0;
			test_done <= 2'b00;
			
			status <= m_idle;
		end
	else
		begin
			case (status)
			m_idle:
				begin
					if(3'd1 == flag)//read
						begin
							wb_cyc_o <= 1'b1;
							wb_stb_o <= 1'b1;
							wb_adr_o <= address;
							wb_we_o <= 1'b0;
							
							status <= m_wait_ack_read;
						end
					else if(3'd2 == flag)//write
						begin
							wb_adr_o <= address;
							wb_dat_o <= 32'h4444_4444;
							wb_cyc_o <= 1'b1;
							wb_stb_o <= 1'b1;
							wb_we_o <= 1'b1;
							
							status <= m_wait_ack_write;
						end
					else
						begin
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							status <= m_idle;
						end
				end
				
			m_wait_ack_read:
				begin
					if(1'b1 != wb_ack_i)
						begin
							test_done <= 2'b10;
							status <= m_wait_ack_read;
						end
					else
						begin
							ram_data <= wb_dat_i;
							
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							test_done <= 2'b01;
							status <= m_idle;
						end
				end
				
			m_wait_ack_write:
				begin
					if(1'b1 != wb_ack_i)
						begin
							test_done <= 2'b10;
							status <= m_wait_ack_write;
						end
					else
						begin
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							test_done <= 2'b01;
							status <= m_idle;
						end
				end
			
			default:
				begin
					status <= m_idle;
				end
			
			endcase

		end
end

endmodule


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


 

 


 
 3》mkg_slave.v

 

/*
*
* mkg_slave.v
*
* rill create 2013-04-02
*
*/


`include "orpsoc-defines.v"


module mkg_slave
(   
	address,
	flag,
	test_status,
	test_done,
	//===slave interface signals
	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
	
);

output reg [31:0] address;
output reg [2:0] flag;
input [2:0] test_status;
input [1:0] test_done;
//===slave interface
input [addr_width-1: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 			      		    wb_clk;
input 			          		wb_rst;
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;




//===slave external parameters
parameter addr_width = 32;
parameter mycore_adr = 8'h97;

	

//===slave local regs
reg [addr_width-1:0] num_1;//addr index:0x0
reg [addr_width-1:0] num_2;//addr index:0x4
reg [addr_width-1:0] sum;//addr index:0x8
reg [31:0] master_status;//test reg 0xc
reg [31:0] write_address;//0x10

//====slave status define
parameter s_idle = 3'b000;
parameter s_read = 3'b001;
parameter s_write = 3'b010;

reg [2:0] state = s_idle;


reg [1:0] done_flag = 2'b0;


reg [2:0] m_status;
reg [1:0] m_done;
//===mycore process start--->
assign wb_err_o=0;
assign wb_rty_o=0;

//===slave process================

always @(posedge wb_clk)
begin
	m_status <=  test_status;
	m_done <= test_done;
end

always @(posedge wb_clk)
begin
	master_status <= {27'b1001_1010_1011_1100_1101_1110_1111_0000,m_status,m_done};
end


always @(*)
begin
	sum = num_1 + num_2;
end


always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			address <= 32'h0;
			flag <= 3'b0;
			done_flag <= 2'b0;
		end
	else
		begin
			if(2'b10 == done_flag)
				begin
					address <= 32'h0;
					flag <= 3'b0;
				end
			else if(2'b01 == done_flag)
				begin
					address <= write_address;
					flag <= 3'b010;
					done_flag <= 2'b10;
				end
			else
				begin
					if(3 == num_2)
						begin
							address <= write_address;
							flag <= 3'b010;
							done_flag <= 2'b01;
						end
					else
						begin
							address <= 32'h0;
							flag <= 3'b0;
							done_flag <= 2'b00;
						end
					
				end
		end
end

always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			state <= s_idle;
		end
	else
		begin
			case(state)
			s_idle:
				begin
					wb_dat_o <= 1'b0;
					wb_ack_o <= 1'b0;
			
					if(wb_stb_i && wb_cyc_i && wb_we_i)
						begin
							state <= s_write;
						end
					else if(wb_stb_i && wb_cyc_i && !wb_we_i)
						begin
							state <= s_read;
						end
					else
						begin
							state <= s_idle;
						end
				end
	
			s_write:
				begin
					if(wb_adr_i == {mycore_adr,24'h000000})
						begin
							num_1 <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i == {mycore_adr,24'h000004})
						begin
							num_2 <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i == {mycore_adr,24'h000010})
						begin
							write_address <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else 
						begin
							//wb_ack_o=1'b0;
						end
				
					state <= s_idle;
				end
  
			s_read:
				begin
					if(wb_adr_i=={mycore_adr,24'h000000})
						begin
							wb_dat_o <= num_1;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000004})
						begin
							wb_dat_o <= num_2;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000008})
						begin
							wb_dat_o <= sum;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h00000c})
						begin
							wb_dat_o <= master_status;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000010})
						begin
							wb_dat_o <= write_address;
							wb_ack_o <= 1'b1;
						end
					else 
						begin
							wb_dat_o = 0;
							wb_ack_o <= 1'b1;
						end
				
					state <= s_idle;

				end
		
		
			default:
				begin
					state <= s_idle;
				end
		
			endcase
		end
end

endmodule


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


 

 


 
 4》d_bus 优先级代码

 


 
 5》linux driver

ip_mkg.c:

 

/*
*
* rill mkg driver
*
*/
#include <linux/vmalloc.h>
#include <linux/slab.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 <asm-generic/io.h>

#include "ip_mkg.h"



void	__iomem 	*g_mkg_mem_base = NULL;

static int device_open(struct inode *inode, struct file *file)
{
	g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
	if(NULL == g_mkg_mem_base)
	{
		printk(KERN_ERR "mkg open ioremap error!\n");
		return -1;
	}
	else
	{
		printk("mkg ioremap addr:%d!\n",(int)g_mkg_mem_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;
}

struct file_operations our_file_ops = {
  .unlocked_ioctl = device_ioctl,
  .read = device_read,
  .write = device_write,
  .open = device_open,
  .release = device_release,
  .owner = THIS_MODULE,
};



void test(void)
{
	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;
	void __iomem *ret_from_request;


	//=== 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");

	//===ioremap mkg registers

	g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
	if(NULL == g_mkg_mem_base)
	{
		printk(KERN_ERR "mkg 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);

	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 0x97000000
#define MKG_MEM_LEN	32

#define IOCTL_REG_SET 0
#define IOCTL_REG_GET 1



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

#endif


 

 

 


 
 6》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.1.3 模块连接图:

 

 

2.1.4 验证结果:

 


2.2 master读功能
 1》driver向slave的num_1寄存器里写入0x11223344
 2》driver向slave的write_address寄存器里写入0x00000097.(这是让master 读的地址,其实就是num_1)
 3》driver向slave的num_2寄存器里写入0x03000000.(这是让master开始读)
 4》打印
 5》driver读slave,验证master读入的值是否正确。

2.2.1 code list:mycore.v,mkg_master.v,mkg_slave.v
 1》mycore.v

 

/*
*
* mycore.v
*
* rill create 2013-04-02
*
*/


`include "orpsoc-defines.v"


module mycore
(   
	//===slave interface signals
	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,
	
	
	
	//===master interface signals

	m_adr,
	m_din,
	m_dout,
	m_cyc,
	m_stb,
	m_sel,
	m_we,
	m_ack,
	m_err,
	m_rty,
	m_cti,
	m_bte
);

//===slave interface
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 			      		    wb_clk;
input 			          		wb_rst;
input [31:0] 					wb_dat_i;
input [3:0] 					wb_sel_i;
input 							wb_we_i;
	
output  [31:0] 		 			wb_dat_o;
output  			      	 	wb_ack_o;
output                			wb_err_o;
output  					 	wb_rty_o;


//===master interface
input				m_ack; 
input				m_err; 
input				m_rty;
input	[31:0]		m_din;

output	[31:0]		m_adr;
output	[31:0]		m_dout;
output				m_cyc; 
output				m_stb;
output	[3:0]		m_sel;
output				m_we;
output	[2:0]		m_cti;
output	[1:0]		m_bte;

wire [31:0] address;
wire [2:0] flag;
wire [2:0] test;
wire [1:0] done;
wire [31:0] value;
//===slave external parameters
parameter addr_width = 32;
parameter mycore_adr = 32'h97;


mkg_slave mkg_slave0
(
	.address (address),
	.flag (flag),
	.test_status (test),
	.test_done (done),
	.ram_data (value),
	
	.wb_clk (wb_clk),
	.wb_rst (wb_rst),	
		
	.wb_dat_i (wb_dat_i),
	.wb_adr_i (wb_adr_i),
	.wb_sel_i (wb_sel_i),
	.wb_cti_i (wb_cti_i),
	.wb_bte_i (wb_bte_i),
	.wb_we_i (wb_we_i),
	.wb_cyc_i (wb_cyc_i),
	.wb_stb_i (wb_stb_i),
		
	.wb_dat_o (wb_dat_o),
	.wb_ack_o (wb_ack_o),
	.wb_err_o (wb_err_o),
	.wb_rty_o (wb_rty_o)
);


mkg_master mkg_master
(   
	.address (address),
	.flag (flag),
	.test_status (test),
	.test_done (done),
	.ram_data (value),
	
	.wb_clk (wb_clk),
	.wb_rst (wb_rst),

	.wb_adr_o (m_adr),
	.wb_dat_o (m_dout),
	.wb_sel_o (m_sel),
	.wb_we_o (m_we),
	.wb_cyc_o (m_cyc),
	.wb_stb_o (m_stb),
	.wb_cti_o (m_cti),
	.wb_bte_o (m_bte),
  
	.wb_dat_i (m_din),
	.wb_ack_i (m_ack),
	.wb_err_i (m_err),
	.wb_rty_i (m_rty)
);

endmodule


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


 


 
 2》mkg_master.v

 

/*
*
* mkg_master.v
*
* rill create 2013-04-02
*
*/



module mkg_master
(   
	address,
	flag,
	test_status,
	test_done,
	ram_data,
	//wishbone interface
	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
);

input [31:0]		address;
input [2:0] 		flag;
output reg [2:0] test_status;
output reg [1:0] test_done;
output reg [31:0] ram_data;
//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;


//====master status define
parameter m_idle = 3'b000;
parameter m_wait_ack_read = 3'b001;
parameter m_wait_ack_write = 3'b010;

reg [2:0] status = m_idle;




always @(posedge wb_clk)
begin
	test_status <= status;
end


always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			wb_cyc_o <= 1'b0;
			wb_stb_o <= 1'b0;
			wb_we_o <= 1'b0;
			wb_adr_o <= 32'h0;
			wb_dat_o <= 32'h0;
			test_done <= 2'b00;
			
			status <= m_idle;
		end
	else
		begin
			case (status)
			m_idle:
				begin
					if(3'd1 == flag)//read
						begin
							wb_cyc_o <= 1'b1;
							wb_stb_o <= 1'b1;
							wb_adr_o <= address;
							wb_we_o <= 1'b0;
							
							status <= m_wait_ack_read;
						end
					else if(3'd2 == flag)//write
						begin
							wb_adr_o <= address;
							wb_dat_o <= 32'h4444_4444;
							wb_cyc_o <= 1'b1;
							wb_stb_o <= 1'b1;
							wb_we_o <= 1'b1;
							
							status <= m_wait_ack_write;
						end
					else
						begin
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							status <= m_idle;
						end
				end
				
			m_wait_ack_read:
				begin
					if(1'b1 != wb_ack_i)
						begin
							test_done <= 2'b10;
							status <= m_wait_ack_read;
						end
					else
						begin
							ram_data <= wb_dat_i;
							
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							test_done <= 2'b01;
							status <= m_idle;
						end
				end
				
			m_wait_ack_write:
				begin
					if(1'b1 != wb_ack_i)
						begin
							test_done <= 2'b10;
							status <= m_wait_ack_write;
						end
					else
						begin
							wb_cyc_o <= 1'b0;
							wb_stb_o <= 1'b0;
							wb_we_o <= 1'b0;
							wb_adr_o <= 32'h0;
							wb_dat_o <= 32'h0;
							
							test_done <= 2'b01;
							status <= m_idle;
						end
				end
			
			default:
				begin
					status <= m_idle;
				end
			
			endcase

		end
end

endmodule


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


 


 
 3》mkg_slave.v

 

/*
*
* mkg_slave.v
*
* rill create 2013-04-02
*
*/


`include "orpsoc-defines.v"


module mkg_slave
(   
	address,
	flag,
	test_status,
	test_done,
	ram_data,
	//===slave interface signals
	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
	
);

output reg [31:0] address;
output reg [2:0] flag;
input [2:0] test_status;
input [1:0] test_done;
input [31:0] ram_data;
//===slave interface
input [addr_width-1: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 			      		    wb_clk;
input 			          		wb_rst;
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;




//===slave external parameters
parameter addr_width = 32;
parameter mycore_adr = 8'h97;

	

//===slave local regs
reg [addr_width-1:0] num_1;//addr index:0x0
reg [addr_width-1:0] num_2;//addr index:0x4
reg [addr_width-1:0] sum;//addr index:0x8
reg [31:0] master_status;//test reg 0xc
reg [31:0] write_address;//0x10
reg [31:0] read_value;//0x14
//====slave status define
parameter s_idle = 3'b000;
parameter s_read = 3'b001;
parameter s_write = 3'b010;

reg [2:0] state = s_idle;


reg [1:0] done_flag = 2'b0;


reg [2:0] m_status;
reg [1:0] m_done;
//===mycore process start--->
assign wb_err_o=0;
assign wb_rty_o=0;

//===slave process================

always @(posedge wb_clk)
begin
	m_status <=  test_status;
	m_done <= test_done;
	read_value <= ram_data;
end

always @(posedge wb_clk)
begin
	master_status <= {27'b1001_1010_1011_1100_1101_1110_1111_0000,m_status,m_done};
end


always @(*)
begin
	sum = num_1 + num_2;
end


always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			address <= 32'h0;
			flag <= 3'b0;
			done_flag <= 2'b0;
		end
	else
		begin
			if(2'b10 == done_flag)
				begin
					address <= 32'h0;
					flag <= 3'b0;
				end
			else if(2'b01 == done_flag)
				begin
					address <= write_address;
					flag <= 3'b001;
					done_flag <= 2'b10;
				end
			else
				begin
					if(3 == num_2)
						begin
							address <= write_address;
							flag <= 3'b001;
							done_flag <= 2'b01;
						end
					else
						begin
							address <= 32'h0;
							flag <= 3'b0;
							done_flag <= 2'b00;
						end
					
				end
		end
end

always @(posedge wb_clk)
begin
	if(wb_rst)
		begin
			state <= s_idle;
		end
	else
		begin
			case(state)
			s_idle:
				begin
					wb_dat_o <= 1'b0;
					wb_ack_o <= 1'b0;
			
					if(wb_stb_i && wb_cyc_i && wb_we_i)
						begin
							state <= s_write;
						end
					else if(wb_stb_i && wb_cyc_i && !wb_we_i)
						begin
							state <= s_read;
						end
					else
						begin
							state <= s_idle;
						end
				end
	
			s_write:
				begin
					if(wb_adr_i == {mycore_adr,24'h000000})
						begin
							num_1 <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i == {mycore_adr,24'h000004})
						begin
							num_2 <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i == {mycore_adr,24'h000010})
						begin
							write_address <= wb_dat_i;
							wb_ack_o <= 1'b1;
						end
					else 
						begin
							//wb_ack_o=1'b0;
						end
				
					state <= s_idle;
				end
  
			s_read:
				begin
					if(wb_adr_i=={mycore_adr,24'h000000})
						begin
							wb_dat_o <= num_1;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000004})
						begin
							wb_dat_o <= num_2;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000008})
						begin
							wb_dat_o <= sum;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h00000c})
						begin
							wb_dat_o <= master_status;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000010})
						begin
							wb_dat_o <= write_address;
							wb_ack_o <= 1'b1;
						end
					else if(wb_adr_i=={mycore_adr,24'h000014})
						begin
							wb_dat_o <= read_value;
							wb_ack_o <= 1'b1;
						end
					else 
						begin
							wb_dat_o = 0;
							wb_ack_o <= 1'b1;
						end
				
					state <= s_idle;

				end
		
		
			default:
				begin
					state <= s_idle;
				end
		
			endcase
		end
end

endmodule


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


 


 
 4》d_bus 优先级代码:arbiter_dbus.v(与写相同)
 
 5》linux driver(与写相同)
 
 6》makefile(与写相同)
 
2.2.3 模块连接图:

 

 

2.2.4 验证结果:

 

 

2.3 小结
写driver时要注意大小端的问题。
比如想写0x97000000(master要访问的地址),在driver里面要写0x00000097。

 

posted @ 2013-04-11 10:46  xinyuyuanm  阅读(215)  评论(0编辑  收藏  举报