--- tags: RISCV, 伴學松, 伴學松活動記錄 --- # 從0到有製作自己的CPU!! 第五周活動記錄 20220802 [TOC] # 直播紀錄連結 {%youtube xtWN4o8P8T0 %} ## 出席 - [x] KIM_WENG - [x] 名名 - [x] chuan - [x] bill503084699 - [x] 楓糖 - [x] 謝祥辰 - [x] 黑貓 - [x] sixkwnp - [ ] Bonki - [x] ouo314 - [x] Willwho - [x] GYLABA - [x] mikuthebest - [x] Penquuin - [x] 葉子 - [ ] painCake - [x] EZ4ENCE - [ ] 頂漿汗腺 - [x] 角角 - [ ] adam chen # 討論內容 1. [複習過往的三大模塊](https://hackmd.io/@accomdemy/ryBEZA2nq) 2. 寫code與操作 3. Decode回顧 4. 播[Register影片](https://www.youtube.com/watch?v=ON4aFtNiEwE&ab_channel=NTHUOCW) # 本周作業 1. 嘗試寫出三大模塊並且兜出來的code # 討論重點 - 1.複習三個模塊與試著兜起來 - 2.嘗試操作code去寫出來 ## 點子 / 撇步 - bill講述大致上學到的所有模塊共筆 [name=第一組] - 看教授的影片 [name=第一組] - 控制reg data [name=第一組] - 名名 寫code [name=第一組] - 先寫module [name=第一組] - 然後先設定輸入跟輸出的 [name=第一組] - 複習risc-v [name=第一組] - 先寫decode [name=第一組] **Decoder** ```verilog= module decode( input [31:0] instr, output reg[4:0] rs1_addr, output reg[4:0] rs2_addr, output reg[4:0] wt_addr output reg[2:0] aluop, output reg r1_enable, output reg r2_enable, output reg wt_enable, output reg imm_enable, ); always @(*) begin case(instr[6:0]) 7'b0110011 begin //Rtype rs1_addr = instr[19:15]; //rs1_addr rs2_addr = instr[24:20]; //rs2_addr wt_addr = instr[11:7]; //rd r1_enable = 1'b1; r2_enable = 1'b1; wt_enable = 1'b1; imm_enable = 1'b0; case(instr[14:12]) //Func3 3'b000: //add / sub case(instr[31:25]) //Func7 7'b0000000: //add aluop = 3'b000; //add 7'b0100000: //sub aluop = 3'b001; default: aluop = 3'b000; //add endcase 3'b111: //and aluop = 3'b100; 3'b110: //or aluop = 3'b101; 3'100: //xor aluop = 3'b111; default: aluop = 3'b000; //add endcase end default: aluop = 3'b000; //add endcase end endmodule ``` **ALU** ```verilog= module alu( input [31:0] a, input [31:0] b, input [31:0] op, output reg[31:0] y, ); always@(*) begin case(op) 3'b000: y = a + b; 3'b001: y = a - b; 3'b010: y = a * b; // RV32I規範中未包含乘法 3'b011: y = a / b; // RV32I規範中未包含除法 3'b100: y = a & b; 3'b101: y = a | b; 3'b110: y = !a; // RV32I規範中未包含NOT 3'b111: y = a ^ b; default: y = 0; endcase end endmodule ``` **Register** ```verilog= module regfile( input clk, input wt_enable, input r1_enable, input r2_enable, input rst, input [4:0] rs1_addr, input [4:0] rs2_addr, input [4:0] wt_addr, input [31:0] wt_data, output reg[31:0] rs1, output reg[31:0] rs2, ); reg [31:0] regfile[31:0]; always@(posedge clk) begin if(!rst) begin if(wt_enable && wt_addr!=0) begin regfile[wt_addr]<=wt_data; end end end always@(*) begin //rs1 if(r1_enable && rs1_addr==0) rs1=0; else if(wt_enable && r1_enable && rs1_addr!=0) rs1 = wt_data; else if(r1_enable && rs1_addr!=0) rs1= regfile[rs1_addr]; else rs1 = 0; end always@(*) begin if(r2_enable && rs2_addr==0) rs2=0; else if(wt_enable && r2_enable && rs2_addr!=0) rs2 = wt_data; else if(r2_enable && rs2_addr!=0) rs2= regfile[rs2_addr]; else rs2 = 0; end endmodule ``` - 再寫 rv32i [name=第一組] **RV32I(decoder, register, alu)** ```verilog= module rv32i( input clk, input reset, ); wire [31:0] INST; wire [4:0] RS1_ADD; wire [4:0] RS2_ADD; wire [4:0] WT_ADD; wire [2:0] OPCODE; wire RS1_ENAB; wire RS2_ENAB; wire WT_ENAB; wire IMM_ENAB; //register - alu wire [31:0] RS1; wire [31:0] RS2; wire [31:0] WT_DAT; //decoder - selecter wire [4:0] DATA2; decode decoder( .instr(INST), .rs1_addr(RS1_ADD), .rs2_addr(RS2_ADD), .wt_addr(WT_ADD), .aluop(OPCODE), .r1_enable(RS1_ENAB), .r2_enable(RS2_ENAB), .wt_enable(WT_ENAB), .imm_enable(IMM_ENAB), ); regfile register( //self .clk(clk), .rst(reset), //decoder .wt_enable(WT_ENAB), .r1_enable(RS1_ENAB), .r2_enable(RS2_ENAB), .rs1_addr(RS1_ADD), .rs2_addr(RS2_ADD), .wt_addr(WT_ADD), //alu .wt_data(WT_DAT), .rs1(RS1), .rs2(RS2), ); alu alu1( .a(RS1), .b(DATA2), .op(OPCODE), .y(WT_DATA), ); if(IMM_ENAB) DATA2 = RS2_ADD; else DATA2 = RS2; endmodule ```