处理器不同编址方式、指令/数据处理方式区别
每个外设都是通过读写其寄存器来控制的。外设寄存器也称为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
处理器不同编址方式、指令/数据处理方式区别相关推荐
- Chap-4 Section 4.2.4 指令修正方式
对于X86平台下的ELF文件的重定位入口所修正的指令寻址方式只有两种:绝对近址32寻址和相对近址32寻址. 这两种指令修正方式每个被修正的位置的长度都为32位,即4个字节,而且都是近址寻址,不用考虑I ...
- 关于数据仓库中变化历史数据处理方式:全量表、快照表、拉链表
关于数据仓库中变化历史数据处理方式:全量表.快照表.拉链表 一.全量表 二.快照表 三.拉链表 对于数据仓库中变化的历史数据存储,一般有三种方式:全量表.快照表.拉链表 一.全量表 直接全量导入,覆盖 ...
- WPS和Word段落文字5种对齐方式的功能、区别和用法详细解析
在WPS文字和Word文档中,段落中的文字对齐方式共有五种,分别是:左对齐.居中.右对齐.两端对齐.分散对齐. 这五种对齐方式分别实现了什么对齐效果?他们的区别是什么?在什么时候使用哪种对齐方式呢?能 ...
- VDA6.5认证咨询,产品审核与其他审核方式及检验的区别
VDA6.3中1998版和2010版的差别 审核员的要求 二.审核过程 过程风险的识别和分析 最佳实践/经验教训 三.项目管理(pm) 四.产品和过程开发的策划 五.产品和过程开 ...
- 谈谈本地缓存的几种方式以及他们的区别?
谈谈本地缓存的几种方式以及他们的区别? 说起本地缓存,大家想到的应该都是这几个方法:localStorage.sessionStorage.cookie. 相同点不必我再多说了,都可以实现本地缓存的效 ...
- Alcohol 120% 的五种烧录方式各有什么区别
Alcohol 120% 的五种烧录方式各有什么区别 Before reading this post you must know that when you extract an image fro ...
- c语言以只写方式打开二进制文件,C语言采用文本方式和二进制方式打开文件的区别分析...
稍微了解C程序设计的人都知道,文本文件和二进制文件在计算机上面都是以0,1存储的,那么两者怎么还存在差别呢?对于编程人员来说,文本文件和二进制文件就是一个声明,指明了你应该以什么方式(文本方式/二进制 ...
- 记: 对于SCPI指令以及相同类型指令解析器的指令压缩方式
0x10 前言 SCPI是一个对人或者说用户十分友好的语言,采用了人性化的抽象与对于用户很友善的组成方式. 但是对于某些机器的设计就会很难受,而且当前的机器会在日后的不停更新导致当前的程序越来越呈现一 ...
- Java连接Oracle两种方式thin与oci区别
Java连接Oracle两种方式thin与oci区别 前几天同事跑过来跟我说, 机房中的一台tomcat服务器跟oracle数据库机连接很慢,查看控制台中的hibernate日志, 基本上是一条sql ...
最新文章
- Virtual PC 2007下虚拟机与本机双XP系统实现互联与上网详解
- python dig trace 功能实现——通过Querying name server IP来判定是否为dns tunnel
- ASP.NET MVC 向浏览器发送文件以提供文件下载功能
- MATLAB基本操作(七):有关文件路径的几个函数在编程中的作用
- linux下几种运行后台任务的方法
- pyinstaller打包pyqt文件(转)
- 前端学习(2715):重读vue电商网站35之在sessionStorage保存左侧菜单栏的激活状态
- matlab 二值化图像反色,图像处理——灰度化、二值化、反色、饱和度、对比度...
- 用matlab画图将原点显示,[转帖] Matlab plot画图时,让原点在图中心
- 对于vue的评价:没事情做可以学
- POJ NOI0105-45 金币
- 总结《Ray Tracing from the Ground Up》
- CentOS 6.3 配置 yum
- 上帝视角-我是一个线程『转』
- jzoj 3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll) (Standard IO)
- 传音手机增长策略:用户需求为核心,创新生产逻辑和客户关系
- 计算机ps2定义,软件硬件界面接口定义 bt656 硬件接口定义
- IE浏览器登录Tomcat报错
- SqlServer geometry 转 geography
- 机器学习比赛、项目之模板
热门文章
- 基于Matlab 实现螺旋线 轨迹曲线绘制
- vscode分支合并
- html中编辑广告位,广告位(banner)的可视化管理后台逻辑说明
- 转载:chatbot聊天机器人技术路线
- 如何在typescript中importfs模块
- STM8L学习笔记-GPIO端口操作(一)
- 国际机器视觉产业发展现状与趋势
- 笔记本计算机作文,我的笔记本电脑作文600字
- 产业新闻-2006.06.02-05
- C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\appcompat-v7-26.1.0.aar