【读书笔记】RISC存储程序机的电路设计(1)

简介: 【读书笔记】RISC存储程序机的电路设计(1)

前言

复习一下研究生时候一个小的课设题,内容在《Verilog HDL高级数字设计(第二版)》“7.3 RSIC存储程序机的设计与综合”,目的是做一个精简指令集计算机。之前一直很是不能理解其中的设计思路与结构,最近这段时间在有了一些实践经验后有种豁然开朗、一拍即合的感觉,趁着还记得赶紧记下来。

完整目录:

 

【读书笔记】RISC存储程序机的电路设计(1)

【读书笔记】RISC存储程序机的电路设计(2)

【读书笔记】RISC存储程序机的电路设计(3)

【读书笔记】RISC存储程序机的电路设计(4)

【读书笔记】RISC存储程序机的电路设计(5)

【读书笔记】RISC存储程序机的电路设计(6)

 

概述

RSIC处理器的结构图我直接从书上拓下来下来了,如下图:

整个处理器电路分为三个通路:控制通路(Controller)、处理通路(Processor)和存储通路(Memory),运算器ALU包含在处理通路中。

整体系统的运转方式,在我理解,先由软件将要执行的指令和数据写入mem中,之后进入硬件工作流程:

1.取值:PC模块中记录着当前需要取得指令的存储地址;

2.译码:IR模块对指令进行译码,告知ALU模块需要对数据进行什么操作;

3.执行:ALU对立即数/通用寄存器值进行运算,输出运算结果至通用寄存器;按照需求更新PC/IR/Add_R/Reg_Z等模块;

4.写入:将执行处理结果写入mem;

5.回收:回收指令上报完成,继续将PC中指向的下一条指令读出至IR中,继续1~5的过程。

6.结束:直到遇到finish指令,结束硬件处理;

Processor

由于processor组件内部是最为复杂的,因此在看完概述后,我觉得有必要先展开下processor中的子模块,直接带着代码来展开可能更易于入门。

PC

程序计数器PC,用来存放着下一条待取指令的存储地址,其代码实现如下:

1. module program_count #(
2.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
3. )(
4.  output reg [WORD_WD -1:0] count_out,
5.  input    [WORD_WD -1:0] count_in,
6.  input             load, incr, clk, rst_n
7. );
8. 
9.  always @(posedge clk)begin
10.     if(rst_n == 1'b0)begin
11.       count_out <= {WORD_WD{1'b0}};
12.     end
13.     else if(load == 1'b1)begin
14.       count_out <= count_in;
15.     end
16.     else if(incr == 1'b1)begin
17.       count_out <= count_out + 'h1;
18.     end
19.     else begin
20.       count_out <= count_out;
21.     end
22.   end
23. 
24. endmodule//: program_count

其主要输入输出信号为:

count_out:待取指令的存储地址,该地址最终作用于Memory,将指令取出经由总线传送至IR模块;

incr:指令自加1高有效,该信号为高是count_out自加1,因为一般取值就是顺序取值,controller控制这个信号让PC自加1一直向下执行就可以了;

load:为高时使count_out跳转至count_in,一般遇到跳转指令时会用到该信号;

count_in:配合load使用,需要进行取值跳转时使用;

OK,PC就是控制指令地址的模块,用来加载下一条指令到IR模块。

IR

指令寄存器IR,用来存放当前正在执行的指令,简单而言就是一个寄存器足以:

1. module reg_unit #(
2.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
3. )(
4.  output reg [WORD_WD -1:0] data_out,
5.  input    [WORD_WD -1:0] data_in,
6.  input             load, clk, rst_n
7. );
8. 
9.  always @(posedge clk)begin
10.     if(rst_n == 1'b0)begin
11.       data_out <= {WORD_WD{1'b0}};
12.     end
13.     else if(load == 1'b1)begin
14.       if(DISPLAY_EN == 1) $display("%0t, %m, data_out update to 'b%8b('h%2h-'d%0d)", $realtime, data_in, data_in, data_in);
15.       data_out <= data_in;
16.     end
17.     else begin
18.       data_out <= data_out;
19.     end
20.   end
21. 
22. endmodule//: reg_unit

load:在load信号有效时,data_in会被写入都寄存器中,load由controller控制;

data_in:总线上的待写入数据,一般为PC->读取mem->读至总线->IR的数据流;

data_out:当前指令,因为指令的固定位是运算操作指示,因此该信号同时送至两个方向,方向一是给controller取解析指令,方向二是给ALU告诉他当前进行什么运算;

可见,IR就是用来暂存当前的指令,controller和ALU都是从IR获取当前要进行的操作的。

R0/R1/R2/R3

四个通用寄存器,用来在任何时间地点把需要用的值存在里面;

比如说我需要mem[100]的值+mem[200]值,那么我受制于总线和指令解析,我只能先把mem[100]的值取出来先放到R0去,然后再取mem[200]的值,在ALU中做加法然后通过总线写到R1,最后再讲R1的值通过总线写入到mem中;

因此这几个通用寄存器就是各种按需做数据倒腾的,代码其实就用上面的reg_unit就可以了。

Mux_1/Bus_1

进行数据交流的模块是无限的,而数据总线是有限的,因此需要对数据进行选择上总线;

Mux_1对接着Bus_1,根据controller的指示,选择将R0/R1/R2/R3/PC的值写到Bus_1,Bus_1的下游再根据需求从Bus_1上获取数据,举几个例子:

指令需要R0去做加法,那么Mux_1选择R0,ALU从Bus_1上取数据;

指令需要将R1存入mem中,那么Mux_1选择R1,mem从Bus_1上取数据;

需要进行取值,那么Mux_1选择PC,mem从Bus_1上取数据;

Mux如何选择,下游谁需要这个数据,一切尽在Controller控制之下,因此Mux_1的代码如下:

1. module mux_5sel1 #(
2.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
3. )(
4.  output reg [WORD_WD -1:0] mux_out,
5.  input  [WORD_WD -1:0]     mux_in0, mux_in1, mux_in2, mux_in3, mux_in4,
6.  input  [SEL1_WD  -1:0]    sel
7. );
8. 
9.  always @(*)begin
10.       case(sel)
11.       'h0: mux_out = mux_in0;
12.       'h1: mux_out = mux_in1;
13.       'h2: mux_out = mux_in2;
14.       'h3: mux_out = mux_in3;
15.       'h4: mux_out = mux_in4;
16.       default: mux_out = {WORD_WD{1'bx}};
17.     endcase   
18.   end
19. 
20. endmodule//: mux_5sel1


相关文章
|
存储
【读书笔记】RISC存储程序机的电路设计(2)
【读书笔记】RISC存储程序机的电路设计(2)
184 0
【读书笔记】RISC存储程序机的电路设计(2)
|
存储
【读书笔记】RISC存储程序机的电路设计(3)
【读书笔记】RISC存储程序机的电路设计(3)
120 0
【读书笔记】RISC存储程序机的电路设计(3)
|
存储 索引
【读书笔记】RISC存储程序机的电路设计(4)
【读书笔记】RISC存储程序机的电路设计(4)
200 0
【读书笔记】RISC存储程序机的电路设计(4)
|
存储 安全 C#
一起谈.NET技术,《Effective C#中文版:改善C#程序的50种方法》读书笔记
  从去年找工作以来,都没什么时间写博客[找工作的体会:建议以后有自己开公司的IT人一定要找IT专业人员做HR,好多公司的HR并不能真正发掘人才,他们形成了太多的偏见,如在学校期间学不了什么东西、只看学校有多少奖励等。
1175 0
|
存储 安全 C#
《Effective C#中文版:改善C#程序的50种方法》“.NET技术”读书笔记
  从去年找工作以来,都没什么时间写博客[找工作的体会:建议以后有自己开公司的IT人一定要找IT专业人员做HR,好多公司的HR并不能真正发掘人才,他们形成了太多的偏见,如在学校期间学不了什么东西、只看学校有多少奖励等。
1385 0
|
算法 UED
软件 = 程序 + 软件工程(构建之法读书笔记一)
  在我正式开始阅读这本书之前,我对于软件工程这个词汇的概念还是模糊的,认为它只是停留在是一门学科,一个专业,或者是一大堆硬生生的理论知识,然而当我读完构建之法这本书的推荐序和第一,第二版前言开始,我就深刻意识到我之前对于软件工程的肤浅认识是多么错误。
1009 0
|
C语言 编译器 程序员
以C语言为例的程序性能优化 --《深入理解计算机系统》第五章读书笔记
  其实大多数的编译器本身就能提供一些简单的优化,比如gcc就能通过使用 -O2 或者 -O3 的选项来优化程序。但编译器的优化始终也是有限,因为它必须小心翼翼保证优化过程不对程序的功能有改动。故而程序员本身应该对程序有优化意识。
1167 0
|
数据库 C#
【读书笔记】用反射+抽象工程模式实现多数据库的访问程序
  今天在上传代码的同时试着写点东西,请大家指教,哈!反射简单说起来就是 Assembly.Load(" 程序集名称").CreateInstance("命名空间.类名称")获取一个“类名称"的对象(使用时添加using System.Reflection命名空间)。
733 0
|
存储 安全 编译器
[笔记]读书笔记 C++设计新思维《一》基于策略的类设计(下)
[笔记]读书笔记 C++设计新思维《一》基于策略的类设计(下)