清霜一梦

基于FPGA的DW8051移植(一)

0
阅读(1533)

最近 半个月都在移植8051,看到DW8051内核资料比较齐全又是新思发布的,所以就开始玩弄

  可是这半个月的努力几近白费 —— 移植失败了,不知道从何着手这个内核。可能大家能找到不同的版本,我的是最初的版本,里面包含了datasheet 以及一些说明文档,看上去貌似是最原始的(可能已经修改过了),本想传上来,但是我一直到偶没有找到哪里可以上传文件。

  我没有添加片外memory,只有片内64k的rom 和256k的ram

 

  首先来看看我的tb

复制代码

  1 `timescale 1us/100ns 
  2   3 module dw8051_tb ; 
  4   5 reg         clk ,            reset ;  6 reg         int0_n,        int1_n ; 
  7 reg      rxd0_in ,   rxd1_in ; 
  8 reg      t0 ,        t1     ;  9  10 wire         rst_out_n ; 11 wire         stop_mode_n,   idle_mode_n ; 
 12 wire     rxd0_out ,     txd0    ; 13 wire     rxd1_out ,     txd1    ; 14 wire     t0_out  ,      t1_out  ; 15  16 integer i ; 
 17  18 DW8051_top  cpu_core( 19  20              .clk (clk)         , 
 21              .reset (reset)       , 22              .rst_out_n (rst_out_n)    ,           
 23              .stop_mode_n (stop_mode_n) , 
 24              .idle_mode_n (idle_mode_n) ,         
 25                           26            //int 27              .int0_n (int0_n)      , 
 28              .int1_n (int1_n)      , 
 29             30            //serial port 31              .rxd0_in (rxd0_in)     , 
 32              .rxd0_out (rxd0_out)    , 
 33              .txd0 (txd0)        , 
 34                           35              .rxd1_in (rxd1_in)      , 
 36              .rxd1_out (rxd1_out)    , 
 37              .txd1 (txd1)        , 
 38             39            //timer/counter input/output 40              .t0 (t0)          , 
 41              .t1 (t1)          , 
 42              .t0_out (t0_out)       , 
 43              .t1_out (t1_out)      , 
 44                           45  46        //sfr interface 47                .sfr_data_in () , 
 48              .sfr_addr ()    , 
 49              .sfr_data_out () , 
 50              .sfr_wr ()      , 
 51              .sfr_rd ()      , 52             53            //external ram interface or user-defined peripheral reg 54                .mem_data_in () , 
 55              .mem_addr ()    , 
 56              .mem_data_out (), 
 57              .mem_wr_n ()     , 
 58              .mem_rd_n () 59             );    
 60  61 always #10 clk = ~clk ; 
 62                              63 initial   begin  64     i = 0  ; 65     clk = 0 ;     reset =0 ; 
 66     int0_n=0 ;    int1_n=0 ; 67     rxd0_in=0 ;   rxd1_in=0 ; 68     t0 =  0  ;    t1  = 0   ; 69     #180 reset =1 ; 
 70      71      72      73 //**********测试1 : 发现无论如何修改idata初始化空间大小,程序都会进入29-2a-2b-2c 这个循环,无法跳出 74     // while (i<8'hff) begin 
 75             // @(cpu_core.irom_addr == 16'h0029)   i = i+1 ; 
 76             // if (i>8'h7f) begin 
 77                     // $display ("rom loop at 0029 is over 7f time "); 78                     // $display ("  i = %d \n", i ); 79                     // end 
 80             // end 
 81 //---------------------------------------------------------------------------------------             82  83 /**********测试2: 依据测试1追查27这个地址上的循环次数数值去了哪里 84     1,@(cpu_core.core.irom_addr == 16'h0027) 测试发现跑到最后一个displays里面去了 ,屏蔽掉所有的if 85 打印具体数据信息结果显示 cpu_core.core.i_cpu.biu_instr == 8'h78 86 而cpu_core.core.i_cpu.biu_data_in == 8'h00 87     2,@(cpu_core.core.irom_addr == 16'h0028) 测试发现cpu_core.core.i_cpu.biu_instr == 8'h3f而 88 cpu_core.core.i_cpu.biu_data_in == 8'h00。由1和2对比可知数据有一个周期的停滞期 89 */ 90 //@(cpu_core.core.irom_addr == 16'h0028) begin 
 91 //        //if (cpu_core.core.int_rom_data_out == 8'h3f) begin 
 92 //                //if (cpu_core.core.i_cpu.biu_instr == 8'h3f) 93 //                        $display ("the rom data 3f have get to biu_instr = %h  \n ",cpu_core.core.i_cpu.biu_instr ); 94 //                //if (cpu_core.core.i_cpu.biu_data_in == 8'h3f) 95 //                        $display ("the rom data 3f have get to biu_data_in  = %h\n", cpu_core.core.i_cpu.biu_data_in); 96 //                end 
 97 //        else  begin 
 98 //                $display ("operation error ! rom data 3f at address 27 have not load in "); 99 //                end 
100 //                end 101 102 /********测试3 依据测试2追查内核执行情况 
103 104 105 */106 $display ("display  data  :  \n");107 $monitor ("%h",cpu_core.core.i_cpu.i_opdec.op);108 #8000 $stop ; 
109 110 111 112 113     @(cpu_core.irom_addr == 16'h0019)114     #80000  $stop ; 
115 116 117 118 119 end 120 121 endmodule

复制代码

  最后的一个stop 是始终执行不到那里去,也就是说代码根本没有执行到程序存储地址19这里来。

  当然需要解释一下我为什么要这么测试,不懂为什么tb这么写,可以先忽略掉。我们一步步来追究,首先看看我的c程序

复制代码

 1 #include <reg51.h> 2 #define uchar unsigned char 
 3 #define uint unsigned int 
 4  5 sbit LED = P0^0 ; 
 6  7 void DelayMS (uint x ) 8 { 9     uchar i ; 
10     while (x--);11     {12         for (i=0;i<2;i++) ;13         14     }15 }16 17 void main ()18 {19    LED = 1 ; 
20    while (1) 
21     {22      23         DelayMS(5);24         LED=~LED ;25     }26 }

复制代码

 

调试窗口中显示我的程序起始地址是19,也就是说如果执行我的main函数要从19这个地址作为入口进行执行。在后面的step按钮下一步步调试发现,我的子函数起始地址是 03 。整个用户程序的起始地址是03,终止地址是25.

下面来看看keilC输出的hex

:03000000020026D5
:0C002600783FE4F6D8FD75810702001950
:10000300EF1FAA0670011E4A600BE4FDEDC39402C4
:0500130050EE0D80F726
:0100180022C5
:0D001900D2807F057E00120003B28080F5CA
:00000001FF

依据我查到的资料上说: 03000000020026D5

03 代码数据数目  0000 代表存储地址,00代表数据类型   020026代表数据  D5代表校验码

依据上述的意思去查QuartusII里面的信息

经过对比发现两者是一致的,说明QuartusII 对hex档的读取是没有问题的(当然我的C程序也是调试过没有问题的)

下面让我们看看modelsim仿真出来的结果

modelsim中仿真可以看到,程序执行地址 00- 01 - 02- 26 -27 - 28 - 29 - 2a - 2b - 2c - 29........然后就是这个循环一直都没有退出,也就是说根本没有执行用户程序。

  继续追踪这个程序段

reset之后一切明白了,程序从00地址开始执行 转跳到地址26——记住用户程序是从03到25,所以这个时候执行的是startup程序段,现在追踪startup,这个startup.a51是每个单片机上电的时候都需要进行执行的代码段,也就是初始化单片机的程序(具体的操作大家自己找资料看,网上很多人对这个文件有了中文的解析,比如这位大虾的http://www.cnblogs.com/heiyue/p/3262389.html

在调试中发现

 

 立即数3f给了r0 ,也就是地址段27这个地方的数据,它表示的是我的ram的大小(startup.a51里面默认的是80编译出来是7f,改成40编译出来是3f),也就是我的初始化执行这个loop的次数。

好,现在可以解释一下为什么有了我的程序中的测试1

依据程序中规定的,这个loop应该是执行3f次—— 我也可以把这个loop直接停止掉,不用去初始化我的ram。因为我不管怎么修改这个loop都跳转不出来,所以我就开始追踪 3f去哪里了,所以才有了测试2

测试2发现这个3f居然进了decode模块的op端口(biu_instr和op相连),为了证实所以有了测试3

 

 3f居然进了decode模块当操作码(op)处理了,它应该是一个立即数才对啊、再进入decode模块证实是否真的当操作码处理了,当我进入decode模块的时候发现真的悲剧了,没有使能信号控制,3f直接进入了操作码的case语句。

初步认定核有问题

在我写这个博客的时候觉得还有一丝希望的是,这个3f虽然当做操作码处理了,loop里面的所有数据都当操作码处理了,但是没有初始化完成,最后有一个使能把执行结果屏蔽了,—— 后待验证