---
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
```