本帖最后由 Tiy 于 2014-1-2 10:09 编辑
学习过nios的小伙伴应该知道nios可以添加自定义外设,下面将以为软核SCore430添加PWM外设为例,讲解如何为SCore430添加外设。 添加外设应该了解以下几点知识: 1.SCore430外设接口时序 2.SCore430的memory map 3.外设控制器ExphCtrl源码的添加新增外设接口 SCore430的外设接口时序 主机接口 名称 | 说明 | out_writeexphaddr[15:0] | 写外设地址 | out_writeexphdata[15:0] | 写外设数据 | out_writeexphbyten[1:0](可选) | 16bit数据分为两个字节,对应out_writebyten的两个bit位,当对应位置位时,对应字节有效。有这个信号的原因是430指令集中大部分指令有16bit和8bit两种操作模式 | out_writeexphen | 写数据使能,当时钟上升沿到来,且此信号为高电平时,数据被写入。 | out_readexphaddr[15:0] | 读外设寄存器地址,用作数据选择器的输入参数,从而输出指定寄存器数据。 |
外设接口 名称 | 说明 | in_clk | 系统时钟 | in_rst | 系统复位 | in_writeaddr[15:0] | 写数据地址 | in_writeen | 写数据使能 | In_writebyten[1:0] (可选) | 数据的字节使能 | in_writedata[15:0] | 写入的数据 | in_readaddr[15:0] | 读数据地址 | out_readdata[15:0] | 读取数据输出 |
SCore430内存区域划分
上图是TI官方文档MSP430x1xx系列的内存映射图,从图中可以看出外设内存地址范围是010h~1FFh,并且010~0FFh范围了只支持8bit的字节访问,SCore430没 有此限制。 010h~1FFh地址范围大部分地址已被标准外设占用,但是我们可以不添加无用的标准外设,将地址让出来,留给自定义外设使用。
SCore430外设控制器的源码修改 在写自定义外设前首先确定外设有几个寄存器(为了操作和理解方便,在此规定所有寄存器为16bit),然后为这些寄存器分配地址。打开quartus II工程目录下的 symbol.v文件 /******************************************************************* *建立时间:2013.12.20 作者:李广敏,all rightsreserved *修改时间: 修改人: *功能:符号定义文件,包含指令名称和外设寄存器名称 /******************************************************************/ /*************单操作数指令************/ `define PUSH 5'b00100 `define SWPB 5'b00001 `define SXT 5'b00011 `define RRA 5'b00010 `define RRC 5'b00000 `define CALL 5'b00101 /***********跳转指令**********/ `define JC 3'b011 `define JZ 3'b001 `define JGE 3'b101 `define JL 3'b110 `define JMP 3'b111 `define JN 3'b100 `define JNC 3'b010 `define JNE 3'b000 /**********双操作数指令***********/ `define MOV 4'b0100 `define ADD 4'b0101 `define ADDC 4'b0110 `define DADD 4'b1010 `define SUB 4'b1000 `define SUBC 4'b0111 `define CMP 4'b1001 `define AND 4'b1111 `define BIC 4'b1100 `define BIS 4'b1101 `define BIT 4'b1011 `define XOR 4'b1110 /*************复位地址*************/ `define RESET 16'h8002 /**************外设地址***************/ /******P1**************/ `define P1DIR 16'h0022 `define P1OUT 16'h0021 `define P1IN 16'h0020 /*********P2************/ `define P2DIR 16'h002a `define P2OUT 16'h0029 `define P2IN 16'h0028 /******Multipilier*****/ `define MPY 16'h0130 `define MPYS 16'h0132 `define MAC 16'h0134 `define MACS 16'h0136 `define OP2 16'h0138 `define RESLO 16'h013a `define RESHI 16'h013c `define SUMEXT 16'h013e
文件后面内容是外设地址定义,假设我们PWM只有一个寄存器,占空比寄存器,可以在symbol.v最后接着乘法器地址后面写入`define DUTY 16’h0140 当外设寄存器当做16bit访问时,地址必须为偶数。 所有外设可以共用同一条写入总线,但是数据输出总线要分离,通数据选择器送入SCore430内部,外设控制器ExphCtrl主要充当数据选择器的作用。打开ExphCtrl.v文件。 /******************************************************************* *建立时间:2013.12.20 作者:李广敏,all rightsreserved *修改时间: 修改人: *功能:外设访问控制器,对外设反馈的数据,根据读取地址, *选择正确的外设数据传送给memctrl模块 /******************************************************************/ `include "symbol.v" module ExphCtrl( inputin_clk, inputin_rst, /**********memctrlinterface************/ input[15:0]in_exphreadaddr, //外设寄存器读地址 outputreg[15:0] out_exphdata, //读外设数据接口 /***********exphinterface*************/ /****P1 port***/ input[15:0]in_readP1data, /*****MultiplierPort***/ input[15:0]in_readmultiplier, /******P2 Port******/ input[15:0]in_readP2data );
/*********************************************** *对外设反馈的数据根据地址选择,时钟上升沿输出数据, *当用户添加自定义外设时,需要修改此always模块 /**********************************************/ always@(posedge in_clk) begin case([url=]in_exphreadaddr[/url]) /************P1Interface***********/ `P1DIR: out_exphdata <= in_readP1data; `P1OUT: out_exphdata <= in_readP1data; `P1IN: out_exphdata <= in_readP1data; /*************P2interface************/ `P2DIR: out_exphdata <= in_readP2data; `P2OUT: out_exphdata <= in_readP2data; `P2IN: out_exphdata <= in_readP2data; /************MultiplierInterface*****/ `MPY: out_exphdata <=in_readmultiplier; `MPYS: out_exphdata <= in_readmultiplier; `MAC: out_exphdata <=in_readmultiplier; `MACS: out_exphdata <= in_readmultiplier; `OP2: out_exphdata <=in_readmultiplier; `RESLO: out_exphdata <= in_readmultiplier; `RESHI: out_exphdata <= in_readmultiplier; `SUMEXT: out_exphdata <= in_readmultiplier; default:out_exphdata <= 0; endcase end endmodule
可以看出,外设控制器中代码就是一个数据选择器,首先增加我们自定义外设的数据反馈接口 input[15:0] in_readpwmdata 在case语句块中添加对PWM反馈数据的选择 Case(in_exphreadaddr) … … `DUTY: out_exphdata <= in_readpwmdata; … ... Endcase 外设控制器修改完成,最后修改好的文件可以查看附件提供的最新工程。 PWM外设添加 PWM代码可以查阅附件工程中文件,在此对PWM定义端口做出解释说明 modulePWM( input in_clk, input in_rst, input[15:0]in_writeaddr, input in_writeen, input[15:0]in_writedata, input[15:0]in_readaddr, output reg[15:0]out_pwmdata, output regout_pwmout ); 可以看出,PWM包含了上面提到外设接口除了In_writebyten[1:0]外的所有必需接口,out_readdata被重命名为out_pwmdata,out_pwmout是用户自定义端口。 按照上述步骤添加PWM文件并且修改symnol.v和ExphCtrl.v后,开始按下图创建PWM和ExphCtrl的符号文件。
打开CPUCore430.bdf顶层文件添加PWM并更新ExphCtrl
找到ExphCtrl模块,右键更新如上图所示。 更新后可以发现多出了我们添加的in_readPwmdata接口,此接口为下面添加的PWM模块的数据反馈接口
双击空白处,弹出上图画框,在project目录下选择PWM模块添加到P2MODULE下方,如下图所示
将PWM左边数据接口与左边数据总线连接,连接方式参照P2MODULE,所以外设输入端口与数据总线连接方式相同。将out_pwmdata与ExphCtrl增加的 in_readPwmdata端口相连。
右键PWM为out_pwmout添加pin管脚。
到此外设添加工作完毕,可以编译工程检测有没有错误。 C语言代码驱动外设
#include<msp430x14x.h>
#define PwmDuty (* (int*)0x140) //0x140对应symbol.v中语句`define DUTY 16'h0140
void delay() //100Mhz主频,每条指令机器周期6~8
{
int i,j;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++);
}
int main( void )
{
char counter = 0;
while(1)
{
delay();
PwmDuty = counter++;
}
return 0;
}
按照文件件包V1.1中的《使用手册》编译此文件,将最终转换获得mif文件添加到quartusII工程中,将out_pwm管脚与LED连接,运行时即可看到LED呼吸灯。 各位可以按照此方法添加自己的外设(无中断请求功能)。具有中断功能的V2.0版将会再两个月内完成。
所有软件设置和代码编写以最新文件包中的《使用手册》知道为准。 文件包V1.1
|