**这是本文档旧的修订版!**

OC8051

我们以开源IP分享网站 opencores.org 上面的一款开源8051核-oc8051为基础,介绍8051的结构、工作原理、硬件描述的实现及在FPGA上的仿真、移植过程。
oc8051下载地址:https://opencores.org/project/8051

1.关于OC8051

oc8051与8051微控制器是兼容的。所谓兼容性是指oc8051使用相同的指令集。实现起来当然各有差异。 首先,最重要的区别是有两个阶段的流水线操作。在第一周期指令及其操作数被取出和解码时,第二周期用于计算结果并将其写入存储器。我们通过额外的寄存器来实现这一点,其唯一的任务是将信号延迟一个时钟周期。这是必须的,因为我们的想法是我们已经在第一个周期中设置了所有控制信号,然后将一个不需要的控制信号(例如,保存结果的地址)延迟一个周期。 因为我们可能还需要指令的第二个和第三个字节,所以我们使用24位宽总线的程序ROM。由于处理器设计的需要,我们还使用能够同时写入和读取的内部存储器。 其中一个重要方面是总线控制,由主模块(oc8051decoder)处理。我们通过控制信号来实现这一点,控制信号连接到在每个总线开始时设置的多路复用器。有了多路复用器,我们设置了谁控制总线 ===1.1 oc8051文件组织目录=== * oc8051 * asm 软件相关文件 * hex * in * v * vec * bench 仿真相关文件 * verilog * doc 说明文档 * pdf * src * rtl verilg代码 * verilog * sim RTL仿真文件 * rtlsim

  • sw ROM生成工具
    • source
  • syn 工程文件
    • src

1.2 oc8051的接口


2.模块描述

2.1.oc8051_top

Ports:

  • -rst reset
  • -clk clock
  • -romaddr Program Memory address * -romdata Program Memory data
  • -ea external access: is used when the external memory is accesed
  • -int0 external interrupt 0
  • -int1 external interrupt 1
  • -dati input for external Data Memory * -dato output for external Data Memory
  • -adro external Data Memory address * -weo writing to external Data Memory
  • -stbo strobe * -acki acknowlage
  • -cyco cycle * -p0in, p1in, p2in, p3in port inputs * -p0out, p1out, p2out, p3out port outputs * -op1, op2, op3 inputs from external Program Memory (3x 8 bitov) * -rxd receive * -txd transmit * -t0, t1 t/c external inputs ===2.2.oc8051decoder===

oc8051decoder是主要模块。 该模块从程序存储器中获取操作代码,然后设置控制信号。
模块有两个内部信号。
首先是两位宽的信号-state。 该信号显然保存有关状态的信息,即流水线的状态。 该信号的典型值为b00。 仅当流水线中的指令执行被阻塞时(遇到jumps),才会更改此值。
第二个内部信号是op,这是寄存器,我们在其中保存操作代码,并且当指令执行需要多于一个时钟周期时,op才会被用到。
这个模块由5个‘always’块组成:
* 第一个利用'case'判断流水线状态,通过状态state和操作码op设置控制信号。 * 第二个是用来记住操作码。 * 第三个是设置信号state到期望值。 * 第四个关注输出信号中断返回指令 * 第五个用来产生信号write
x 输入输出信号
- clk (in) clock
- rst (in) reset
- opin (in) 操作码, 由memoryinterface得到,[oc8051opselect.op1]
- eq (in) 比较结果 [oc8051comp.eq]
- ram
rdsel (out) 选择信号, 读ram地址选择 [oc8051ramrdsel.sel, oc8051sp.ramrdsel]
- ram
wrsel (out) 选择信号,写ram地址选择 [oc8051ramwrsel.sel -r, oc8051sp.ramwrsel -r]
- wr (out) 读写位1表示写,0表示读[oc8051
ramtop.wr -r, oc8051acc.wr -r, oc8051bregister.wr -r, oc8051sp.wr-r, oc8051dptr.wr -r, oc8051psw.wr -r,oc8051indiaddr.wr -r, oc8051ports.wr -r]
- srcsel1 (out) 选择alu 资源1 [oc8051alusrc1sel.sel -r]
- srcsel2 (out) 选择alu 资源 2 [oc8051alusrc2sel.sel -r]
- srcsel3 (out) 选择alu 资源 3 [oc8051alusrc3sel.sel -r]
- aluop (out) alu 操作[oc8051alu.opcode -r]
- psw
set (out) 定义在PSW寄存器中设置哪个标志 cy, ac, ov from alu [oc8051psw.set -r]
- cy
sel (out) alu中进位选择信号 [oc8051cyselect.cysel -r]
- comp
sel (out) 比较内容选择 [oc8051comp.sel]
- bit
addr (out) 位寻址 [oc8051ramtop.bitaddr -r, oc8051acc.wrbit -r, oc8051bregister.wrbit-r, oc8051sp.wrbit -r, oc8051dptr.wrbit -r, oc8051psw.wrbit -r, oc8051indiaddr.wrbit -r, oc8051ports.wrbit -r]
- pc
wr (out) pc 写 [oc8051pc.wr]
- pc
sel (out) pc 选择[oc8051pc.pcwrsel]
- rd (out) rom 中读[oc8051
pc.rd, oc8051opselect.rd]
- reti (out) 中断返回 [pin]
- rmw (out) 读-修改-写 指令时有效[oc8051ports.rmw]
- pc
wait (out)

2.3.oc8051_alu

模块oc8051alu表示用于算术和逻辑运算的组合逻辑。
模块有3个8位输入操作数(第三个操作数用于计算PC或DPTR的地址)和3个输入信号。 这三个信号分别是进位,辅助进位和用于位寻址指令的信号。还有四位宽的操作码输入。
操作指令:
* OC8051
ALUNOP – 空操作 * OC8051ALUADD - 加 * OC8051ALUSUB - 减 * OC8051ALUMUL - 乘 * OC8051ALUDIV - 除 * OC8051ALUDA – 十进制调整 * OC8051ALUNOT – 取反, 按位取反 * OC8051ALUAND – 与, 按位与 * OC8051ALUXOR – 异或 * OC8051ALUOR - 或 * OC8051ALURL – 循环左移 * OC8051ALURLC – 带进位的循环左移 * OC8051ALURR – 循环右移 * OC8051ALURRC – 带进位的循环右移 * OC8051ALUPCS – 添加16位无符号数和8位有符号数 * OC8051ALUXCH – 交换,第一个输入传输到第二个输出,反之亦然。 如果设置了进位,则只更改字节的最低半部分 运算码在文件oc8051defines.v中。输出是2个八位宽结果,还有进位,辅助进位和溢出。乘法和除法子模块分别定义在oc8051multiply 和 oc8051divide 中。它俩都有八位宽的输入总线和2个八位宽输出总线,1个总线输出结果,另一个总线输出进位标志。

2.4.oc8051_pc

模块oc8051pc实际上是一个程序计数器。 它计算下一条指令的地址值。模块中的输入是操作码,我们用它来计算地址的值。 还有一些输入用于跳转(op2和op3用于绝对跳转,alu输入用于相对寻址),还有用于选择新pc源的信号(pcwrsel)和输入新地址的信号(wr)。 模块的唯一输出是程序计数器的16位宽的当前值。 ===2.5.oc8051rom=== 该模块包含了程序存储器。 程序存储器取决于我们的实现方式。
模块中的输入是16位地址。 输出是三个8位数据总线和eaint信号。 输入地址来自数据的第一个字节(data1),第二个和第三个字节(data2,data3)位于以下地址。 这是流水线不间断运行的必备条件。Eaint信号等于外部ea信号,如果所使用的地址对于内部程序存储器来说太大了,那么就需要使能该信号,来访问外部程序存储器。

2.6.oc8051_comp

模块oc8051comp的功能是比较两个输入并在输入相同时设置输出。 在条件跳转时,计算条件需要该模块。
比较输入有不同的选项:
- ACC对0
- 算术运算的结果对0
- 进位
- 位进位(来自存储器)
这些选项足以满足8051中的所有条件跳转。输出连接到oc8051
decoder的输入,在需要时传输到pcwr。
===2.7.oc8051
opselect=== 所有来自程序存储器的数据都要经过该模块。它有三项任务。
第一项任务是选择使用哪种内存,内部或外部。这项任务有点像多路复用器:它具有用于输入的ea和ea
int信号(当这两个信号任意一个低电位时,将是外部空间的读周期)和输出。
该模块的第二个任务是接收中断。为此,除了3个8位输入之外,该模块还具有两个用于接收中断的输入信号。这些是信号int和8位的intv。如果设置了int信号,我们有一个中断,在8位总线上,我们接收到中断程序的地址(高8位为零)。在中断时,检查当前正在执行的指令是否大于一个时钟周期(输入信号rd),然后将LCALL操作码发送到第一个输出。随后发送中断程序其他两个输出的地址。
该模块的最后一个任务是检查操作码并发送存储器地址,以便将结果写入输出中。这与需要DPTR用于计算结果的指令和使用B寄存器的指令一起使用。使用此选项可以实现以后的立即寻址模式。必须要小心啦,因为第二个操作数有两个不同输出,一个用于ALU中的立即操作数,另一个用于直接寻址。
===2.8.oc8051
regX=== oc8051regX模块代表X位寄存器,其功能仅在于将信号延迟一个时钟周期。 除了时钟和复位输入外,它们还具有数据输入和输出。 ====3.数据存储器和特殊功能寄存器(SFR)==== 下面的模块包括两部分, * 数据存储器和特殊功能寄存器模块 * 多路复用器模块 这部分的模块都包含数据,这些模块共享同样的地址空间,因此他们有一些共同的输入信号:
这些信号有:
- clk clock,时钟信号
- rst reset. Reset values are written oc8051
defines.v file. 复位信号
- wr writing 写操作信号
- wraddr address to where data is written 写地址信号
- data
in input data 输入数据
- wrbit defines if the instruction is bit addressable 如果指令可操作位地址,则有该信号
- bit
in bit input (for use only with bit addressable instructions and Data Memory) 位输入 (只用在位操作指令和位操作数据空间)
在下列情况下,特殊寄存器每时钟周期都要被检查:
1、如果有写周期(wr信号);
2、如果位操作;
3、如果地址匹配要写入寄存器的数据。
地址可以不同,以便处理位操作指令或字节操作指令。物理地址定义在oc8051defines.v文件中。
除了输入空间外,还有数据地址输入空间和数据输出空间。
===3.1 oc8051
ram_top===


===参考来源===:
opencores的设计文档 < oc8051_design >
李全利老师主编的《单片机原理及接口技术》
网友oldbeginner的开源软核学习笔记:http://xilinx.eetop.cn/space.php?uid=1214938&op=bbs
网友leishangwen的《DE2上使用OC8051运行点灯程序》:
https://download.csdn.net/download/leishangwen/5173363
由于水平所限,难免有不对之处,欢迎指正。