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

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

前言

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

 

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

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

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

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

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

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

 

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

我这个顺序说实话没有太掌握好,应该在前面就把Processor的代码贴全的,不过没关系,经过前面的完整分析,我们已经直接拼出来Processor的代码啦,进而得到全部编码。

Processor完整代码

子模块

所有需要的子模块代码:

1. `ifndef PROC_UNIT
2. `define PROC_UNIT
3. 
4. module reg_unit #(
5.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
6. )(
7.  output reg [WORD_WD -1:0] data_out,
8.  input    [WORD_WD -1:0] data_in,
9.  input             load, clk, rst_n
10. );
11. 
12.   always @(posedge clk)begin
13.     if(rst_n == 1'b0)begin
14.       data_out <= {WORD_WD{1'b0}};
15.     end
16.     else if(load == 1'b1)begin
17.       if(DISPLAY_EN == 1) $display("%0t, %m, data_out update to 'b%8b('h%2h-'d%0d)", $realtime, data_in, data_in, data_in);
18.       data_out <= data_in;
19.     end
20.     else begin
21.       data_out <= data_out;
22.     end
23.   end
24. 
25. endmodule//: reg_unit
26. 
27. module program_count #(
28.   `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
29. )(
30.   output reg [WORD_WD -1:0] count_out,
31.   input    [WORD_WD -1:0] count_in,
32.   input             load, incr, clk, rst_n
33. );
34. 
35.   always @(posedge clk)begin
36.     if(rst_n == 1'b0)begin
37.       count_out <= {WORD_WD{1'b0}};
38.     end
39.     else if(load == 1'b1)begin
40.       count_out <= count_in;
41.     end
42.     else if(incr == 1'b1)begin
43.       count_out <= count_out + 'h1;
44.     end
45.     else begin
46.       count_out <= count_out;
47.     end
48.   end
49. 
50. endmodule//: program_count
51. 
52. module mux_5sel1 #(
53.   `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
54. )(
55.   output reg [WORD_WD -1:0] mux_out,
56.   input  [WORD_WD -1:0]     mux_in0, mux_in1, mux_in2, mux_in3, mux_in4,
57.   input  [SEL1_WD  -1:0]    sel
58. );
59. 
60.   always @(*)begin
61.       case(sel)
62.       'h0: mux_out = mux_in0;
63.       'h1: mux_out = mux_in1;
64.       'h2: mux_out = mux_in2;
65.       'h3: mux_out = mux_in3;
66.       'h4: mux_out = mux_in4;
67.       default: mux_out = {WORD_WD{1'bx}};
68.     endcase   
69.   end
70. 
71. endmodule//: mux_5sel1
72. 
73. module mux_3sel1 #(
74.   `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
75. )(
76.   output reg [WORD_WD -1:0] mux_out,
77.   input  [WORD_WD -1:0]     mux_in0, mux_in1, mux_in2,
78.   input  [SEL2_WD  -1:0]    sel
79. );
80. 
81.   always @(*)begin
82.       case(sel)
83.       'h0: mux_out = mux_in0;
84.       'h1: mux_out = mux_in1;
85.       'h2: mux_out = mux_in2;
86.       default: mux_out = {WORD_WD{1'bx}};
87.     endcase   
88.   end
89. 
90. endmodule//: mux_3sel1
91. 
92. module alu_unit #(
93.   `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
94. )(
95.   output reg [WORD_WD -1:0]   alu_out,
96.   output                zero_flag,
97.   input    [WORD_WD -1:0]   alu_in1, alu_in2,
98.   input    [OPCODE_WD -1:0] opcode
99. );
100. 
101.  always @(*)begin
102.    case(opcode)
103.      NOP:  alu_out = 'h0;
104.      ADD:  alu_out = alu_in2 + alu_in1;
105.      SUB:  alu_out = alu_in2 - alu_in1;    
106.      AND:  alu_out = alu_in2 & alu_in1;
107.      NOT:  alu_out = ~alu_in2;
108.      default:alu_out = 'hx;
109.    endcase
110.  end
111.  
112.  assign zero_flag = ~(|alu_out);
113. 
114. endmodule//: alu_unit
115. `endif

Processor层代码

1. `ifndef PROCESSING_UNIT
2. `define PROCESSING_UNIT
3. 
4. module processing_unit #(
5.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
6. )(
7.  output [WORD_WD -1:0] instruction ,//to ctl
8.  output            zero_flag     ,//to ctl
9. 
10.   output [ADDR_WD -1:0] addr      ,//to mem, address
11.   output [WORD_WD -1:0] bus1      ,//to mem, data_in
12. 
13.   input  [WORD_WD -1:0] mem_word    ,//from mem, data_out
14.   input           load_R0, load_R1, load_R2, load_R3,
15.   input         load_PC, 
16.   input         load_IR,
17.   input         load_reg_Y,
18.   input         load_reg_Z,
19.   input         load_add_R,
20.   input         inc_PC,
21.   input  [SEL1_WD -1:0] mux1_sel_to_bus1,
22.   input  [SEL2_WD -1:0] mux2_sel_to_bus2,
23.   input           clk, rst_n
24. );
25. 
26.   wire [WORD_WD -1:0]   bus2;
27.   wire [WORD_WD -1:0]   R0_out, R1_out, R2_out, R3_out;
28.   wire [WORD_WD -1:0]   alu_out;
29.   wire [WORD_WD -1:0]   Y_out;
30.   wire [WORD_WD -1:0]   PC_out;
31.   wire          alu_zero_flag;  
32.   wire [OPCODE_WD -1:0] opcode;
33. 
34.   assign opcode = instruction[(WORD_WD -1) : (WORD_WD -OPCODE_WD)];
35. 
36.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R0(.data_out(R0_out), .data_in(bus2), .load(load_R0), .clk(clk), .rst_n(rst_n));
37.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R1(.data_out(R1_out), .data_in(bus2), .load(load_R1), .clk(clk), .rst_n(rst_n));
38.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R2(.data_out(R2_out), .data_in(bus2), .load(load_R2), .clk(clk), .rst_n(rst_n));
39.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R3(.data_out(R3_out), .data_in(bus2), .load(load_R3), .clk(clk), .rst_n(rst_n));
40. 
41.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_REG_Y(.data_out(Y_out), .data_in(bus2), .load(load_reg_Y), .clk(clk), .rst_n(rst_n)); 
42.   reg_unit #(.WORD_WD(1))       U_REG_Z(.data_out(zero_flag), .data_in(alu_zero_flag), .load(load_reg_Z), .clk(clk), .rst_n(rst_n));
43.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_IR(.data_out(instruction), .data_in(bus2), .load(load_IR), .clk(clk), .rst_n(rst_n));
44.   reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_ADD_R(.data_out(addr), .data_in(bus2), .load(load_add_R), .clk(clk), .rst_n(rst_n));
45. 
46.   program_count #(.WORD_WD(WORD_WD)) U_PC(.count_out(PC_out), .count_in(bus2), .load(load_PC), .incr(inc_PC), .clk(clk), .rst_n(rst_n));
47. 
48.   mux_5sel1 #(.WORD_WD(WORD_WD), .SEL1_WD(SEL1_WD)) U_MUX1(
49.     .mux_out(bus1), 
50.     .mux_in0(R0_out), 
51.     .mux_in1(R1_out), 
52.     .mux_in2(R2_out), 
53.     .mux_in3(R3_out),
54.     .mux_in4(PC_out),
55.     .sel(mux1_sel_to_bus1)
56.   );
57. 
58.   mux_3sel1 #(.WORD_WD(WORD_WD), .SEL1_WD(SEL2_WD)) U_MUX2(
59.     .mux_out(bus2), 
60.     .mux_in0(alu_out), 
61.     .mux_in1(bus1), 
62.     .mux_in2(mem_word), 
63.     .sel(mux2_sel_to_bus2)
64.   );
65. 
66.   alu_unit #(.WORD_WD(WORD_WD), .OPCODE_WD(OPCODE_WD)) U_ALU(
67.     .alu_out(alu_out),
68.     .zero_flag(alu_zero_flag),
69.     .alu_in1(Y_out),
70.     .alu_in2(bus1),
71.     .opcode(opcode)
72.   );
73. endmodule//: processing_unit
74. 
75. `endif

感觉这代码写的还是挺好看的,甚至不需要做太多解释,具体实现可以参考1。

顶层代码

已经完成全部子模块代码了,那么就可以直接拼接定层了,先把参数文件贴一下:

1. parameter WORD_WD   = 8,
2. parameter MEM_SIZE  = 256,
3. parameter ADDR_WD   = $clog2(MEM_SIZE),
4. parameter OPCODE_NUM = 9,
5. parameter OPCODE_WD = $clog2(OPCODE_NUM),
6. parameter SRC_WD    = 2,
7. parameter DEST_WD   = 2,
8. 
9. parameter SEL1_NUM = 5,
10. parameter SEL2_NUM = 3,
11. parameter SEL1_WD  = $clog2(SEL1_NUM),
12. parameter SEL2_WD  = $clog2(SEL2_NUM),
13. 
14. parameter NOP = 'b0000,
15. parameter ADD = 'b0001,
16. parameter SUB = 'b0010,
17. parameter AND = 'b0011,
18. parameter NOT = 'b0100,
19. parameter RD  = 'b0101,
20. parameter WR  = 'b0110,
21. parameter BR  = 'b0111,
22. parameter BRZ = 'b0111,
23. 
24. parameter STATE_NUM = 12,
25. parameter STATE_WD  = $clog2(STATE_NUM),
26. parameter S_IDLE    = 'h0,
27. parameter S_FET1    = 'h1,
28. parameter S_FET2    = 'h2,
29. parameter S_DEC     = 'h3,
30. parameter S_EX1     = 'h4,
31. parameter S_RD1     = 'h5,
32. parameter S_RD2     = 'h6,
33. parameter S_WR1     = 'h7,
34. parameter S_WR2     = 'h8,
35. parameter S_BR1     = 'h9,
36. parameter S_BR2     = 'ha,
37. parameter S_HALT    = 'hb,
38. 
39. parameter SEL_R0 = 0,
40. parameter SEL_R1 = 1,
41. parameter SEL_R2 = 2,
42. parameter SEL_R3 = 3,
43. 
44. parameter DISPLAY_EN = 0

接下来就是定层代码:

1. module RISC_SPM #(
2.  `include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
3. )(
4.  input clk, rst_n
5. );
6. 
7.  wire            ctrl2proc_load_R0;
8.  wire            ctrl2proc_load_R1;
9.  wire          ctrl2proc_load_R2;
10.   wire          ctrl2proc_load_R3;
11.   wire          ctrl2proc_load_PC;
12.   wire            ctrl2proc_load_IR;
13.   wire          ctrl2proc_load_reg_Y;
14.   wire          ctrl2proc_load_reg_Z;
15.   wire          ctrl2proc_load_add_R;
16.   wire          ctrl2proc_inc_PC;
17.   wire [SEL1_WD -1:0]   ctrl2proc_mux1_sel_to_bus1;
18.   wire [SEL2_WD -1:0]   ctrl2proc_mux2_sel_to_bus2;
19. 
20.   wire          ctrl2mem_write;
21.   wire [WORD_WD -1:0]   mem2proc_data;
22. 
23.   wire [WORD_WD -1:0]   proc2ctrl_instruction;
24.   wire            proc2ctrl_zero_flag;
25. 
26.   wire [ADDR_WD -1:0]   proc2mem_addr;
27.   wire [WORD_WD -1:0]   proc2mem_data;
28. 
29.   ctrl_unit U_CTRL(
30.     .load_R0(ctrl2proc_load_R0), 
31.     .load_R1(ctrl2proc_load_R1), 
32.     .load_R2(ctrl2proc_load_R2), 
33.     .load_R3(ctrl2proc_load_R3),
34.     .load_PC(ctrl2proc_load_PC), 
35.     .load_IR(ctrl2proc_load_IR),
36.     .load_reg_Y(ctrl2proc_load_reg_Y),
37.     .load_reg_Z(ctrl2proc_load_reg_Z),
38.     .load_add_R(ctrl2proc_load_add_R),
39.     .inc_PC(ctrl2proc_inc_PC),  
40.     .mux1_sel_to_bus1(ctrl2proc_mux1_sel_to_bus1),
41.     .mux2_sel_to_bus2(ctrl2proc_mux2_sel_to_bus2),
42. 
43.     .write(ctrl2mem_write),
44. 
45.     .instruction(proc2ctrl_instruction),
46.     .zero_flag(proc2ctrl_zero_flag),
47.     .clk(clk),
48.     .rst_n(rst_n)
49.   );
50. 
51.   processing_unit U_PROCESSING(
52.     .instruction(proc2ctrl_instruction),
53.     .zero_flag(proc2ctrl_zero_flag),
54. 
55.     .addr(proc2mem_addr),
56.     .bus1(proc2mem_data),
57. 
58.     .mem_word(mem2proc_data),
59.     .load_R0(ctrl2proc_load_R0), 
60.     .load_R1(ctrl2proc_load_R1), 
61.     .load_R2(ctrl2proc_load_R2), 
62.     .load_R3(ctrl2proc_load_R3),
63.     .load_PC(ctrl2proc_load_PC), 
64.     .load_IR(ctrl2proc_load_IR),
65.     .load_reg_Y(ctrl2proc_load_reg_Y),
66.     .load_reg_Z(ctrl2proc_load_reg_Z),
67.     .load_add_R(ctrl2proc_load_add_R),
68.     .inc_PC(ctrl2proc_inc_PC),
69.     .mux1_sel_to_bus1(ctrl2proc_mux1_sel_to_bus1),
70.     .mux2_sel_to_bus2(ctrl2proc_mux2_sel_to_bus2),
71.     .clk(clk), 
72.     .rst_n(rst_n)
73.   );
74. 
75.   mem_unit #(.DISPLAY_EN(1)) U_MEM(
76.     .data_out(mem2proc_data),
77.     .data_in(proc2mem_data),
78.     .addr_in(proc2mem_addr),
79.     .write_en(ctrl2mem_write),
80.     .clk(clk),
81.     .rst_n(rst_n)
82.   );
83. 
84. endmodule

可以很清楚的看到,定层只有两个接口信号:clk和rst_n,也就是说软件与处理器交互,全部都是通过mem中存储指令,再从mem中读取结果来完成的。


相关文章
|
1月前
|
存储
【头歌·计组·自己动手画CPU】五、单总线CPU设计(理论版) 【计算机硬件系统设计】
【头歌·计组·自己动手画CPU】五、单总线CPU设计(理论版) 【计算机硬件系统设计】
448 2
|
1月前
|
存储 人工智能 缓存
计算机架构:漫游CPU的奥秘世界(一)
计算机架构:漫游CPU的奥秘世界
79 0
|
1月前
|
存储 人工智能 并行计算
计算机架构:漫游CPU的奥秘世界(二)
计算机架构:漫游CPU的奥秘世界
82 0
|
存储
【读书笔记】RISC存储程序机的电路设计(1)
【读书笔记】RISC存储程序机的电路设计(1)
138 1
【读书笔记】RISC存储程序机的电路设计(1)
|
存储 前端开发 Linux
(上)【数字IC精品文章收录】近500篇文章|学习路线|基础知识|接口|总线|脚本语言|芯片求职|安全|EDA|工具|低功耗设计|Verilog|低功耗|STA|设计|验证|FPGA|架构|AMBA|书籍|
【数字IC精品文章收录】近500篇文章|学习路线|基础知识|接口|总线|脚本语言|芯片求职|安全|EDA|工具|低功耗设计|Verilog|低功耗|STA|设计|验证|FPGA|架构|AMBA|书籍|
(上)【数字IC精品文章收录】近500篇文章|学习路线|基础知识|接口|总线|脚本语言|芯片求职|安全|EDA|工具|低功耗设计|Verilog|低功耗|STA|设计|验证|FPGA|架构|AMBA|书籍|
|
存储 索引
【读书笔记】RISC存储程序机的电路设计(4)
【读书笔记】RISC存储程序机的电路设计(4)
173 0
【读书笔记】RISC存储程序机的电路设计(4)
|
存储 测试技术 索引
【读书笔记】RISC存储程序机的电路设计(6)
【读书笔记】RISC存储程序机的电路设计(6)
136 0
【读书笔记】RISC存储程序机的电路设计(6)
|
存储
【读书笔记】RISC存储程序机的电路设计(2)
【读书笔记】RISC存储程序机的电路设计(2)
154 0
【读书笔记】RISC存储程序机的电路设计(2)
|
存储
【读书笔记】RISC存储程序机的电路设计(3)
【读书笔记】RISC存储程序机的电路设计(3)
【读书笔记】RISC存储程序机的电路设计(3)
|
芯片 异构计算
FPGA硬件工程师Verilog面试题(基础篇二)
FPGA硬件工程师Verilog面试题(基础篇二)
377 1
FPGA硬件工程师Verilog面试题(基础篇二)