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。

浙公网安备 33010602011771号