在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 14353|回复: 34

开源软核学习笔记03(8051软核如何仿真modelsim或C++)——2014_1_11

[复制链接]
发表于 2014-1-11 18:32:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 oldbeginner 于 2014-1-12 06:17 编辑

oc8051的帮助文件最后两页给出了测试文件介绍,并给了一个网站

这个网站除了开源自己51软核外,还有利用C++仿真51的源代码,只高兴了一会。因为这个代码好像要用makefile和g++,之前从来没有这些编译,都是vc或keil工具,从没碰过Linux和相关工具。

另外还有一个问题,我还没来得及买FPGA开发板,我觉得可以用modelsim仿真,暂时应该不需要开发板。(这个想法来源于Proteus使用,但这几天和modelsim的接触,感觉比Proteus效果差很远)

另外找了几篇相关国内的oc8051测试文章:

在FPGA上对OC8051IP核的修改与测试

用FPGA实现8051内核及外设I2C接口扩展的研究(2006年论文)

DE2上使用OC8051运行点灯程序(一)
(上面的文章属于http://download.csdn.net/detail/leishangwen/5173363其中的一个文件,来自leishangwen的提示)

************************************************************************************

因为基础差,不论是DE2上使用OC8051运行点灯程序modelsim仿真,还是C++仿真(没能编译出),利用现成的资源,我都没能作出来。需要手把手那种类型的教程啊!

计划:1、继续研究《DE2上使用OC8051运行点灯程序》,毕竟近水楼台先得月。
          2、先从这里开始求助C++文件的仿真。

C++仿真使用说明
The simulator will continue executing the provided program until either the user hit Ctrl-C or the program completion condition is met. The program completion condition can be set by defining a macro PROGRAM_COMPLETION located in i8051.h to indicate the program completion condition, e.g., RAM[P0] == 0x01.

The program's output can be controlled through the macros PORTS, DEBUG, DEBUG_PC and DETAIL located in i8051.h. If PORTS is defined, anytime one of the output ports of the 8051 changes all ports will be printed out. If DEBUG is defined, a trace of all instructions executed by the simulator will be outputted to the output file specified by the user. If DEBUG is defined and DEBUG_PC is defined the PC for each instruction executed will be outputted to the output file. Finally, if DETAIL is defined, more information regarding each instruction will outputted to the output file.

NOTE: DEBUG_PC and DETAIL are not available in version 1.0.

To use the simulator, edit i8051.h and uncomment the PORTS, DEBUG, DEBUG_PC, and/or DETAIL macros to enable the respective output. Modify the macro PROGRAM_COMPLETION to the appropriate completion condition. If there is no program completion condition do not define PROGRAM_COMPLETION. Make the executable using the supplied Makefile. The program can be invoked by the following command

    8051sim < hexfile > < outfile >


我下载了mingw,结果make时出错,第一次使用不知所措。
01.JPG

8051sim.tar.gz (9.87 KB, 下载次数: 60 )
源代码,感觉有用的来帮帮忙编译一下。

**************************************************

下面先要把剩下两页理解了。
 楼主| 发表于 2014-1-12 17:11:57 | 显示全部楼层
**************************************

Verification

The basic idea is that we download the verification program to internal Program Memory and then monitor output of p0, p1 and p2 ports. Port p3 serves for additional testing of perifery.  

把验证程序下载到内部程序空间, 然后检测P0 P1 P2口的输出,P3口作为附加测试用。

1、oc8051_tb

This is the top module, test bench. It contains connections between oc8051 core and the rest of the verification modules. In this module ports from 0 to 2 are monitored and the data is then compered with the expected data.

Testbench 的顶层模块,包括oc8051软核和其它验证模块的联结。
端口P0 P1 P2被检测,然后对比实测数据与期望数据。

2、oc8051_xram

This module contains external Data Memory. It is important for testing movx instructions.

该模块包括外部数据空间,对检测movx 指令非常重要。

3、oc8051_uart_test

This module is used for testing serial interface (uart). It contains modul oc8051_uart whish is the same as in oc8051 core. Using this module communication across serial interface is tested.

该模块用来检测串口,它包括 oc8051_uart 模块。使用该模块可以检测串口通信。

**************************************************************

Basic idea is that we run a program on our oc8051 core and monitor output ports. So all test programs must put an unexpected value (error number for example) on output if an error occurs.

通过在软核上运行程序,同时检测输出,当发现输出与预期不一致时就知道有错误发生了。

Expected values of outputs are saved in oc8051_test.vec file. This file is loaded to buffer in oc8051_tb module and at every change on ports the output vector is compared to the one in the file. When vector XXXX is reached the test is succesfuly finished.

输出预期值保存在文件 oc8051_test.vec 中。该文件上传给模块 oc8051_tb 的缓存中,每次端口数值的改变,输出向量会和该文件中对应值对比一下。 当向量 xxxx 达到时,测试成功了。

******************************************************************

Port p3

As it was already mentioned port p3 is used for testing the oerifery of the processor.
This is the reason that most pins has special assignment:
7        selects between external memory and uart
           1 - external memory
           0 - uart
6        connected to input t1
5        connected to input t0
4        connected to input int1
3        connected to input int0
2        unused
1        connected to ow, input to external uart
0        connected to wr_bit, input to external uart




**************************************************

Most programs that we use for testing the core was found on homepage of a similar project (http://www.cs.ucr.edu/~dalton/i8051/).
This programs test only processor, so for testing the perifery a few programs are added:
-        div16u: additional testing of mul and div instructions
-        xram_m: testing of external Data Memory
-        timer_test: timer testing
-        counter_test : counter testing
-        interrupt_test : interrupts testing
-        serial_test : serial interface testing
-        r_bank: testing of psw fourth and fifth bit (register bank choosing)


上面就是给出的推荐网站,最后更新是11年前,没关系了,oc8051最后更新也是11年前。

***************************************************************

这样整个文件就浏览完毕,在分析内核代码之前,就像标题所写得,找个方法先测试一下。
 楼主| 发表于 2014-1-13 19:20:06 | 显示全部楼层
先尝试 《DE2上使用OC8051运行点灯程序》,因为下载的文件是完整的,设置一下仿真参数,综合一下就可以仿真了。
我使用的是Quartus 12 加 modesim 6.5 (和文章版本不一致,暂时不知道是否会影响结果)

仿真.gif

结果如下图,
03.JPG

警告很多,但是已经有了眉目了。顺藤摸瓜。

(仿真即使有问题,即使不理解,这个仿真在心里上也是非常重要的。借用《科学结构的革命》中的范式概念,现在刚找到了一种8051软核范式,在该范式下仿真或测试都是有解的,只不过题目比较难,我只要需要耐心学习,然后解题就可以了。)

*******************************

先从oc8051_tb.v文件开始理解,
该文件是test bench文件,

网上搜一下,
什么是test bench 文件?

知道了什么是test bench后,再
如何编写testbench?

编写test bench格式:
1、Module 仿真模块名1;
2、各个施加激励的端口2;
3、例化设计模块3;
4、使用initial 或always 语句来产生激励波形4;
5、监控和比较输出响应5;
6、Endmodule


为什么要按照上面的格式?


*************************************************

那么看一下oc8051_tb.v 的格式和内容,

仿真模块名1, oc8051_tb;

各个施加激励的端口2

parameter FREQ  = 12000; // frequency in kHz

parameter DELAY = 500000/FREQ;

reg  rst, clk,int0,int1, rxd;
reg  [7:0] p0_in, p1_in, p2_in;
wire [31:0] idat_i;
wire [15:0] ext_addr, iadr_o;
wire write, write_xram, write_uart, int_uart, txd,t0, t1, bit_out, stb_o ;
wire ack_xram, ack_uart, cyc_o,  istb_o, icyc_o, t2, t2ex;
wire [7:0] data_in, data_out, p0_out, p1_out, p2_out, p3_out, data_out_uart, data_out_xram;
reg [7:0] p3_in;
reg wbi_err_i, wbd_err_i;
reg iack_i,dack_i;

reg ea;


例化设计模块3
oc8051_top oc8051_top_1(.wb_rst_i(rst), .wb_clk_i(clk),
         .int0_i(int0), .int1_i(int1),

          .wbd_err_i(wbd_err_i), .wbd_ack_i(dack_i),
         .wbd_cyc_o(cyc_o),

         .wbi_adr_o(iadr_o), .wbi_stb_o(istb_o), .wbi_ack_i(iack_i),
         .wbi_cyc_o(icyc_o), .wbi_dat_i(idat_i), .wbi_err_i(wbi_err_i),

  `ifdef OC8051_PORTS

   `ifdef OC8051_PORT0
         .p0_i(p0_in),
         .p0_o(p0_out),
   `endif

   `ifdef OC8051_PORT1
         .p1_i(p1_in),
         .p1_o(p1_out),
   `endif

   `ifdef OC8051_PORT2
         .p2_i(p2_in),
         .p2_o(p2_out),
   `endif

   `ifdef OC8051_PORT3
         .p3_i(p3_in),
         .p3_o(p3_out),
   `endif
  `endif


   `ifdef OC8051_UART
         .rxd_i(rxd), .txd_o(txd),
   `endif

   `ifdef OC8051_TC01
         .t0_i(t0), .t1_i(t1),
   `endif

   `ifdef OC8051_TC2
         .t2_i(t2), .t2ex_i(t2ex),
   `endif

         .ea_in(ea));

使用initial 或always 语句来产生激励波形4
        initial begin
  clk= 1'b0;
  rst= 1'b1;
  ea=1'b1;
  wbd_err_i=1'b0;
  dack_i=1'b0;
  iack_i=1'b0;
  wbi_err_i=8'h00;

#100
  rst = 1'b0;
#1200
  $finish;
end

always clk = #10 ~clk;


监控和比较输出响应5
initial $dumpvars;

//initial $monitor("time ",$time," rst ",rst, " int1 ", int1, " int2 ", int2, " int3 ", int3, " sw1 ", sw1, " sw2 ", sw2, " sw3 ", sw3, " sw4 ", sw4, " int act ", int_act, " p0_out %h", p0_out);

//initial $monitor("time ",$time," rst ",rst, " p1_out %h", p1_out);


endmodule

*********************************************************************

引用《DE2上使用OC8051运行点灯程序》,上面的测试代码定义了时钟周期是20ns,注意的是要给ack_i、iack_i、wbd_err_i、wbi_err_i赋初值,否则会导致时序仿真出现异常。

tb文件的最大难点,我感觉和其它的模块文件一致,大量的输入输出名称,如果对8051结构(输入输出和各种模块,笔记02的内容)不熟悉,真得是不能承受之重。
 楼主| 发表于 2014-1-14 07:21:15 | 显示全部楼层
****************************************************************

意外的仿真:MC8051


下载地址
MC8051IP核完整原代码及注释(VHDL).zip
****************************************************************

本来一直打算用oc8051做仿真的,但是看了几个版本,都需要做很多的改动。因为对其中的细节不详,所以感觉不踏实。

看了
开源MC8051 IP核在Modelsim下的调试仿真
后,
感觉很不错,过程如下:

*******************
一、编译hex文件
内容自定,比较简单,给端口赋值P0=11,P1=22,P2=33。

keil.gif

*********************
二、将hex文件转成dua文件,并将名字改为 mc8051_rom.dua (然后放到msim目录下)
利用hex2dua.exe工具,和hex文件放在同一目录下
Hex2Dua.rar (17.01 KB, 下载次数: 74 )

用法如下:
hex2dua.gif

05.JPG
***********************
三、打开modelsim,更改目录,在TransScript中输入:do mc8051_compile.do编译VHDL文件。
mc8051_compile.gif

***********************
四、在TransScript中输入:do mc8051_sim.do开始仿真调试。

mc8051_sim.gif

最后观察波形图,

06.JPG

已经赋值了。

************************************************************************

使用该MC8051仿真的好处是,目前可以避开内部实现的细节(比如实体设计和接口等),而来理解指令是如何实现的。
把这个仿真当作一个理解指令的工具。因为只需要在KEIL中更改指令(再做一遍步骤1到4),就会得到不同的波形图。

理解指令后再来理解内部实现细节。
 楼主| 发表于 2014-1-14 20:58:49 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-1-14 21:00 编辑

***************************************
利用上面的仿真方法 来学习一篇文章,可以理解指令执行过程。

《MC8051 IP 核简单指令的仿真步骤》,作者是老邹。
10.JPG
MC8051_IP核简单指令的仿真步骤.pdf (118.42 KB, 下载次数: 53 )

文章只有7页,分为四个部分:

1、仿真步骤;

    这里,可以利用上一页的方法。

2、仿真程序源码解析;

   hex文件是什么?dua文件是什么?原来很简单。

3、MC8051 IP Core 关于指令执行的关键代码分析;

   指令执行过程描述得比较清楚。

4、ModelSim 仿真具体问题的实现;

   利用波形图确认指令执行过程。这部分操作不够具体,花了我一些精力,主要是波形do文件的制作。

*****************************************

对我来说,最难的是第四部分,怎样仿真,看了一下modelsim的手册,1000多页的英文,翻了一下。更改方法了,直接查看mc8051_wave.do 文件。
用写字板打开,
内容类似:

onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider {TOP LEVEL INPUTS}
add wave -noupdate -format Logic /tb_mc8051_top/i_mc8051_top/clk
add wave -noupdate -format Logic /tb_mc8051_top/i_mc8051_top/reset
add wave -noupdate -format Literal /tb_mc8051_top/i_mc8051_top/int0_i
add wave -noupdate -format Literal /tb_mc8051_top/i_mc8051_top/int1_i
add wave -noupdate -format Literal /tb_mc8051_top/i_mc8051_top/all_t0_i
add wave -noupdate -format Literal /tb_mc8051_top/i_mc8051_top/all_t1_i
。。。。。
。。。。。
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2



因为该文章要利用,s_pc_inc_en,pc_o,s_help等波形,自带的do文件不含这些变量。
通过观察其它变量是如何加入波形文件的,
比葫芦画瓢,居然管用

看目录结构,
07.JPG

pc_o是 control_mem 模块下的一个变量,所以添加
add wave -noupdate -format Literal -radix hexadecimal /tb_mc8051_top/i_mc8051_top/i_mc8051_core/i_mc8051_control/i_control_mem/pc_o
就可以了,该命令具体含义不详,暂时绕开modelsim的学习(只用某些功能就可以了),否则负担太重。

添加变量如下,
08.JPG

执行do mc8051_sim.do 后,
波形图局部
09.JPG

对照第三部分,边理解过程说明边看波形图,效果应该很好。
更改后的do文件下载
mc8051_wave.rar (742 Bytes, 下载次数: 17 )
 楼主| 发表于 2014-1-15 21:01:37 | 显示全部楼层
现在可以研究一个指令MOV direct, #data是如何在mc8051中实现的了。

首先,编辑指令
mov 20h,#10h ;
end

编译后,再转成dua文件,改名mc8051_rom.dua,放在msim目录下

修改msim目录下的mc8051_wave.do文件,然后仿真。

13.JPG

可以看出,MOV direct, #data 对应的机器码 01110101

14.JPG

根据指令,设置状态,感觉不错。

然后,就是根据状态。。。

15.JPG

16.JPG

17.JPG

好像有点不完整。

再看波形图,变量都是并列出现的,不能直接从图中看出变量之间的赋值是怎样传递的(虽然赋值时间能看出),要是能有个变量之间关系的显示多好。
18.JPG
发表于 2014-1-16 18:20:04 | 显示全部楼层
回复 6# oldbeginner



    我提供一个当初学习oc8051时画的模块间连接关系图,仅供参考,希望对您有帮助。

oc8051模块连接图.rar (276.03 KB, 下载次数: 53 )
 楼主| 发表于 2014-1-16 22:12:30 | 显示全部楼层
 楼主| 发表于 2014-1-17 10:30:14 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-1-17 10:34 编辑

继续,
19.JPG

对MOV_D_DATA 指令过程 的解释
20.JPG

**********************************
再仿照上面

mov 20h,#10h ;将10H 送入空间地址20H 处
mov a,20h ;将地址20H 的值送入寄存器a
end

生成hex文件,然后转成mc8051_rom.dua 文件
01110101
00100000
00010000
11100101
00100000

然后再
do mc8051_compile.do
do mc8051_sim.do

观察波形图
21.JPG

核对指令执行时间
22.JPG

然后,检测其它指令,好像很枯燥。因为指令解释得并不透彻,没有深入到底层。

看了两篇论文(07年的,涉及mc8051),只看仿真部分,过程描述得不够清楚,为什么会这样也解释得不清楚。帮助不太大。

百度文库上可以找到
《基于8051单片机IP软核的优化设计及应用研究.pdf》
《基于VHDL语言的8051IP核的设计与验证研究.pdf》
***********************************

目前的困境是: 如何从上而下理解底层?
上层: modelsim对指令的仿真;
底层:各种模块的搭建。

缺少中间过渡,上层和下层是分开的,看了上面的两篇论文也没找到过渡方法。

既然从上而下,就要看一下MC8051结构,
23.JPG

红色虚线部分,表示上面简单分析过的两个模块: 寄存器单元模块 和 控制状态机模块。

看到这个结构图,感觉从上而下逐个模块学习还是有希望的。

*********************************

因为找到《计算机系统要素-从零开始构建现代计算机.pdf》
这本书的配套资源,感觉不错,可以同时从下向上学习。
XOR模块的仿真演示:
xor仿真.gif

************************************

c++仿真代码待继续研究,有进展会在这个帖子里更新。

这样,就可以进入下一步:从上而下(MC8051)和从下而上(The elements of computing systems)的同时学习。
 楼主| 发表于 2014-1-18 08:22:57 | 显示全部楼层
C++代码仿真有了进展,尝试移植到VC,还是比较顺利的,修改一些函数。

24.JPG

25.JPG

26.JPG

27.JPG

因为只是从上层的功能来移植,所以对8051是如何具体实现的,比如针对不同指令,ROM和RAM和PC是怎样变化的,还没有研究。

不过可以感觉到,这个仿真应该能够帮助理解MC8051是如何实现的。

VC工程文件
i8051.rar (18.93 KB, 下载次数: 19 )
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-23 01:50 , Processed in 0.024957 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表