基于OR1200开源软核处理器的简单SoC系统设计,FPGA与仿真实现,UART、GPIO、定时器等外设,基于wishbone总线

概论

SoC是在单个芯片上集成数字、模拟电路、CPU、DSP等各种模块,实现一个系统的功能,集成度高、可靠性好、成本低。本设计为一个基于OR1200的系统设计,各模块之间采用wishbone总线连接,所使用的主要模块有GPIO、on chip memory、PLL、定时器模块(PTC)、串口(uart16550)、外部中断模块。系统软件实现的功能为通过按键控制LED灯,通过中断,在中断服务函数中通过串口发送数据,通过定时器产生一个PWM波,来调节LED灯的亮度。

系统源码 qq 3270516346

一、系统总体功能概述

1、系统硬件模块

① OR1200处理器
② wishbone总线
③ 定时/计数器模块(PTC)
④ 串口模块(UART)
⑤ 锁相环模块(PLL)
⑥ GPIO接口模块
⑦ 片上存储器模块(on chip memory)

2、各模块连接

在这里插入图片描述

3、系统总体功能

将GPIO配置为双向端口,将GPIO的低8位定义为输出,并连接到LED灯上,高八位定义为输入并连接到按键上,通过按键控制LED的亮灭。启用外部中断,当输入为上升沿时触发中断,在中断服务函数中,通过串口向终端发送数据。启用定时器,使用定时器产生PWM波,将定时器PWM的输出连接到LED上,控制LED的亮度。通过PLL模块来调节系统时钟频率为25MHz。

二、最小系统模块设计

1、OR1200

1、OR1200是OR1000的一种实现,源于OpenRISC项目,免费开源。
2、OR1200采用数据和指令分离的哈佛体系结构,为32位RISC处理器,所以OR1200占用两个主端口,rim和rdm端口,分别为指令和数据总线。
3、OR1200支持中断、电源管理灯多种功能

2、wishbone

1、wishbone总线是Silicore公司推出的片上总线标准,被opencore组织采用并维护。
2、wishbone支持8个主设备和16个从设备,内置仲裁器,允许多个主从设备进行通信

3、存储器

1、可以使用寄存器来实现存储器,也可以使用FPGA嵌入式存储块来实现
2、存储器生成以后,要采用wishbone总线进行封装,使其符合wishbone总线标准

三、各功能模块软硬件设计

1、GPIO

1、模块主要特征:
①用户可以从1到32之间选择通用IO信号的个数,更多信号可以采用多个GPIOP核并用。
②包含三态使能端或开漏使能端(需要三态或漏级开路IO单元)。
③设为输入的通用O信号可对CPU产生中断请求。
④设为输入的通用I/O信号能记录在系统时钟的上升沿或外部时钟的用户编程边沿。
2、GPIO模块主要由WISHBONE主机接口、GPIO寄存器、辅助输入输出端口、外部单元接口组成。GPIO核结构如下所示:
在这里插入图片描述

3、GPIO模块接口采用wishbone接口,在本设计中GPIO连接到wishbone总线的从接口14上,基地址定义为“GPIO_BASE 0xE0000000”。
4、GPIO的寄存器定义如下:
在这里插入图片描述

按照如上的定义定义寄存器的地址:

#define GPIO_BASE		0xE0000000
#define RGPIO_IN		(GPIO_BASE + 0x0)
#define RGPIO_OUT		(GPIO_BASE + 0x4)
#define RGPIO_OE		(GPIO_BASE + 0x8)
#define RGPIO_INTE		(GPIO_BASE + 0xc)
#define RGPIO_PTRIG		(GPIO_BASE + 0x10)
#define RGPIO_AUX		(GPIO_BASE + 0x14)
#define RGPIO_CTRL		(GPIO_BASE + 0x18)
#define RGPIO_INTS		(GPIO_BASE + 0x1c)
#define RGPIO_ECLK		(GPIO_BASE + 0x20)
#define RGPIO_NEC		(GPIO_BASE + 0x24)

5、在初始化GPIO时,设置高8位为输入,低8位为输出,开启外部中断,开启GPIO高8位输入的中断,并设置为上升沿触发中断。相应的GPIO初始化程序为:

void gpio_int()
{
	REG32 (RGPIO_OE) = 0xff000000;
//	gpio[31 :24] in   gpio[23:0] out;
  //中断设置
  REG32( RGPIO_PTRIG)=0xff000000;  //上升沿触发	
  REG32(RGPIO_INTS )=0x00000000;  //清楚中断请求
  REG32(RGPIO_INTE )=0xff000000;   //开启外部中断
  REG32 ( RGPIO_CTRL )=0x01;     //开启总中断

6、将GPIO配置为双向端口,OE为输入输出控制端。将GPIO端口定义为“inout”类型,相应的模块结构如下:
在这里插入图片描述

对于每一位都可以单独设置为输入输出,相应的HDL描述为:

module  set(
            input oe,
            input  gpio_out,
            output reg gpio_in,
            inout  gpio,
            input clk
            );
       reg gpio_reg;
  assign gpio=(oe==1'b1)?gpio_out:1'bz;
  always @(posedge clk)
        begin
        	if(oe)
        	  gpio_reg<=gpio_out;
        	else
        	  gpio_in<=gpio;
        end
endmodule

2、UART

、UART为异步串行接口,数据在单条传输线上一位一位的传输,节省通信总线,码率低,本设计采用opencore上开源的UART 16550 IP模块。
2、在UART16550模块中,我们约定数据为8个数据位、1个停止位、无效验位,波特率设置位115200.
3、UART控制器表示如下:
在这里插入图片描述

UART接口控制器设计中只支持TXD和RXD两个信号。
4、设置串行通信的波特率为115200,波特率设置方式为“(输入时钟速度)/(除数锁存值)= 16 x 通信
波特率“。
5、在设计时我们通常只使用“void uart_putc(char c)”函数来发送数据,使用“void uart_init(void)”函数来初始化。

3、定时器、看门狗和PWM(PTC)

1、PTC的主要功能为:
①32位计时、计数功能;
②次或连续计时、计数;
③可编程PWM模式;
④系统时钟核外部时钟两种选择;HI/LO参考和捕获寄存器;
⑤PWM输出三态控制;
⑥PWM计时器/计数器计时中断;
⑦WISHBONE 接口兼容。

2、PTC模块的结构如下:
在这里插入图片描述

PTC通过WISHBONE接口连接到系统并与系统通信,PTC有4个与外部连接的端口。ptc_ecgt为当使用外部输入时钟时的时钟输入端;ptc_capt为使用捕获输入模式模式时,当输入下降沿或上升沿时,捕获当前的计数值;ptc_pwm为使用输出比较模式时,pwm波输出接口。
3、PTC的寄存器定义为:
在这里插入图片描述

PTC共有4个寄存器,我们将PTC连接到WISHBONE从模块的15端口,对于寄存器的定义为:

#define PTC_BASE               0xF0000000
#define RPTC_CNTR              (PTC_BASE +0x00)
#define RPTC_HRC               (PTC_BASE +0x04)
#define RPTC_LRC               (PTC_BASE +0x08)
#define RPTC_CTRL              (PTC_BASE +0x0C)
RPTC_CTRL为控制寄存器,其每一位都有相应的作用,将控制寄存器中的每一位单独定义:
#define en_set                 REG32(RPTC_CTRL)|=0x0001
#define en_reset               REG32(RPTC_CTRL)&=0x0fffe

#define eclk_set               REG32(RPTC_CTRL)|=0x0002
#define eclk_reset             REG32(RPTC_CTRL)&=0x0fffd

#define nec_set                REG32(RPTC_CTRL)|=0x0004
#define nec_reset              REG32(RPTC_CTRL)&=0x0fffb

#define oe_set                 REG32(RPTC_CTRL)|=0x00008
#define oe_reset               REG32(RPTC_CTRL)&=0x0fff7

4、我们使用PTC模块来产生pwm波形,在初始化时,首先使能PTC模块,然后使能pwm输出功能,配置定时器为自动循环计数方式,然后设置HRC和LRC的值,以配置pwm的频率和占空比。

void pwm_init(int lrcm,int hrcm)
{
	en_set;
	oe_set;
	single_reset;
	lrc=lrcm;
	hrc=hrcm;
}

在产生pwm波时,定时器计数到LRC的值时,在从0开始计数;当当前计数值小于HRC时pwm输出为低电平,当当前计数值大于HRC的值时,pwm输出高电平,所以LRC决定pwm的频率,HRC决定pwm的占空比。

4、锁相环设置(PLL)

1、锁相环能调节输入时钟的频率和相位,我们采用PLL模块将FPGA上50MHz的信号时钟变为25MHz。
2、
在这里插入图片描述

四、软件设计

1、中断设置

1、需要先使用“l.mtspr”配置特殊功能寄存器开处理器中断;中断服务函数使用“l.rfe”返回。开中断操作为:
     l.mfspr r1,r0,0x0011
     l.ori r3,r1,0x6
     l.mtspr r0,r3,0x0011
2、外部中断对应的中断向量地址为0X800,当外部中断响应后,程序就会跳转到0x800地址处执行相应的程序。
3、在0x800处,跳转到相应的中断服务函数处,在中断服务函数中,要清楚中断标志位,即使“REG32(RGPIO_INTS )=0x00000000;”中断服务函数执行完毕后调用“l.rfe”指令恢复现场,接着执行相应的程序。

2、主程序设计

1、在主程序中,首先初始化串口、定时器和GPIO,配置定时器频率为1kHz,占空比为50%。
2、相应的C程序为:

int main (void)
{
	  uart_init();
	 uart_print_str("\nstart\n");
    gpio_int();
    pwm_init(4999,4440);
   gpio_out=0x00fffff;
  while(1)
  {  	
  	out();  
   delay_ms(10);
   }
}

3、中断服务函数设计

在中断服务函数中,首先通过串口打印相应的字符,然后在清楚中断,调用“l.rfe”指令进行中断返回。

void gpios(void) 
{
 uart_print_str("\nexit\n");
     exit_clear()}
void exit_clear()
{
	REG32(RGPIO_INTS )=0x00000000;
  re();
}

五、结果验证

1、仿真验证

通过Modelsim进行仿真,对系统施加一定的激励,观察输出的时序。
  观察的gpio输出值和串口打印数据为:
在这里插入图片描述

观察的pwm的输出为:
在这里插入图片描述

可以看到有相应的pwm波生成。

2、FPGA系统验证

将所设计的系统下载到FPGA中进行验证
设计步骤为分析综合、映射、布局、布线、管脚分配,在FPGA上上的引脚分配为:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chy_wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值