(原创)构建基于aemb的sopc系统(五)--系统仿真与fpga验证(DE2-70平台)
构建aemb的sopc系统(不带串口)
下面开始构建aemb的sopc系统并对整个系统做仿真。系统仍先采用aemb+wishbone+onchip memory+gpio的形式
参考(原创)基于or1200最小sopc系统搭建(一)--搭建及仿真(DE2,DE2-70)
在opencores网站上下载aemb_latest.tar.gz,wb_conmax_latest.tar.gz, gpio_latest.tar.gz解压出源码到 aemb , wb_conmax , gpio 目录下。
Onchip-memory用altera的MegaWizard Plug-In Manager工具生成,并为之编写符合wishbone slave接口规范的接口,参考(原创)Altera 1-port ram 的wishbone slave接口写法和wishbone master BFM验证,用ram0.mif文件初始化。
Pll的配置如下
Inclk0 50M
Clk c0: output clock frequency: 25MHz, Clock phase shift 0.00 ns, Clock duty cycle %:50
为or1200提供时钟
Clk c1: output clock frequency: 10MHz, Clock phase shift 0.00 ns, Clock duty cycle %:50
生成的目录结构
/aemb_sopc_gpio
/aemb
/wb_conmax
/gpio
/ram
/pll
构建一个sopc系统
编写aemb_sys.v文件,把各个模块连接起来。
构建顶层模块aemb_sopc.v,把aemb_sys包装起来,便于在DE2上验证。
从C:\altera\90\quartus\eda\sim_lib目录(参考)下拷贝altera_mf.v和220model.v文件到顶层aemb_sopc_gpio目录下,用于仿真。
添加Reset_Delay文件用于产生复位信号。
编写aemb_sopc_tb.v测试文件,把开关SW信号附一个任意值。
最终的目录结构
/aemb_sopc_gpio
/aemb
/wb_conmax
/gpio
/ram
/pll
aemb_sopc.v
aemb_sys.v
aemb_sopc_tb.v
Reset_Delay.v
altera_mf.v
220model.v
编写vlog参数文件vlog.args文件。
编写.do脚本文件。
调试至硬件平台没有错误。
可把or1200工程中的board.h文件,修改里面的各个模块的地址和配置寄存器的信息与自己的工程相符。
使用orsocdef.h文件,以REG32()的方式访问外部地址空间。
编写主程序gpio_aemb.c
#include "orsocdef.h"
#include "board.h"
int main(){
uint32 gpio_in;
REG32 (RGPIO_OE) = 0xffffffff;
while(1){
gpio_in = REG32 (RGPIO_IN);
gpio_in = gpio_in & 0x0000ffff;
REG32 (RGPIO_OUT) = gpio_in;
}
}
修改gccrom文件,在生成可执行的.elf文件后,加上以下语句。
先用mb-objcopy把生成的.elf文件转换成.ihex文件。
# Convert the ELF file to an IHEX file
mb-objcopy -O ihex $ELFFILE $ELFFILE.ihex && \
echo "copy2ihex=$?" && \
再用ihex2mif工具,把.ihex文件转换成altera ram支持.mif初始化文件。(也可以在生成.srec文件后,用srec2mif工具转换)。
# Generate a MIF file from the IHEX file
./my_c/ihex2mif -f $ELFFILE.ihex -o ram0.mif && \
echo "ihex2mif=$?" && \
把生成的ram0.mif文件拷贝到,配置altera ram时指定的目录。
对Sopc系统进行仿真(不带串口)
以下进行系统级的仿真。
所遇到的问题:
在aemb2_edk63.v中为什么把地址设成
output [AEMB_IWB-1:2] iwb_adr_o;
修改aemb_sys.v文件,应该把29位的iwb_adr_o和dwb_adr_o放到wishbone 总线的高29位,低两位取零。
但是仿真结果是,只取了第一条指令便停止运行了。通过仿真结果发现aemb模块中的dena信号和iena信号都是无效的,这是因为以下这条语句的原因:
assign iena = ich_fb &
xwb_fb &
dwb_fb &
sys_ena_i;
由于xwb的接口没接,所以iena无效,看来还是把xwb接口的必要的输入信号接上吧。
vlog.args中使用”//”注释,在sim.do中用”#”注释
在edk63的模拟仿真时,分设了一个rom和一个ram。Rom只与指令总线相连,ram只与数据总线相连,这样,即使同时取指和取数据都不会发生错误,但是在aemb+wishbone+onchip memory的仿真过程中,只设了一块onchip-memory,这样当指令总线和数据总线同时对onchip memory进行操作时,就发生了错误。在仿真波形上显示的是,当数据总线有一个写操作时,系统便挂起啦了,因为数据总线写的数据,正好被指令总线取走。为什么会这样呢,还应该是ram的wishbone slave接口写得有错误。为什么ram0_top.v会不正常呢,在or1200的那个系统中是正常的?
改了一下ram0_top.v,仿真正确了。Wb_conmax是不会同时对同一地址进行操作的。是ram0_top中wb_ack_o的信号有错误,wb_ack_o的有效条件是在系统的总线循环信号和选通信号 wb_stb_i & wb_cyc_i (记为request信号)同时有效并且是在它们同时有效的上升沿处才有效。这就假定了一个情况,就是如果aemb系统的主端口在接收到wb_ack_o信号有效后就必须把request信号置低,表示一次总线操作的完成。
如若不然呢。如若不然,aemb处理器等到wb_ack_o有效后并没有把request置低,而是等着下一次或者更长时间的wb_ack_o有效信号,便不会把request置低,也就不会有这个信号的上升沿产生。但ram0_top中见不到有request信号的上升沿,便不会把wb_ack_o信号置高,从而就僵持了起来。
怎样解决这个问题呢
把ram0_top.v中的这句代码
assign request_rising_edge = (request_delay ^ request) & request;
改成
assign request_rising_edge = ~wb_ack_o & request;
就可以了,gpio程序的仿真结果。
LEDR输出等于SW的输入。
关于ram0_top中的这个问题,在那个or1200中没有错误。不知道aemb为什么会不一样。
FPGA上验证(不带串口)
参照(原创)基于or1200最小sopc系统搭建(二)--QuartuII工程及DE2平台下载构建QuartusII工程。
不过这一次试一下不用图形化页面,只修改.qsf文件的方法。
修改or1200_sopc.qsf文件,主要修改的地方有:
文件名改一下改成aemb_sopc.qsf吧
引脚配置全不用改
改一下TOP_LEVEL_ENTITY为aemb_sopc。
用set_global_assignment -name VERILOG_FILE命令加入工程的Verilog文件(带路径)
执行
>quartus_sh --flow compile aemb_sopc.qsf
编译成功之后,执行以下命令把.sof文件配置到DE2
>quartus_pgm --no_banner --mode=jtag -o p;aemb_sopc.sof
显示效果与(原创)基于or1200最小sopc系统搭建(二)--QuartuII工程及DE2平台下载是相同的。看来如果要维护一个可移植的QuartusII工程,除了HDL代码外,只需要一个.qsf文件,或者.tcl文件就可以了。
添加串口
下面添加串口,重复以上步骤。
参考(原创)基于or1200最小sopc系统搭建(三)--串口添加串口。
把uart16550_latest.tar.gz源码文件解压到工程目录aemb_sopc_gpio_uart。
修改sopc顶层文件aemb_sys.v添加上串口相关信号。
修改工程的顶层文件aemb_sopc.v添加上串口相关信号。
把UART的接收器核uart_rx.v拷贝到工程目录aemb_sopc_gpio_uart。
修改testbench文件aemb_sopc_tb.v,把串口仿真模块加入。
修改vlog.args文件,加入串口相关文件。
修改sim.do文件,增长仿真时间。
软件工程的建立,加入demo_or32_sw.zip中的uart.h和uart.c文件。修改主程序:
#include "orsocdef.h"
#include "board.h"
#include "uart.h"
int main(){
uint32 gpio_in;
REG32 (RGPIO_OE) = 0xffffffff;
//iprintf("iwillsuc!\n");
uart_init();
uart_print_str("Hello World From aeMB!\n");
while(1){
gpio_in = REG32 (RGPIO_IN);
gpio_in = gpio_in & 0x0000ffff;
REG32 (RGPIO_OUT) = gpio_in;
}
}
执行
$ ./gccrom my_c/uart.c my_c/aemb_gpio_uart.c
生成ram0.mif文件。
串口程序仿真结果
# H
# e
# l
# l
# o
#
# W
# o
# r
# l
# d
#
# F
# r
# o
# m
#
# a
# e
# M
# B
# !
重新配置QuartusII工程,修改aemb_sopc.qsf文件即可。
加入uart相关的文件。
执行
>quartus_sh --flow compile aemb_sopc.qsf
编译成功之后,执行以下命令把.sof文件配置到DE2
>quartus_pgm --no_banner --mode=jtag -o p;aemb_sopc.sof
配置串口115200 8N1
但在下载之后发现,串口并不能正常工作,打印出一些莫名奇妙的东西。在仿真正确的情况下,出现这种情况更令人郁闷。最后,还是张老师发现,问题仍出现在onchip memory上,便没再做修改,把onchip memory直接换掉了。
可以打印出来了,但是复位仍有些问题,便又修改了C代码,把core.hh头文件加进去了。
#include "orsocdef.h"
#include "board.h"
#include "uart.h"
#include "aemb/core.hh"
int main(){
uint32 gpio_in;
REG32 (RGPIO_OE) = 0xffffffff;
uart_init();
uart_print_str("Hello From aeMB!\n");
while(1){
gpio_in = REG32 (RGPIO_IN);
gpio_in = gpio_in & 0x0000ffff;
REG32 (RGPIO_OUT) = gpio_in;
}
}