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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【读书笔记】RISC存储程序机的电路设计(4)

前言

继续来~~~~~~~~~~~~~~~~~~~~~~

 

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

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

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

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

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

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

 

图放好~~~~~~~~~~~~~~~~~~~~~~

指令解析

指令解析的过程就是Controller的编码过程,对于每一个指令,Controller需要将其拆解为具体的电路行为。

RD

继续来看下长指令,以RD指令为实例吧,为了防止忘记,我们再回顾下前两步要干什么~

1.处于S_fet1时,进行取值操作,完成后跳转至S_fet2:

  • Sel_PC:Mux_1选择当前PC的输出到Bus_1总线,这个值就是我们要取得指令的地址;
  • Sel_Bus_1:Mux_2选择Bus_1,也就是说把PC值加载到Bus_2上来了;
  • Load_Add_R:把Bus_2总线上的数据写入到Add_R寄存器中,时序逻辑当拍拉高,下拍完成写入;

2.S_fet2状态下,将mem中的指令读出,之后进入S_dec译码:

  • Sel_mem:Bus_2选择mem的输出数据,即把mem[Add_R]值加载到Bus_2总线上;
  • Load_IR:将Bus_2上的值写入到IR内,实现了取值的功能;
  • Inc_PC:取值完成了,PC先自加1,无论是长指令还是短指令,下一个要取的位置都在下一个Byte,除非解析出了跳转,那就一会跳一下好了;

3.S_dec状态下进行译码,此时IR内的指令已经稳定,opcode = IR.data_out[8 -1:4]为操作码,假设现在确认了操作码为RD,先复习下RD的行为~

RD 0101 从长指令第二字节指定的存储单元中取出操作数,写入到目的寄存器 dst = mem[addr]

 

 

那么当识别到opcode为RD的话,需要进行如下解码操作:

  • Sel_PC + Sel_Bus_1 + Load_Add_R:把现在已经自加1的PC值再次写入到Add_R中,准备读取下一个地址;

因此,下面一个状态就是S_rd1状态,来处理mem读出操作;

4.S_rd1状态,注意这个时候我们通过PC索引到的是一个8bit值,这个值是我们所需要的内容的地址!因此我们需要的是把这个8bit作为地址索引,读出需要的内容,如何把这8bit作为地址索引呢?

  • Sel_mem:这样,mem的输出值加载到Bus_2总线上;
  • Load_Add_R:把Bus_2总线的值加载到Add_R内;
  • Inc_PC:处理完了后别忘记给PC自加1,PC值应该时刻指向下一个指令;

完成上述几步操作后,要读取的地址已经作用在mem接口上了,只需要在下一个状态S_rd2内将数据读出。

5.S_rd2状态,把长指令第二个字节索引地址内的内容写入dst寄存器中:

  • Sel_mem:把mem的值加载到Bus_2总线;
  • Load_R0/1/2/3:根据IR.data_out[2 -1:0],将Bus_2的数据写入到对应的目的寄存器中;

6.完美的完成了,这样继续跳会S_fet1继续取值就好了。

BR

1.长指令里再看一个BR跳转指令吧,前3步不多写了,从S_br1开始~

  • Sel_mem:这样,mem的输出值加载到Bus_2总线上;
  • Load_Add_R:把Bus_2总线的值加载到Add_R内;

S_br1与S_rd1的区别在哪里呢?就是少了Inc_PC,毕竟是要跳转,那自然就不需要PC自加1了呀;

2.S_br1之后就进入S_br2状态:

  • Sel_mem:把mem的值加载到Bus_2总线;
  • Load_PC:把Bus_2总线数据直接加载到PC就ok了;

好的,在需要跳转的地址直接加载到PC,那自然就完成了取值跳转。

Controller完整代码

经过上面的解析,实际上我们已经可以得到完整的Controller代码了,直接贴在这里,代码实现与书上的两段式状态机不一致,我更喜欢用三段状态机:

1. `ifndef CTRL_UNIT
2. `define CTRL_UNIT
3. 
4. `define ASSIGN_ZERO begin \
5.  sel_PC = 'h0; \
6.  sel_R0 = 'h0; \
7.  sel_R1 = 'h0; \
8.  sel_R2 = 'h0; \
9.  sel_R3 = 'h0; \
10.   sel_ALU = 'h0; \
11.   sel_BUS1 = 'h0; \
12.   sel_MEM = 'h0; \
13.   load_add_R = 'h0; \
14.   load_reg_Y = 'h0; \
15.   load_reg_Z = 'h0; \
16.   load_IR = 'h0; \
17.   inc_PC  = 'h0; \
18.   sel_R0  = 'h0; \
19.   sel_R1  = 'h0; \
20.   sel_R2  = 'h0; \
21.   sel_R3  = 'h0; \
22.   load_R0 = 'h0; \
23.   load_R1 = 'h0; \
24.   load_R2 = 'h0; \
25.   load_R3 = 'h0; \
26.   load_PC = 'h0; \
27.   sel_ALU = 'h0; \
28.   write   = 'h0; \
29. end
30. 
31. 
32. module ctrl_unit #(
33.   `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
34. )(
35.   output reg            load_R0, load_R1, load_R2, load_R3,
36.   output reg          load_PC, 
37.   output reg            load_IR,
38.   output reg          load_reg_Y,
39.   output reg          load_reg_Z,
40.   output reg          load_add_R,
41.   output reg          inc_PC, 
42.   output reg [SEL1_WD -1:0] mux1_sel_to_bus1,
43.   output reg [SEL2_WD -1:0] mux2_sel_to_bus2,
44. 
45.   output reg          write,
46. 
47.   input  [WORD_WD -1:0]     instruction,
48.   input                 zero_flag,
49.   input               clk, rst_n
50. );
51. 
52.   reg [STATE_WD -1:0] state, next_state;
53.   wire[OPCODE_WD -1:0] opcode;
54.   wire[SRC_WD -1:0]    src;
55.   wire[DEST_WD -1:0]   dest;
56.   reg sel_R0, sel_R1, sel_R2, sel_R3, sel_PC;
57.   reg sel_ALU, sel_BUS1, sel_MEM;
58. 
59.   assign opcode = instruction[(WORD_WD -1) : (WORD_WD -OPCODE_WD)];
60.   assign src    = instruction[(SRC_WD +DEST_WD -1) : DEST_WD];
61.   assign dest   = instruction[DEST_WD -1:0];
62. 
63.   always @(*)begin
64.     if(sel_R0)      mux1_sel_to_bus1 = 0;
65.     else if(sel_R1) mux1_sel_to_bus1 = 1;
66.     else if(sel_R2) mux1_sel_to_bus1 = 2;
67.     else if(sel_R3) mux1_sel_to_bus1 = 3;
68.     else if(sel_PC) mux1_sel_to_bus1 = 4;
69.     else      mux1_sel_to_bus1 = 0;
70.   end
71. 
72.   always @(*)begin
73.     if(sel_ALU)       mux2_sel_to_bus2 = 0;
74.     else if(sel_BUS1) mux2_sel_to_bus2 = 1;
75.     else if(sel_MEM)  mux2_sel_to_bus2 = 2;
76.     else        mux2_sel_to_bus2 = 0;
77.   end     
78. 
79.   always @(posedge clk)begin
80.     if(rst_n == 1'b0)begin
81.       state <= 'h0;
82.     end
83.     else begin
84.       state <= next_state;
85.     end
86.   end
87. 
88.   always @(*)begin
89.       case(state)
90.       S_IDLE: next_state = S_FET1;
91.       S_FET1: next_state = S_FET2;
92.       S_FET2: next_state = S_DEC;
93.       S_DEC : begin
94.         case(opcode)
95.           NOP, NOT:           next_state = S_FET1;
96.           ADD, SUB, AND, NOT: next_state = S_EX1;
97.           RD:         next_state = S_RD1;
98.           WR:         next_state = S_WR1;
99.           BR:         next_state = S_BR1;
100.          BRZ:        if(zero_flag == 0) next_state = S_BR1;
101.          default:        next_state = S_FET1;
102.        endcase
103.      end
104.      S_EX1 : next_state = S_FET1;
105.      S_RD1 : next_state = S_RD2;
106.      S_RD2 : next_state = S_FET1;
107.      S_WR1 : next_state = S_WR2;
108.      S_WR2 : next_state = S_FET1;
109.      S_BR1 : next_state = S_BR2;
110.      S_BR2 : next_state = S_FET1;
111.      default:next_state = S_IDLE;
112.    endcase
113.  end
114. 
115.  always @(*)begin
116.    `ASSIGN_ZERO
117.    case(state)
118.      S_IDLE: ;
119.      S_FET1: begin
120.        sel_PC     = 'h1;
121.        sel_BUS1   = 'h1;
122.        load_add_R = 'h1;
123.      end
124.      S_FET2: begin
125.        sel_MEM = 'h1;
126.        load_IR = 'h1;
127.        inc_PC  = 'h1;
128.      end
129.      S_DEC:  begin
130.        case(opcode)
131.          NOP: ;
132.          ADD, SUB, AND: begin
133.            case(src)
134.              SEL_R0: sel_R0 = 'h1;
135.              SEL_R1: sel_R1 = 'h1;
136.              SEL_R2: sel_R2 = 'h1;
137.              SEL_R3: sel_R3 = 'h1;
138.              default:;
139.            endcase
140.            sel_BUS1   = 'h1;
141.            load_reg_Y = 'h1;
142.          end
143.          NOT: begin
144.            case(src)
145.              SEL_R0: sel_R0 = 'h1;
146.              SEL_R1: sel_R1 = 'h1;
147.              SEL_R2: sel_R2 = 'h1;
148.              SEL_R3: sel_R3 = 'h1;
149.              default:;
150.            endcase
151.            case(dest)
152.              SEL_R0: load_R0 = 'h1;
153.              SEL_R1: load_R1 = 'h1;
154.              SEL_R2: load_R2 = 'h1;
155.              SEL_R3: load_R3 = 'h1;
156.              default:;
157.            endcase
158.            load_reg_Z = 'h1;
159.            sel_ALU    = 'h1;
160.          end
161.          RD:  begin
162.            sel_PC     = 'h1;
163.            sel_BUS1   = 'h1;
164.            load_add_R = 'h1;
165.          end
166.          WR:  begin
167.            sel_PC     = 'h1;
168.            sel_BUS1   = 'h1;
169.            load_add_R = 'h1;
170.          end
171.          BR:  begin
172.            sel_PC     = 'h1;
173.            sel_BUS1   = 'h1;
174.            load_add_R = 'h1;
175.          end
176.          default:;
177.        endcase
178.      end
179.      S_EX1:  begin
180.        case(dest)
181.          SEL_R0: begin sel_R0 = 'h1; load_R0 = 'h1; end
182.          SEL_R1: begin sel_R1 = 'h1; load_R1 = 'h1; end
183.          SEL_R2: begin sel_R2 = 'h1; load_R2 = 'h1; end
184.          SEL_R3: begin sel_R3 = 'h1; load_R3 = 'h1; end
185.          default:;
186.        endcase
187.        sel_ALU    = 'h1;
188.        load_reg_Z = 'h1;
189.      end
190.      S_RD1:  begin
191.        sel_MEM = 'h1;
192.        load_add_R = 'h1;
193.        inc_PC  = 'h1;
194.      end
195.      S_RD2:  begin
196.        sel_MEM = 'h1;
197.        case(dest)
198.          SEL_R0: load_R0 = 'h1;
199.          SEL_R1: load_R1 = 'h1;
200.          SEL_R2: load_R2 = 'h1;
201.          SEL_R3: load_R3 = 'h1;
202.          default:;
203.        endcase
204.      end
205.      S_WR1:  begin
206.        sel_MEM    = 'h1;
207.        load_add_R = 'h1;
208.        inc_PC     = 'h1;
209.      end
210.      S_WR2:  begin
211.        load_add_R = 'h1;
212.        write    = 'h1;
213.        case(src)
214.          SEL_R0: sel_R0 = 'h1;
215.          SEL_R1: sel_R1 = 'h1;
216.          SEL_R2: sel_R2 = 'h1;
217.          SEL_R3: sel_R3 = 'h1;
218.          default:;
219.        endcase
220.      end
221.      S_BR1:  begin
222.        sel_MEM    = 'h1;
223.        load_add_R = 'h1;
224.      end
225.      S_BR2:  begin
226.        sel_MEM    = 'h1;
227.        load_PC    = 'h1;
228.      end     
229.    endcase
230.  end
231. 
232. endmodule
233. 
234. `endif


相关文章
|
存储
【读书笔记】RISC存储程序机的电路设计(1)
【读书笔记】RISC存储程序机的电路设计(1)
176 1
【读书笔记】RISC存储程序机的电路设计(1)
|
存储
【读书笔记】RISC存储程序机的电路设计(2)
【读书笔记】RISC存储程序机的电路设计(2)
184 0
【读书笔记】RISC存储程序机的电路设计(2)
|
存储
【读书笔记】RISC存储程序机的电路设计(3)
【读书笔记】RISC存储程序机的电路设计(3)
120 0
【读书笔记】RISC存储程序机的电路设计(3)
|
存储 安全 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++设计新思维《一》基于策略的类设计(下)