【计算机系统设计】实践笔记(3)改进数据通路:移位R型指令分析

0 回顾

前面的内容中,第一类R型指令分析,我们完成了一类R型指令的设计,完成了其数据通路,构建了相应的部件,并且完成了从ROM中取指,成功进行了基本的功能仿真,进行了综合和实现,但是没有完成综合和实现的时序仿真。

下面,我们要继续进行其他R型指令的分析,这次我们只分析三个移位指令,也就是sll srl sra,然后改进我们已有的数据通路,完成对应的设计。

1 移位指令分析

我们先看看指令编码

instructionoprsrtrdshamtfunc
sll00000000000rtrdshamt000000
srl00000000000rtrdshamt000010
sra00000000000rtrdshamt000011

再看看其功能逻辑

三个指令的逻辑都是一样的

  • rd <- (rt op shamt)
  • op:
    • srl: >>
    • sll: <<
    • sra: >>>

指令的使用:instruction rd,rs,shamt

值得注意的是,shamt是5位,范围是0~31.

需要的器件和信号

我们依次分析一下,完成操作,需要改进哪些部件和信号

很容易知道,我们只需要改进一下ALU的输入数据和控制即可,同时控制器要识别出这三个指令,增加一些相关信号。

  1. ALU
    1. 增加shamt的输入
    2. 移位操作不需要增加,之前已经实现过
    3. 移位操作的输入需要增加选择,使得rt和shamt被正确输入
    4. 为ALU增加控制信号Sftmd,表明是这几个移位操作
  2. 控制器:增加控制信号Sftmd输出到ALU

我们原来的数据通路就变成了
在这里插入图片描述

3 ALU和控制器设计改进

3.1 控制器设计

我们把之前的也拿出来,同时标出新增内容。

  • 输入信号:op func
  • 输出信号:RegWrite ALUop新增Sftmd
instructionopfuncALUopRegWriteSftmd 新增
add000000100000000010
addu000000100001000110
sub000000100010001010
subu000000100011001110
and000000100100010010
or000000100101010110
xor000000100110011010
nor000000100111011110
slt000000101010100010
sltu000000101011100110
sllv000000101010101010
srlv000000000110101110
srav000000000111110010
新增
sll000000000000101011
srl000000000010101111
sra000000000011110011

3.2 ALU设计

  • 数据输入:R[rs] R[rd]新增shamt
  • 控制输入:ALUop新增Sftmd
  • 数据输出:R[rd]

特别的,当Sftmd == 1(表明是移位指令)的时候,ALU增加了多路选择器,将sllv等指令的输入由rtrs变成了rtshamt

也就是在rsshamt之间增加了选择器,当Shtmd == 1使用shamt作为输入,注意需要0扩展为32位进行运算。

注意:改了输入输出端口,相应的实例也要改。

4 Verilog实现

我们下面改进代码!

4.1 Bug修复:sllv等指令的ALU错误

设计中发现,之前的设计有错误!是在移位指令的时候!我们先来改正它,并且改进我们的测试实例。

sllv举例,它是使用方法是sllv rd,rt,rs,逻辑是rd <- rt << rs

汇编程序员视角

是正常指令的使用,逻辑也是正常的,但是,内部逻辑却不一样了。

内部逻辑

例如sllv $5,$10,$9,功能操作是$5 = $10 << $9,而内部是

  • rt = $10 对应ALU的B
  • rs = $9 对应ALU的A
  • ALU操作是B << A,而不是A << B

这里之前犯的错误是,改变了程序员视角的指令……,将上层和底层搞混了……

4.2 新的ALU

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/14 22:30:23
// Design Name:
// Module Name: ALU_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module ALU_1(// datainput [31:0] A,input [31:0] B,input [4:0] shamt,// controlinput [3:0] ALUop,input Sftmd, // shift instruction controloutput reg [31:0] ALUresult);// convert A and B to signed numbers
wire signed [31:0] A_signed = A;
wire signed [31:0] B_signed = B;// for shift instructions
// select data: if (Sftmd == 1) input shamt else input rs
wire [31:0] A_or_Shift = (Sftmd == 0) ? A : {27'b0,shamt};/* calculate */
always @(*)
begincase (ALUop)4'b0000:    // addbeginALUresult <= A + B;end4'b0001:    // addubeginALUresult <= A + B;end4'b0010:    // subbeginALUresult <= A - B;end4'b0011:    // sububeginALUresult <= A - B;end4'b0100:    // andbeginALUresult <= A & B;end4'b0101:    // orbeginALUresult <= A | B;end4'b0110:    // xorbeginALUresult <= A ^ B;end4'b0111:    // norbeginALUresult <= ~(A | B);end4'b1000:    // slt // note:********signed********//beginif(A_signed < B_signed)ALUresult <= 1;elseALUresult <= 0;end4'b1001:    // sltubeginif(A < B)ALUresult <= 1;elseALUresult <= 0;end4'b1010:    // sllv 10beginALUresult <= B << A_or_Shift;    // NOTE: not A << B!end4'b1011:    // srlvbeginALUresult <= B >> A_or_Shift;    // NOTE: not A >> B!end4'b1100:    // srav // note: ******signed*******//beginALUresult <= B_signed >>> A_or_Shift;    // NOTE: not A_signed >> B!enddefault:beginALUresult <= 0;endendcase
endendmodule

关注移位指令的部分即可,同时注意最开始的多路选择器。

4.3 新的control

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/14 22:30:48
// Design Name:
// Module Name: control_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module control_1(input [5:0] op,input [5:0] func,output reg RegWrite,output reg Sftmd,    // indicate the instruction is sll/srl/sraoutput reg [3:0] ALUop);always @(*)
beginif(op == 6'b0)begincase (func)6'b100000:  // addbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0000;end6'b100001:  // addubeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0001;end6'b100010:  // subbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0010;end6'b100011:  // sububeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0011;end6'b100100:  // andbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0100;end6'b100101:  // orbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0101;end6'b100110:  // xorbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0110;end6'b100111:  // norbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0111;end6'b101010:  // sltbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1000;end6'b101011:  // sltubeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1001;end6'b000100:  // sllvbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1010;end6'b000110:  // srlvbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1011;end6'b000111:  // sravbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1100;end6'b000000:  // sllbeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1010;end6'b000010:  // srlbeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1011;end6'b000011:  // srabeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1100;enddefault:beginRegWrite <= 0;Sftmd <= 0;ALUop <= 4'b1111;endendcaseendelsebeginRegWrite <= 0;Sftmd <= 0;ALUop <= 4'b1111;end
endendmodule

注意新增的信号。

4.4 新的datapath

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/27 11:41:34
// Design Name:
// Module Name: datapath_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 仅仅实现了几个简单的R类指令的最简单的数据通路,不与外界交互
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module datapath_1(input clk,input rst_n,output [31:0] result // 测试syntheses,没有输出的模块是恐怖的);/******** PC ********/// pc_1 Outputs
wire  [31:0]  pcOld;pc_1  u_pc_1 (.clk                     ( clk     ),.rst_n                   ( rst_n   ),.pcNew                   ( pcOld   ), // pcNew = pcOld + 4; no selection.pcOld                   ( pcOld   ));/******** Instruction ROM ********/// blk_mem_gen_0 Inputs
// wire  [13:0]  addra  = pcOld[15:2];// blk_mem_gen_0 Outputs // instructions
wire  [31:0]  instruction;blk_mem_gen_0  u_blk_mem_gen_0 (.clka                    ( clk    ),.addra                   ( pcOld[15:2]   ),.douta                   ( instruction   ));/******** Reg Files ********/// reg_files_1 Inputs
wire  [31:0]  ALUresult;/// wire   [4:0]  rA = instruction[25:21];
/// wire   [4:0]  rB = instruction[20:16];
/// wire   [4:0]  rW = instruction[15:11];
/// wire   [31:0]  writeData = ALUresult;
wire   RegWrite;// reg_files_1 Outputs
wire  [31:0]  A;
wire  [31:0]  B;reg_files_1  u_reg_files_1 (.clk                     ( clk         ),.rst_n                   ( rst_n       ),.rA                      ( instruction[25:21]          ),.rB                      ( instruction[20:16]          ),.rW                      ( instruction[15:11]          ),.writeData               ( ALUresult   ),.RegWrite                ( RegWrite    ),.A                       ( A           ),.B                       ( B           ));/******** ALU ********/// ALU_1 Inputs
// wire   [31:0]  A;
// wire   [31:0]  B;
wire   [3:0]  ALUop;
wire   Sftmd;// ALU_1 OutputsALU_1  u_ALU_1 (.A                       ( A           ),.B                       ( B           ),.shamt                   ( instruction[10:6]),.ALUop                   ( ALUop       ),.Sftmd                   ( Sftmd       ),.ALUresult               ( ALUresult   ));/******** controler ********/// control_1 Inputs
// wire   [5:0]  op = instruction[31:26];
// wire   [5:0]  func = instruction[5:0];// control_1 Outputs
// wire  RegWrite
// wire  [3:0]  ALUop;control_1  u_control_1 (.op                      ( instruction[31:26]         ),.func                    ( instruction[5:0]       ),.RegWrite                ( RegWrite   ),.Sftmd                   ( Sftmd      ),.ALUop                   ( ALUop      ));assign result = ALUresult;endmodule

注意实例化的时候,信号不要弄错。

4.5 旧的测试:tb_datapath

激励块内容不变。

4.6 新的测试用例

nop
add $1,$2,$3	# $1 = 2 + 3 = 5
addu $2,$4,$1	# $2 = 4 + 5 = 9
sub $4,$2,$1	# $4 = 9 - 5 = 4
subu $5,$4,$3	# $5 = 4 - 3 = 1and $6,$7,$8	# $6 = 0111 and 1000 = 0
or $7,$6,$8		# $7 = 0 or 1000 = 8
xor $7,$6,$8	# $7 = 0000 xor 1000 = 1000 = 8
nor $8,$7,$6	# $8 = not (1000 or 0) = 11111111111110111slt $10,$11,$12	# $10 = 11 < 12 = 1		# 应该用负数验证,以后再说
sltu $10,$12,$11	# $10 = 12 > 11 = 0# sllv $12,$5,$13	# $12 = 1101 << 1 = 1101_0 = 1A	【注意此处的倒置问题! sllv rd,rt,rs】
# srlv $12,$5,$13	# $12 = 1101 >> 1 = 110 = 6
# srav $14,$5,$15	# $14 = 1111 >>> 1 = 111  = 7 应该用负数验证,以后再说# 上面3条是错误的!我们应该改的不是使用,而是内部运算逻辑
# 对于使用者来说,逻辑就是 $13 << $5
# 而实际的编码是 rt = $13,rs = $5,这与一般的指令不一样
# 因此,我们在ALU运算中 rt--B,rs--A,应该是 【B << A】,而不是 A >> B。
sllv $12,$13,$5	# $12 = 1101 << 1 = 1101_0 = 1A	
srlv $12,$13,$5	# $12 = 1101 >> 1 = 110 = 6
srav $14,$15,$5	# $14 = 1111 >>> 1 = 111  = 7 应该用负数验证,以后再说sll $16,$17,2	# $16 = 1_0001 << 2 = 100_0100 = 44	
srl $16,$18,2	# $16 = 1_0010 >> 2 = 0100 = 4
sra $16,$19,2	# 应该用负数验证,以后再说 $16 = 4

特别注意最后移位指令,注意注释内容。

指令编码的coe文件:

memory_initialization_radix = 16;
memory_initialization_vector =
00000000,
00430820,
00811021,
00412022,
00832823,
00e83024,
00c83825,
00c83826,
00e64027,
016c502a,
018b502b,
00ad6004,
00ad6006,
00af7007,
00118080,
00128082,
00138083;

最终测试

经过了每个模块的RTL优化和最终的仿真测试,结果没有问题!我们又为之前的数据通路增加了新的3个指令!Fighting!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机系统设计】实践笔记(3)改进数据通路:jr指令分析与实现

1 jr指令分析 instructionoprsrtrdshamtfuncjr000000rs000000000000000001000 举例&#xff1a;jr $31 功能&#xff1a;PC <- &#xff08;$31&#xff09; 这是个跳转指令&#xff0c;将指定寄存器的值&#xff0c;放入PC中&#xff0c;是无条件跳转。 我们需要 更新P…

【计算机系统设计】实践笔记(4)改进数据通路:第一类I型指令分析与实现

0 回顾 之前&#xff0c;我们完成了17条R型指令的设计&#xff0c;接下来&#xff0c;我们逐步完成I型指令的设计。 1 核心思想&#xff1a;增量思维 & 复用思维 & 学会选择 & 分治思想 增量思维 我们从无到有&#xff0c;构建了支持R型指令的CPU&#xff0c;接…

【算法】学习笔记(2):递归思想

0 回顾 之前的笔记&#xff08;0&#xff09;和笔记&#xff08;1&#xff09;&#xff0c;我们介绍了算法的基本含义&#xff0c;并且举了一些实例&#xff0c;同时理解了&#xff0c;算法就是人类在教计算机做事情&#xff01; 我们知道&#xff0c;算法就是解决问题的方案…

【计算机系统设计】实践笔记(5)改进数据通路:beq和bne指令分析与实现

接下来的分析和实践非常粗糙&#xff0c;因为跟之前一样的分析流程&#xff0c;不再多说了&#xff0c;如果前面真的掌握&#xff0c;这里不看也罢。 分析 先看beq指令。 ALU输入的是rs和rt&#xff0c;不输入imm&#xff0c;进行subu操作&#xff0c;判断是否为zero&#x…

【算法】学习笔记(4):分治思想 归并排序

分治思想&#xff0c;分治策略&#xff0c;自古有之&#xff0c;与人类生活息息相关&#xff0c;其本质是将大问题拆解为小问题&#xff0c;小问题转换为已知解的问题&#xff0c;进而求解。 军队管理&#xff0c;国家分级治理…… 大规模数据排序&#xff0c;例如10000000000…

html css 学习笔记(1)背景相关

背景颜色 图片 插入图片img背景图片 背景图片 3. logo 4. 大图 5. 装饰性小图 便于控制位置&#xff01; 插入后会执行自动平铺&#xff0c;这与插入图片是不同的&#xff01; div{width: 600px;height: 300px;background-image: url(img/登录用户头像.png); }小结 盒子的第…

2020-12-15 CPU设计复盘

SOC修改 将之前完成的31条指令单周期CPU进行了重构&#xff0c;将其分开&#xff0c;实现了内外有别&#xff0c;将CPU、指令ROM和数据RAM。 这样&#xff0c;以后为其增加接口外设&#xff0c;总线控制&#xff0c;才更加清晰&#xff0c;这是进一步封装和抽象。 MARS大坑 …

Tomcat 学习笔记(0)

JavaWeb 用Java写的程序&#xff0c;可以在浏览器运行。 Request & Responce Web资源 Web服务器 我们在自己的主机启动Tomcat服务器&#xff0c;然后运行它&#xff0c;就能够通过主机访问这个服务器&#xff0c;这个服务器能够运行我们的程序。 部署Web工程 法1 将web…

计算机系统 学习笔记(0)南京大学(一)第一周

课程&#xff1a;计算机系统基础 核心理念&#xff1a;人类世界与计算机世界的异同 人类世界 直观感受数学 计算机世界 与数学不同&#xff0c;存储首先&#xff0c;各层次与现实世界不同 我们关注点是差异点&#xff01; 一样的你就不用关心了&#xff0c;关心差异&#…

x86架构下 CF与OF标志位 带符号和无符号运算 详解

针对能够影响OF和CF标志位的指令&#xff0c;一般来说是涉及到数据运算的指令&#xff0c;这里使用add举例&#xff0c;即不区分有无符号的加法指令&#xff0c;参与运算的数据&#xff0c;从二进制层级去考虑。 CF标志位 对于CF&#xff0c;它是carry flag&#xff0c;进位标…

tmux学习笔记

参考学习链接 我们需要理解几个重要的概念 session 回话window 窗口pane 窗格 window 我们打开的一个terminal就是一个window. 而打开的这个window&#xff0c;也就是打开了一个session&#xff0c;打开window&#xff0c;session开始&#xff1b;关闭window&#xff0c;se…

Linux的ext4文件系统学习笔记

补充&#xff1a;设备独立性 Linux中&#xff0c;设备驱动以文件形式表示&#xff0c;用户操作逻辑设备就是操作文件&#xff0c;而不是具体的物理设备&#xff0c;也就是说&#xff0c;用户操作的是功能&#xff0c;是黑箱&#xff0c;而不是真正的实体。 APP操作的都是逻辑…

html基础元素案例笔记(1)

这是代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>CSS FlexBox test</title><link rel"stylesheet" type"text/css" href"./css/index.css"></head><body>…

C语言中的struct和union区别

参考&#xff1a;Difference between Structure and Union in C 二者区别 struct 这里不做详细说明&#xff0c;因为参考链接中都写明了。只做一些重点强调。 struct中声明的变量&#xff0c;在分配空间的时候&#xff0c;struct结构空间大小&#xff0c;大于等于其内部所有…

Leetcode1512. 好数对的数目 抽出本质原型 利用范围条件

解法1&#xff1a;暴力枚举 class Solution {public int numIdenticalPairs(int[] nums) {int count 0;for(int i 0;i < nums.length; i){for(int j i 1; j < nums.length; j){if(nums[i] nums[j])count;}}return count;} }没啥可说的&#xff0c;就是小学数学问题…

leetcode面试题 10.01. 合并排序的数组

直接排序 直接使用Java已有的方法进行排序&#xff0c;这一招…大意了&#xff01; 这题简单&#xff0c;就是个基本的排序&#xff0c;后面难题&#xff0c;可能这只是一小步&#xff0c;内个时候直接用排序算法比较合适&#xff0c;这个不合适。。 class Solution {public…

IA-32 Architecture: the function of segment regitster(CS DS SS ES)

对于IA-32架构&#xff0c;与8086不同&#xff0c;段寄存器不再是像以前一样&#xff0c;直接作为段基址&#xff0c;因为32位的寄存器直接就可以表示4GB大小&#xff0c;不需要再偏移&#xff0c;因此段寄存器的含义也发生了相应的变化。 在IA-32架构里&#xff0c;段寄存器是…

x86异常处理与中断机制(1)概述中断的来源和处理方式

参考《计算机组成》&#xff08;北京大学 MOOC&#xff09; 1 异常与中断的来源&#xff08;为什么需要中断&#xff09; 首先&#xff0c;说明一下异常和中断这两个概念。 它们两个唯一的区别&#xff0c;就是&#xff0c;没有什么区别。只是不同的地方不同的时间不同的人的…

【C language】动态数组的创建和使用

在C语言中&#xff0c;使用malloc函数创建动态数组&#xff0c;使用一个指针指向它&#xff0c;使用下标进行访问。 unsigned long *a (unsigned long *)malloc(2 * sizeof(int)); a[0] 1000; a[1] 2000; printf("%d %d\n", a[0], a[1]); free(a);上述例子&…

x86异常处理与中断机制(2)中断向量表

补充&#xff1a;事件不仅包含中断和异常&#xff0c;还包含系统调用&#xff0c;这个属于用户主动请求的事件。 上一节&#xff0c;只有一个溢出异常&#xff0c;那么&#xff0c;如果很多异常、中断呢&#xff1f;&#xff08;中断向量表&#xff09; 另外&#xff0c;之前0…