每个外设都是通过读写其寄存器来控制的。外设寄存器也称为I/O端口,通常包括:控制寄存器、状态寄存器和数据寄存器三大类。根据访问外设寄存器的不同方式,可以把CPU分成两大类。一类CPU(如ARM,MIPS,M68K,Power PC等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令。这就是所谓的“I/O内存”方式。另一类CPU(典型的如X86),将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这些寄存器,而要为对外设寄存器的读/写设置专用指令,如IN和OUT指令。这就是所谓的“ I/O端口”方式。

下面以X86的一种实现为例,该项目链接为http://zet.aluzina.org/index.php/Zet_processor。这个CPU的接口如下:

`include "defines.v"module zet_core (input clk,input rst,// interruptsinput  intr,output inta,input  nmi,output nmia,// interfaceoutput [19:0] cpu_adr_o,input  [15:0] iid_dat_i,input  [15:0] cpu_dat_i,output [15:0] cpu_dat_o,output        cpu_byte_o,input         cpu_block,output        cpu_mem_op,output        cpu_m_io,output        cpu_we_o,output [19:0] pc  // for debugging purposes);

从上面总线接口的定义中我们可以看到,该CPU具有独立的IO总线,总线信号如 data_in,data_out,adr_out,we等都是共用的,也就是MEM总线与IO总线复用这些信号,通过cpu_m_io来区分当前的总线操作是IO还是MEM,实际上是分时复用的。当然也可以完全复用,就是各自有独立的总线信号,这个项目实现了兼容传统8086的架构,所以是复用的。

module zet_exec (input         clk,input         rst,input [`IR_SIZE-1:0] ir,input [15:0]  off,input [15:0]  imm,output [15:0] cs,output [15:0] ip,output        of,output        zf,output        cx_zero,input [15:0]  memout,output [15:0] wr_data,output [19:0] addr,output        we,output        m_io,output        byteop,input         block,output        div_exc,input         wrip0,output        ifl,output        tfl,output        wr_ss);// Net declarationswire [15:0] c;wire [15:0] omemalu;wire [ 3:0] addr_a;wire [ 3:0] addr_c;wire [ 3:0] addr_d;wire [ 8:0] flags;wire [15:0] a, b, s, alu_iflags, bus_b;wire [31:0] aluout;wire [3:0]  addr_b;wire [2:0]  t, func;wire [1:0]  addr_s;wire        wrfl, high, memalu, r_byte, c_byte;wire        wr, wr_reg;wire        wr_cnd;wire        jmp;wire        b_imm;wire  [8:0] iflags, oflags;wire  [4:0] logic_flags;wire        alu_word;wire        a_byte;wire        b_byte;wire        wr_high;wire        dive;// Module instances
  zet_alu alu( {c, a }, bus_b, aluout, t, func, alu_iflags, oflags,alu_word, s, off, clk, dive);zet_regfile regfile (a, b, c, cs, ip, {aluout[31:16], omemalu}, s, flags, wr_reg, wrfl,wr_high, clk, rst, addr_a, addr_b, addr_c, addr_d, addr_s, iflags,~byteop, a_byte, b_byte, c_byte, cx_zero, wrip0);zet_jmp_cond jmp_cond (logic_flags, addr_b, addr_c[0], c, jmp);// Assignmentsassign addr_s = ir[1:0];assign addr_a = ir[5:2];assign addr_b = ir[9:6];assign addr_c = ir[13:10];assign addr_d = ir[17:14];assign wrfl   = ir[18];assign we     = ir[19];assign wr     = ir[20];assign wr_cnd = ir[21];assign high   = ir[22];assign t      = ir[25:23];assign func   = ir[28:26];assign byteop = ir[29];assign memalu = ir[30];assign m_io   = ir[32];assign b_imm  = ir[33];assign r_byte = ir[34];assign c_byte = ir[35];assign omemalu = memalu ? aluout[15:0] : memout;assign bus_b   = b_imm ? imm : b;assign addr = aluout[19:0];assign wr_data = c;assign wr_reg  = (wr | (jmp & wr_cnd)) && !block && !div_exc;assign wr_high = high && !block && !div_exc;assign of  = flags[8];assign ifl = flags[6];assign tfl = flags[5];assign zf  = flags[3];assign iflags = oflags;assign alu_iflags = { 4'b1111, flags[8:3], 1'b0, flags[2], 1'b0, flags[1],1'b1, flags[0] };assign logic_flags = { flags[8], flags[4], flags[3], flags[1], flags[0] };assign alu_word = (t==3'b011) ? ~r_byte : ~byteop;assign a_byte = (t==3'b011 && func[1]) ? 1'b0 : r_byte;assign b_byte = r_byte;assign div_exc = dive && wr;assign wr_ss = (addr_d == 4'b1010) && wr;endmodule

这部分代码可以看出,addr的计算来源只有一个,也就是他并不区分指令地址和数据地址,因此是冯诺依曼结构的处理器。

下面以OpenRISC无MMU和浮点运算单元的精简版本AltOR32处理器来说明统一编址的CPU总线接口形式。

(1)冯诺依曼结构,读取数据的接口和读取指令的接口在一起的,代码如下:

module altor32_lite
(// Generalinput               clk_i /*verilator public*/,input               rst_i /*verilator public*/,// Maskable interrupt    input               intr_i /*verilator public*/,// Unmaskable interruptinput               nmi_i /*verilator public*/,// Memory interfaceoutput reg [31:0]   mem_addr_o /*verilator public*/,input [31:0]        mem_dat_i /*verilator public*/,output reg [31:0]   mem_dat_o /*verilator public*/,output reg          mem_cyc_o /*verilator public*/,output reg          mem_stb_o /*verilator public*/,output reg          mem_we_o /*verilator public*/,output reg [3:0]    mem_sel_o /*verilator public*/,input               mem_ack_i/*verilator public*/
);
.
.
.
.
//-----------------------------------------------------------------
// Next State Logic
//-----------------------------------------------------------------
reg [3:0] next_state_r;
always @ *
beginnext_state_r = state_q;case (state_q)    //-----------------------------------------// IDLE - //-----------------------------------------
    STATE_IDLE :beginif (enable_i)next_state_r    = STATE_FETCH;end    //-----------------------------------------// FETCH - Fetch line from memory//-----------------------------------------
    STATE_FETCH :beginnext_state_r    = STATE_FETCH_WAIT;end//-----------------------------------------// FETCH_WAIT - Wait for read responses//-----------------------------------------
    STATE_FETCH_WAIT:begin// Read from memory completeif (mem_ack_i)next_state_r = STATE_EXEC;end  //-----------------------------------------// EXEC//-----------------------------------------
    STATE_EXEC :beginif (load_inst_r || store_inst_r)next_state_r    = STATE_MEM;elsenext_state_r    = STATE_WRITE_BACK;end//-----------------------------------------// MEM//-----------------------------------------
    STATE_MEM :begin// Read from memory completeif (mem_ack_i)next_state_r = STATE_FETCH;end    //-----------------------------------------// WRITE_BACK//-----------------------------------------
    STATE_WRITE_BACK :beginif (enable_i)next_state_r    = STATE_FETCH;end    default:;endcase
end
.
.
.
.
//-----------------------------------------------------------------
// Memory Access / Instruction Fetch
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
beginif (rst_i == 1'b1)beginmem_addr_o      <= 32'h00000000;        mem_dat_o       <= 32'h00000000;mem_sel_o       <= 4'b0;mem_we_o        <= 1'b0;mem_stb_o       <= 1'b0;mem_cyc_o       <= 1'b0;
opcode_q        <= 32'h00000000;mem_offset_q    <= 2'b0;endelsebegincase (state_q)//-----------------------------------------// FETCH - Issue instruction fetch//-----------------------------------------
            STATE_FETCH :begin// Start fetch from memorymem_addr_o  <= pc_q;mem_stb_o   <= 1'b1;mem_we_o    <= 1'b0;mem_cyc_o   <= 1'b1;end//-----------------------------------------// FETCH_WAIT - Wait for response//-----------------------------------------
            STATE_FETCH_WAIT :begin// Data ready from memory?if (mem_ack_i)beginopcode_q    <= mem_dat_i;mem_cyc_o   <= 1'b0;                            endend//-----------------------------------------// EXEC - Issue read / write//-----------------------------------------
            STATE_EXEC :begin`ifdef CONF_CORE_TRACE$display("%08x: Execute 0x%08x", pc_q, opcode_q);$display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);$display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);`endifcase (1'b1)// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
                 load_inst_r:beginmem_addr_o      <= {mem_addr_r[31:2], 2'b0};mem_offset_q    <= mem_addr_r[1:0];mem_dat_o       <= 32'h00000000;mem_sel_o       <= 4'b1111;mem_we_o        <= 1'b0;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;
`ifdef CONF_CORE_DEBUG$display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);`endifendinst_sb_w: // l.sbbeginmem_addr_o      <= {mem_addr_r[31:2], 2'b0};mem_offset_q    <= mem_addr_r[1:0];case (mem_addr_r[1:0])2'b00 :beginmem_dat_o       <= {reg_rb_r[7:0],24'h000000};mem_sel_o       <= 4'b1000;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;end2'b01 :beginmem_dat_o       <= {{8'h00,reg_rb_r[7:0]},16'h0000};mem_sel_o       <= 4'b0100;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;end2'b10 :beginmem_dat_o       <= {{16'h0000,reg_rb_r[7:0]},8'h00};mem_sel_o       <= 4'b0010;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;end2'b11 :beginmem_dat_o       <= {24'h000000,reg_rb_r[7:0]};mem_sel_o       <= 4'b0001;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;enddefault :;endcaseendinst_sh_w: // l.shbeginmem_addr_o      <= {mem_addr_r[31:2], 2'b0};mem_offset_q    <= mem_addr_r[1:0];case (mem_addr_r[1:0])2'b00 :beginmem_dat_o       <= {reg_rb_r[15:0],16'h0000};mem_sel_o       <= 4'b1100;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;end2'b10 :beginmem_dat_o       <= {16'h0000,reg_rb_r[15:0]};mem_sel_o       <= 4'b0011;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;enddefault :;endcaseendinst_sw_w: // l.swbeginmem_addr_o      <= {mem_addr_r[31:2], 2'b0};mem_offset_q    <= mem_addr_r[1:0];mem_dat_o       <= reg_rb_r;mem_sel_o       <= 4'b1111;mem_we_o        <= 1'b1;mem_stb_o       <= 1'b1;mem_cyc_o       <= 1'b1;
`ifdef CONF_CORE_DEBUG$display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2'b00}, reg_rb_r);
      `endifenddefault:;endcaseend//-----------------------------------------// MEM - Wait for response//-----------------------------------------
            STATE_MEM :begin// Data ready from memory?if (mem_ack_i)beginmem_cyc_o   <= 1'b0;endend            default:;endcaseend
end

该实现是一个典型的5级流水线处理器,下方的部分是访存部分的状态机逻辑实现,这部分的代码描述了 Memory Access / Instruction Fetch的操作,是通过唯一的总线端口进行的。

(2)哈佛结构,读取数据的接口和读取指令的接口分开,代码如下:

//-----------------------------------------------------------------
// Module - AltOR32 CPU (Pipelined Wishbone Interfaces)
//-----------------------------------------------------------------
module altor32
(// Generalinput               clk_i,input               rst_i,input               intr_i,input               nmi_i,output              fault_o,output              break_o,// Instruction memoryoutput [31:0]       imem_addr_o,input [31:0]        imem_dat_i,output [2:0]        imem_cti_o,output              imem_cyc_o,output              imem_stb_o,input               imem_ack_i,  // Data memoryoutput [31:0]       dmem_addr_o,output [31:0]       dmem_dat_o,input [31:0]        dmem_dat_i,output [3:0]        dmem_sel_o,output [2:0]        dmem_cti_o,output              dmem_cyc_o,output              dmem_we_o,output              dmem_stb_o,input               dmem_ack_i
);
.
.
.
//-----------------------------------------------------------------
// Module - Wishbone fetch unit
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
beginif (rst_i == 1'b1)beginwbm_addr_o      <= 32'h00000000;wbm_cti_o       <= 3'b0;wbm_stb_o       <= 1'b0;wbm_cyc_o       <= 1'b0;
fetch_word_q    <= {FETCH_WORDS_W{1'b0}};resp_word_q     <= {FETCH_WORDS_W{1'b0}};endelsebegin// Idleif (!wbm_cyc_o)beginif (fetch_i)beginif (burst_i)beginwbm_addr_o      <= {address_i[31:FETCH_BYTES_W], {FETCH_BYTES_W{1'b0}}};fetch_word_q    <= {FETCH_WORDS_W{1'b0}};resp_word_q     <= {FETCH_WORDS_W{1'b0}};// Incrementing linear burstwbm_cti_o       <= WB_CTI_BURST;endelsebegin                    wbm_addr_o      <= address_i;resp_word_q     <= address_i[FETCH_BYTES_W-1:2];// Single fetchwbm_cti_o       <= WB_CTI_FINAL;                    end// Start fetch from memorywbm_stb_o           <= 1'b1;wbm_cyc_o           <= 1'b1;                        endend// Access in-progresselsebegin// Command acceptedif (~wbm_stall_i)begin// Fetch next word for lineif (wbm_cti_o != WB_CTI_FINAL)beginwbm_addr_o      <= {wbm_addr_o[31:FETCH_BYTES_W], next_word_w, 2'b0};fetch_word_q    <= next_word_w;// Final word to read?if (penultimate_word_w)wbm_cti_o   <= WB_CTI_FINAL;end// Fetch completeelsewbm_stb_o       <= 1'b0;end// Responseif (wbm_ack_i)resp_word_q         <= resp_word_q + 1'b1;// Last response?if (final_o)wbm_cyc_o           <= 1'b0;endend
end
.
.
.
.
//-----------------------------------------------------------------
// Module - Data Cache Memory Interface
//-----------------------------------------------------------------
always @ *
beginnext_state_r = state;case (state)//-----------------------------------------// IDLE//-----------------------------------------
    STATE_IDLE :begin// Perform cache evict (write)     if (evict_i)next_state_r    = STATE_WRITE_SETUP;// Perform cache fill (read)else if (fill_i)next_state_r    = STATE_FETCH;// Read/Write singleelse if (rd_single_i | (|wr_single_i))next_state_r    = STATE_MEM_SINGLE;end//-----------------------------------------// FETCH - Fetch line from memory//-----------------------------------------
    STATE_FETCH :begin// Line fetch complete?if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})next_state_r    = STATE_FETCH_WAIT;end//-----------------------------------------// FETCH_WAIT - Wait for read responses//-----------------------------------------
    STATE_FETCH_WAIT:begin// Read from memory completeif (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})next_state_r = STATE_IDLE;end  //-----------------------------------------// WRITE_SETUP - Wait for data from cache//-----------------------------------------
    STATE_WRITE_SETUP :next_state_r    = STATE_WRITE;//-----------------------------------------// WRITE - Write word to memory//-----------------------------------------
    STATE_WRITE :begin// Line write complete?if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})next_state_r = STATE_WRITE_WAIT;// Fetch next word for lineelse if (~mem_stall_i | ~mem_stb_o)next_state_r = STATE_WRITE_SETUP;end//-----------------------------------------// WRITE_WAIT - Wait for write to complete//-----------------------------------------
    STATE_WRITE_WAIT:begin// Write to memory completeif (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})next_state_r = STATE_IDLE;end            //-----------------------------------------// MEM_SINGLE - Single access to memory//-----------------------------------------
    STATE_MEM_SINGLE:begin// Data ready from memory?if (mem_ack_i)next_state_r  = STATE_IDLE;end  default:;endcase
end

上面摘录了不同阶段的代码,首先是CPU总线接口,有专门的指令总线和数据总线,下面是指令读取的状态机逻辑中的操作,最后部分是数据读写的逻辑操作。

转载于:https://www.cnblogs.com/lyuyangly/p/6623348.html

处理器不同编址方式、指令/数据处理方式区别相关推荐

  1. Chap-4 Section 4.2.4 指令修正方式

    对于X86平台下的ELF文件的重定位入口所修正的指令寻址方式只有两种:绝对近址32寻址和相对近址32寻址. 这两种指令修正方式每个被修正的位置的长度都为32位,即4个字节,而且都是近址寻址,不用考虑I ...

  2. 关于数据仓库中变化历史数据处理方式:全量表、快照表、拉链表

    关于数据仓库中变化历史数据处理方式:全量表.快照表.拉链表 一.全量表 二.快照表 三.拉链表 对于数据仓库中变化的历史数据存储,一般有三种方式:全量表.快照表.拉链表 一.全量表 直接全量导入,覆盖 ...

  3. WPS和Word段落文字5种对齐方式的功能、区别和用法详细解析

    在WPS文字和Word文档中,段落中的文字对齐方式共有五种,分别是:左对齐.居中.右对齐.两端对齐.分散对齐. 这五种对齐方式分别实现了什么对齐效果?他们的区别是什么?在什么时候使用哪种对齐方式呢?能 ...

  4. VDA6.5认证咨询,产品审核与其他审核方式及检验的区别

    VDA6.3中1998版和2010版的差别  审核员的要求  二.审核过程    过程风险的识别和分析   最佳实践/经验教训  三.项目管理(pm)   四.产品和过程开发的策划  五.产品和过程开 ...

  5. 谈谈本地缓存的几种方式以及他们的区别?

    谈谈本地缓存的几种方式以及他们的区别? 说起本地缓存,大家想到的应该都是这几个方法:localStorage.sessionStorage.cookie. 相同点不必我再多说了,都可以实现本地缓存的效 ...

  6. Alcohol 120% 的五种烧录方式各有什么区别

    Alcohol 120% 的五种烧录方式各有什么区别 Before reading this post you must know that when you extract an image fro ...

  7. c语言以只写方式打开二进制文件,C语言采用文本方式和二进制方式打开文件的区别分析...

    稍微了解C程序设计的人都知道,文本文件和二进制文件在计算机上面都是以0,1存储的,那么两者怎么还存在差别呢?对于编程人员来说,文本文件和二进制文件就是一个声明,指明了你应该以什么方式(文本方式/二进制 ...

  8. 记: 对于SCPI指令以及相同类型指令解析器的指令压缩方式

    0x10 前言 SCPI是一个对人或者说用户十分友好的语言,采用了人性化的抽象与对于用户很友善的组成方式. 但是对于某些机器的设计就会很难受,而且当前的机器会在日后的不停更新导致当前的程序越来越呈现一 ...

  9. Java连接Oracle两种方式thin与oci区别

    Java连接Oracle两种方式thin与oci区别 前几天同事跑过来跟我说, 机房中的一台tomcat服务器跟oracle数据库机连接很慢,查看控制台中的hibernate日志, 基本上是一条sql ...

最新文章

  1. Virtual PC 2007下虚拟机与本机双XP系统实现互联与上网详解
  2. python dig trace 功能实现——通过Querying name server IP来判定是否为dns tunnel
  3. ASP.NET MVC 向浏览器发送文件以提供文件下载功能
  4. MATLAB基本操作(七):有关文件路径的几个函数在编程中的作用
  5. linux下几种运行后台任务的方法
  6. pyinstaller打包pyqt文件(转)
  7. 前端学习(2715):重读vue电商网站35之在sessionStorage保存左侧菜单栏的激活状态
  8. matlab 二值化图像反色,图像处理——灰度化、二值化、反色、饱和度、对比度...
  9. 用matlab画图将原点显示,[转帖] Matlab plot画图时,让原点在图中心
  10. 对于vue的评价:没事情做可以学
  11. POJ NOI0105-45 金币
  12. 总结《Ray Tracing from the Ground Up》
  13. CentOS 6.3 配置 yum
  14. 上帝视角-我是一个线程『转』
  15. jzoj 3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll) (Standard IO)
  16. 传音手机增长策略:用户需求为核心,创新生产逻辑和客户关系
  17. 计算机ps2定义,软件硬件界面接口定义 bt656 硬件接口定义
  18. IE浏览器登录Tomcat报错
  19. SqlServer geometry 转 geography
  20. 机器学习比赛、项目之模板

热门文章

  1. 基于Matlab 实现螺旋线 轨迹曲线绘制
  2. vscode分支合并
  3. html中编辑广告位,广告位(banner)的可视化管理后台逻辑说明
  4. 转载:chatbot聊天机器人技术路线
  5. 如何在typescript中importfs模块
  6. STM8L学习笔记-GPIO端口操作(一)
  7. 国际机器视觉产业发展现状与趋势
  8. 笔记本计算机作文,我的笔记本电脑作文600字
  9. 产业新闻-2006.06.02-05
  10. C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\appcompat-v7-26.1.0.aar