测试1:SFR可用性测试
简单的用逻辑模拟一个SFR可访问的外部寄存器,该寄存器只使用低四位,对应控制4个外部LED的亮暗。以此验证核外SFR的可用性。
对于8051硬核而言,如果开启核外SFR功能,提供了如下接口(与前面给出的波形图对应):
// External Special Function Registers interface
output[7:0] sfrdatao; //8051写数据
output [6:0] sfraddr; //8051访问地址
input [7:0] sfrdatai; //8051读数据
output sfrwe; //8051写SFR使能信号,高电平有效
output sfroe; //8051读SFR使能信号,高电平有效
SFR从机的逻辑接口代码如下:
reg[3:0] ledr; //LED指示灯对应的SFR
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n) ledr 《= 4‘h0;
else if(sfrwe && (sfraddr == 7’h78)) ledr 《= sfrdatao[3:0];
//8051往地址为0xf8的SFR写数据,将数据锁存到ledr寄存器中
end
assign {led3,led2,led1,led0} = ledr;
软件编程时,需要在工程中做一个新的sfr定义:
//自定义SFR
sfr LED = 0xf8; //低4bit控制LED亮暗
编写函数实现SFR控制的流水灯:
void main(void)
{
while(1)
{
LED = 0x1;
delay(500);
LED = 0x2;
delay(500);
LED = 0x4;
delay(500);
LED = 0x8;
delay(500);
}
}
实验结果证明功能可行,达到预期。这个SFR功能的使用还是蛮简单的。
为了验证写功能,基本思路是想针对板载4个按键做一个SFR寄存器,专供8051内核读取当前按键值,然后把该值分别赋给4个LED(在前面测试的基础上执行)。添加的逻辑代码:
reg[3:0] keyr;
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n) keyr 《= 4‘hz;
else if(sfroe && (sfraddr == 7’h79)) keyr 《= {key4,key3,key2,key1}; //8051从地址为0xf9的SFR读出数据
else keyr 《= 4‘hz;
end
assign sfrdatai = keyr;
读时序这个时钟clkcpu应该是8051工作的指令时钟,即8051外部输入时钟的12分频。这个时序图好像不太准确,实际读或写选通高脉冲不会保持一整个指令周期。特权同学测试下来发现用50MHz时钟做从接口,早一个时钟或是晚一个时钟周期送数据都无法使8051读走数据,只有上面给出的代码下时钟送数据才能正常保证8051锁存数据。也就是说,数据必须在读选通期间都保持稳定,早一个时钟周期撤销或是晚一个时钟周期撤销都不行。因此,为了延长数据有效长度,改进如下:
reg[3:0] keyr;
reg keyrden;
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n) keyrden 《= 1’b0;
else if(sfroe && (sfraddr == 7‘h79)) keyrden 《= 1’b1;
else keyrden 《= 1‘b0;
end
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n) keyr 《= 4’hz;
else if(keyrden || (sfroe && (sfraddr == 7‘h79))) keyr 《= {key4,key3,key2,key1}; //8051从地址为0xf9的SFR读出数据
else keyr 《= 4’hz;
end
assign sfrdatai = keyr;
软件编程也很简单:
//自定义SFR
sfr LED = 0xf8; //低4bit控制LED亮暗
sfr KEY = 0xf9; //低4bit对应当前按键值
void main(void)
{
while(1)
{
LED = KEY;
}
}
测试2:SFR性能测试
与《国产FPGA试用手记二(51硬核性能测试)》做了类似的测试,验证LED寄存器拉高拉低的速度,和之前的结果一样。也就是说,核外的SFR在不使用等待功能的情况下与核内SFR的操作速度是一样的。
测试3:SFR等待功能验证
在50MHz的clkcpu下,没有等待时(即assign sfrack = 1‘b1;),不断的对核外SFR写使能情况可以得到如图2所示的使能信号波形。两次上升沿之间240ns即一个指令周期(12个50MHz时钟周期),而读使能信号有效高脉冲为160ns,即8个时钟周期。
图4
Datasheet中标明的sfrack信号其实无法直接从例化的51硬核中找到接口,于是特权同学干脆直接生成的IP核例化文件中把它手动引出来了,在自定义逻辑中对这个信号做了一些测试,也发现了该信号的使用方法。
代码如下:
reg[7:0] sfcnt; //延时等待计数器,以50MHz为时钟单位计数
wire sfrack; //SFR 读写等待信号
always @(posedge clk_50m or negedge rst_n) begin
if(!rst_n) sfcnt 《= 8’d0;
else if(sfrwe) sfcnt 《= sfcnt+1‘b1;
else sfcnt 《= 8’d0;
end
assign sfrack = (sfcnt == 0) | (sfcnt 》 8‘d23);
//等待n个指令周期,则sftcnt要大于(n*12-1)
该代码实现在sfrwe即SFR寄存器写选通信号到来后,用计数器sfcnt进行计数,然后相应的对需要延时等待的8051指令周期数通过控制sfrack为低电平实现。
分别设置了sfcnt》8’d16、sfcnt》8’d24、sfcnt》8’d23得到sfrwe的波形如图5、图6、图7所示。
图5
图6
图7
由此可见,这里延时等待的时间必须刚好是指令周期。即系统指令周期为20ns*12=240ns,那么我们外部计数周期也是20ns的情况下,一般取等待时钟数为12的倍数即可。否则就会出现图3和图4的“毛刺”,其中原因不好妄下定论,恐怕和器件本身的内部处理机制有关。
评论
查看更多