[读书日志]8051软核处理器设计实战(基于FPGA)第七篇:8051软核处理器的测试(verilog+C)

embedded/2025/1/15 19:18:03/

6. 8051软核处理器的验证和使用

为了充分测试8051的性能,我们需要测试每一条指令。在HELLO文件夹中存放了整个测试的C语言工程文件。主函数存放在指令被分为五大类,和上面一样。

在这里插入图片描述

在这里插入图片描述

打开后是这样的文件结构。HELLO.c是主文件,这是里面的代码:

/*------------------------------------------------------------------------------
HELLO.CCopyright 1995-2005 Keil Software, Inc.
------------------------------------------------------------------------------*/#include <REG52.H>                /* special function register declarations   *//* for the intended 8051 derivative         */#include <stdio.h>                /* prototype declarations for I/O functions */#include "instruction.h"/*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void main (void) {test_status = 1;instruction_test_all();if (test_status) {printf("Test success!\n");}else{printf("Test failed!\n");}printf("Test finished!\n");kill_self = 1;while (1);
}

这里引用了头文件instruction.h,它的实现在Instruction文件夹中,先看一下instruction.c的内容:

#include <REG52.H>
#include <stdio.h> 
#include "instruction.h"void error(void){if (test_status==0) {printf("ERROR HERE...\n");while(1);}
}	void instruction_test_all(void){
#ifdef ARITHMETICarithmetic();  
#endif
#ifdef LOGICALlogical();
#endif
#ifdef TRANSFERtransfer();
#endif
#ifdef BOOLEANboolean();
#endif
#ifdef PROGRAMprogram();
#endif
}void arithmetic(void){
#ifdef ADD_A_RNadd_a_rn();
#endif
#ifdef ADD_A_DIadd_a_di();
#endif	
#ifdef ADD_A_RIadd_a_ri();
#endif		
#ifdef ADD_A_DAadd_a_da();
#endif
#ifdef ADDC_A_RNaddc_a_rn();
#endif	
#ifdef ADDC_A_DIaddc_a_di();
#endif		
#ifdef ADDC_A_RIaddc_a_ri();
#endif
#ifdef ADDC_A_DAaddc_a_da();
#endif
#ifdef SUBB_A_RNsubb_a_rn();
#endif
#ifdef SUBB_A_DIsubb_a_di();
#endif
#ifdef SUBB_A_RIsubb_a_ri();
#endif
#ifdef SUBB_A_DAsubb_a_da();
#endif
#ifdef INC_Ainc_a();
#endif
#ifdef INC_RNinc_rn();
#endif
#ifdef INC_DIinc_di();
#endif
#ifdef INC_RIinc_ri();
#endif
#ifdef INC_DPinc_dp();
#endif
#ifdef DEC_Adec_a();
#endif
#ifdef DEC_RNdec_rn();
#endif
#ifdef DEC_DIdec_di();
#endif
#ifdef DEC_RIdec_ri();
#endif
#ifdef MULTmult();
#endif
#ifdef DIVIDEdivide();
#endif
#ifdef DA_Ada_a();
#endif
}

这里只列出了一部分。可以看出通过预编译指令定义了五类指令及每一类的指令。而每一类中具体的指令通过汇编语言使用预编译指令进行编译。它们分布在剩余的几个c文件中。比如算术运算指令如下:

#include <REG52.H>
#include <stdio.h> 
#include "instruction.h"void add_a_rn(void) {printf("ADD_A_RN\n");#pragma ASM  push pswpush accmov  psw,#0H	setb rs0     setb rs1	#pragma ENDASM #pragma ASMmov acc,#01Hmov R0,#0fHadd A,R0#pragma ENDASM	if (ACC!=0x10) test_status = 0;if (AC!=1) test_status = 0;if (OV!=0) test_status = 0;if (CY!=0) test_status = 0;AC = 0;#pragma ASMmov acc,#40Hmov R1,#40Hadd A,R1#pragma ENDASMif (ACC!=0x80) test_status = 0;if (AC!=0) test_status = 0;if (OV!=1) test_status = 0;if (CY!=0) test_status = 0;OV = 0;#pragma ASMmov acc,#80Hmov R2,#81Hadd A,R2#pragma ENDASMif (ACC!=0x01) test_status = 0;if (AC!=0) test_status = 0;if (OV!=1) test_status = 0;if (CY!=1) test_status = 0;OV = 0;CY = 0;#pragma ASMmov acc,#0C0Hmov R3,#0C2Hadd A,R3#pragma ENDASMif (ACC!=0x82) test_status = 0;if (AC!=0) test_status = 0;if (OV!=0) test_status = 0;if (CY!=1) test_status = 0;CY = 0;	#pragma ASM pop accpop psw	#pragma ENDASM 	error();
}

如果每一条指令都通过,最后会打印测试成功字样,如果有任何一条指令执行有误则会导致抛出错误和暂停测试。

将HELLO工程编译后生成了HELLO.bin,这就是我们最后需要使用的文件,将其留存。之后编写一个tb文件,用于对接接口和设置存储空间:

`timescale 1 ns/1 ps
`define PERIOD 10
`define HALF_PERIOD (`PERIOD/2)
//`define TYPE8052
`define CODE_FILE "C:/Users/15661/Desktop/R8051_test/HELLO/HELLO.bin"
module tb;reg     clk = 1'b0;
always #`HALF_PERIOD clk = ~clk;reg     rst = 1'b1;
initial #`PERIOD rst = 1'b0;wire            rom_en;
wire [15:0]     rom_addr;
reg  [7:0]      rom_byte;
reg             rom_vld;wire            ram_rd_en_data;
wire            ram_rd_en_sfr;
wire            ram_rd_en_xdata;
wire [15:0]     ram_rd_addr;reg  [7:0]      ram_rd_byte;wire            ram_wr_en_data;
wire            ram_wr_en_sfr;
wire            ram_wr_en_xdata;
wire [15:0]     ram_wr_addr;
wire [7:0]      ram_wr_byte;r8051 u_cpu (.clk                  (    clk              ),.rst                  (    rst              ),.cpu_en               (    1'b1             ),.cpu_restart          (    1'b0             ),.rom_en               (    rom_en           ),.rom_addr             (    rom_addr         ),.rom_byte             (    rom_byte         ),.rom_vld              (    rom_vld          ),.ram_rd_en_data       (    ram_rd_en_data   ),.ram_rd_en_sfr        (    ram_rd_en_sfr    ),.ram_rd_en_xdata      (    ram_rd_en_xdata  ),.ram_rd_addr          (    ram_rd_addr      ),.ram_rd_byte          (    ram_rd_byte      ),.ram_rd_vld           (    1'b1             ),.ram_wr_en_data       (    ram_wr_en_data   ),.ram_wr_en_sfr        (    ram_wr_en_sfr    ),.ram_wr_en_xdata      (    ram_wr_en_xdata  ),.ram_wr_addr          (    ram_wr_addr      ),.ram_wr_byte          (    ram_wr_byte      ));reg [7:0] rom[(1'b1<<16)-1:0];integer fd,fx;
initial beginfd = $fopen(`CODE_FILE,"rb");fx = $fread(rom,fd);$fclose(fd);
endalways @ ( posedge clk )
if ( rom_en )rom_byte <=  rom[rom_addr];
else;always @ ( posedge clk )
rom_vld <=  rom_en;reg [7:0] data [127:0];
reg [7:0] data_rd_byte;
always @ ( posedge clk )
if ( ram_rd_en_data )data_rd_byte <=  data[ram_rd_addr[6:0]];
else;always @ ( posedge clk )
if ( ram_wr_en_data )data[ram_wr_addr[6:0]] <=  ram_wr_byte;
else;reg [7:0] xdata [127:0];
reg [7:0] xdata_rd_byte;
always @ ( posedge clk )
if ( ram_rd_en_xdata )xdata_rd_byte <=  xdata[ram_rd_addr[6:0]];
else;always @ ( posedge clk )
if ( ram_wr_en_xdata )if (( ram_wr_addr[6:0]==8'h7f ) & ram_wr_byte[0] ) beginrepeat(1000) @ (posedge clk);$display("Test over, simulation is OK!");$stop(1);endelsexdata[ram_wr_addr[6:0]] <=  ram_wr_byte;
else;reg [7:0] sfr_rd_byte;always @ ( posedge clk )
if ( ram_wr_en_sfr & ( ram_wr_addr[7:0]==8'h99 ) )$write("%s",ram_wr_byte);
else;always @ ( posedge clk )
if ( ram_rd_en_sfr ) if ( ram_rd_addr[7:0]==8'h98 )sfr_rd_byte <=  8'h3;else if ( ram_rd_addr[7:0]==8'h99 )sfr_rd_byte <=  0;elsebegin$display($time," ns : --- SFR READ: %2h---",ram_rd_addr[7:0]);//$stop;end
else;	always @ ( posedge clk )
if ( ram_wr_en_sfr )if(( ram_wr_addr[7:0]==8'h98 )|( ram_wr_addr[7:0]==8'h99 ))#0;else	begin$display($time," ns : --- SFR WRITE: %2h -> %2h---",ram_wr_addr[7:0],ram_wr_byte);//$stop;end
else;	reg [1:0] read_flag;
always @ ( posedge clk )
if ( ram_rd_en_sfr )read_flag <= 2'b10;
else if ( ram_rd_en_xdata )read_flag <= 2'b01;	
else if ( ram_rd_en_data )read_flag <= 2'b0;
else;always @*
if ( read_flag[1] )ram_rd_byte = sfr_rd_byte;
else if ( read_flag[0] )ram_rd_byte = xdata_rd_byte;
elseram_rd_byte = data_rd_byte;endmodule

将tb.v和R8051.v一起加入Modelsim工程(注意不要导入instruction.v,否则会报错,需要更改的有两处路径,分别是tb中引用HELLO.bin的路径,和R8051.v中对instruction.v引用的路径,更改后即可复现代码。)之后进行仿真,结果正确。

在这里插入图片描述

在这里插入图片描述

至此,我们的8051软核处理器开发基本完毕。之后可以自行修改一些功能,使用这套测试框架进行测试。现在这个软核处理器中没有添加中断,在书中并没有提供添加中断的说明。后续如果有机会将继续更新添加中断的内容。


http://www.ppmy.cn/embedded/154170.html

相关文章

【系统安全】CVE-2024-49113 Windows轻量级目录访问协议(LDAP)拒绝服务漏洞

文章目录 免责声明一、漏洞描述二、漏洞成因三、漏洞危害四、影响版本五、攻击流程六、修复方案 免责声明 在网络安全领域&#xff0c;技术文章应谨慎使用&#xff0c;遵守法律法规&#xff0c;严禁非法网络活动。未经授权&#xff0c;不得利用文中信息进行入侵&#xff0c;造…

使用Python和Neo4j驱动程序来实现小规模数据的CSV导入

要将CSV数据导入到Neo4j数据库中&#xff0c;你可以使用Neo4j提供的工具&#xff0c;比如neo4j-admin import命令&#xff08;适用于大规模数据导入&#xff09;&#xff0c;或者使用Python的Neo4j驱动程序通过Cypher查询逐行插入数据&#xff08;适用于小规模数据导入&#xf…

Bevy 移动端开发指南

Bevy 移动端开发指南 Bevy 确实支持 iOS 和 Android 平台开发&#xff0c;但需要特定的配置和工具链。本指南将详细介绍如何在移动平台上开发 Bevy 游戏。 支持状态 ✅ iOS: 完全支持✅ Android: 完全支持⚠️ 注意&#xff1a;需要额外配置和工具链 环境准备 Android 开发…

OpenGL学习笔记(四):Shader 着色器(GLSL、Shader类封装)

文章目录 GLSL数据类型输入与输出Uniform的使用Shader类封装练习0练习1练习2练习3 前面的文章提到&#xff0c;着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分运行。从本质上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是…

2025封禁指定国家ip-安装xtables-addons记录

如何安装和使用 安装lux仓库(该仓库包含xtables-addons所需的依赖环境) # wget http://repo.iotti.biz/CentOS/7/noarch/lux-release-7-1.noarch.rpm # rpm -ivh lux-release-7-1.noarch.rpm 安装xtables-addons。注意&#xff1a;必须先安装kmod-xtables-addons&#xff0c;再…

win下虚拟机安装选项补充

一、将WSL移动出C盘 二&#xff1a;WSL额外设置 三、WslRegisterDistribution 错误 0x80071772 的解决方案 当遇到 WslRegisterDistribution 错误码 0x80071772 时&#xff0c;这通常意味着 WSL 尝试安装到非默认磁盘分区上。此错误主要发生在尝试将 WSL 安装至除 C 盘外的位置…

【搭建JavaEE】(1)maven仓库安装配置

Maven项目 maven–管理类的 Apache Maven 是一种软件项目管理和理解工具。基于项目对象模型的概念 &#xff08;POM&#xff09; 的 Mvc 文件&#xff0c;Maven 可以从一个中心信息中管理项目的构建、报告和文档。 maven VS npm 依赖(dependencies) 项目中需要的对象&#x…

力扣 子集

回溯基础&#xff0c;一题多解&#xff0c;不同的回朔过程。 题目 求子集中&#xff0c;数组的每种元素有选与不选两种状态。因此在使用dfs与回溯时把每一个元素分别进行选与不选的情况考虑即可。可以先用dfs跳过当前元素即不选然后一直深层挖下去&#xff0c;直到挖到最深了即…