やかんです。
とりあえず、デコーダを頑張って作ろうと思います。
そもそもデコーダとは?
ざっくり言えば、「命令セットを入力として受け取り、制御信号を出力する」装置なはず。
ほんとか?
まあ、現状の理解なので、理解に進展があったら改めます。
順々に書き始めてみる。
まずは、算術演算の命令から。
多分、まずはこんな感じになる。出力として盛り込みたい算術演算命令を列挙。
module decoder_ver2(
input[31:0] instr,
output reg[4:0] rs1,
output reg[4:0] rs2,
output reg[4:0] rd,
output reg[6:0] opcode,
output reg LUI,
output reg AUIPC,
output reg ADDI,
output reg SLTI,
output reg SLTIU,
output reg XORI,
output reg ORI,
output reg ANDI,
output reg SLLI,
output reg SRLI,
output reg SRAI,
output reg ADD,
output reg SUB,
output reg SLL,
output reg SLT,
output reg SLTU,
output reg XOR,
output reg SRL,
output reg SRA,
output reg OR,
output reg AND,
);
endmodule
で、instrから7bitのopcodeを取得して、それに応じてcase文で分岐させる。
module decoder_ver2(
input[31:0] instr,
output reg[4:0] rs1,
output reg[4:0] rs2,
output reg[4:0] rd,
output reg[6:0] opcode,
output reg LUI,
output reg AUIPC,
output reg ADDI,
output reg SLTI,
output reg SLTIU,
output reg XORI,
output reg ORI,
output reg ANDI,
output reg SLLI,
output reg SRLI,
output reg SRAI,
output reg ADD,
output reg SUB,
output reg SLL,
output reg SLT,
output reg SLTU,
output reg XOR,
output reg SRL,
output reg SRA,
output reg OR,
output reg AND,
);
always @(instr) begin
opcode = instr[6:0];
case(opcode)
7'b0110111: LUI = 1;
7'b0010111: AUIPC = 1;
7'b0010011: ADDi = 1;
// ここに記述
endcase
end
endmodule
うん。あってるかわからんが、とりあえず良さそうだ。で、ここで問題というか、一癖出てくるわけだ。
opcodeが等しいものをfunction_codeで場合分けする場合がある!
まあ、当然と言えば当然なんですが。一生懸命分岐させたものが多分こちら。
module decoder_ver2(
input[31:0] instr,
output reg[4:0] rs1,
output reg[4:0] rs2,
output reg[4:0] rd,
output reg[6:0] opcode,
output reg LUI,
output reg AUIPC,
output reg ADDI,
output reg SLTI,
output reg SLTIU,
output reg XORI,
output reg ORI,
output reg ANDI,
output reg SLLI,
output reg SRLI,
output reg SRAI,
output reg ADD,
output reg SUB,
output reg SLL,
output reg SLT,
output reg SLTU,
output reg XOR,
output reg SRL,
output reg SRA,
output reg OR,
output reg AND,
);
always @(instr) begin
opcode = instr[6:0];
case(opcode)
7'b0110111: LUI = 1;
7'b0010111: AUIPC = 1;
7'b0010011: ADDi = 1;
7'b0010011:begin
reg[2:0] funct3 = instr[14:12];
case(funct3)
3'b000: ADDI = 1;
3'b010: SLTI = 1;
3'b011: SLTIU = 1;
3'b100: XORI = 1;
3'b110: ORI = 1;
3'b111: ANDI = 1;
3'b001: SLLI = 1;
3'b101: begin
reg[6:0] funct7 = instr[31:25];
case(funct7)
7'b0000000: SRLI = 1;
7'b0100000: SRAI = 1;
endcase
end
endcase
end
7'b0110011: begin
funct3 = instr[14:12];
case(funct3)
3'b000: begin
funct7 = instr[31:25];
case(funct7)
7'0000000: ADD = 1;
7'b0100000: SUB = 1;
endcase
end
3'b001: SLL = 1;
3'b010: SLT = 1;
3'b011: SLTU = 1;
3'b100: XOR = 1;
3'b101: begin
funct7 = instr[31:25];
case(funct7)
7'0000000: SRL = 1;
7'b0100000: SRA = 1;
endcase
end
3'b110: OR = 1;
3'b111: AND = 1;
endcase
end
endcase
end
endmodule
頑張った、、、
まあ、あってるかはテストベンチ作って地道に動作確認するしかないですね。
今回のまとめ。
いや、めっちゃ大変だわ。でも、面白い。楽しい。頑張る!
次は、テストベンチ作っていい感じだったら算術演算以外の命令について一生懸命網羅する。
ということで、今回の奮闘記は終了。最後までお読みいただき、ありがとうございます。