前言
继续来~~~~~~~~~~~~~~~~~~~~~~
图放好~~~~~~~~~~~~~~~~~~~~~~
我这个顺序说实话没有太掌握好,应该在前面就把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中读取结果来完成的。