Tác giả: TrongTran
Ngày: 14/10/2019Tài liệu tham khảo: www-inst.eecs.berkeley.edu/~cs61c/fa18/img/riscvcard.pdf và tài liệu học tập từ trường đại học Bách Khoa TP.HCM (Bộ môn Điện-Điện tử).
Đây là một bài nằm trong chuỗi bài hướng dẫn thiết kế 1 CPU RISC-V 32 bit.
Như các bạn đã biết, trong bài trước mình đã hướng dẫn chi tiết về datapath và cấu trúc của các câu lệnh nhóm R-format (http://trongtranrvc.blogspot.com/2019/09/designthiet-ke-cpu-32-bit-bai-2-tim_17.html).
Bài này, Mình tiếp tục hướng dẫn về datapath và cấu trúc nhóm lệnh I-format.
Các bạn lưu ý cấu trúc trong bài này chỉ dành riêng cho các câu lệnh “addi, subi, andi, ori ,xori, slli, srli, srai, slti”.
Các câu lệnh khác mình sẽ nói trong bài tiếp theo.
Đừng nhầm lẫn giữa các câu lệnh nhóm R-format trong bài 3 và nhóm I-format trong bài này nhé.
Dưới đây là bảng nhóm câu lệnh I-format:
Cú pháp nhóm câu lệnh I-format là:
instruction rd, rs1, A
Hoặc
instruction rd, rs1, rs2 (cho lệnh slli, srli, srai)
Trong đó “instruction” là các lệnh “addi, ori, xori….” trong bảng trên.
rd, rs1, rs2 : là các thanh ghi.
A là một số nguyên được biểu diễn bởi 12 bit.
Nhóm lệnh này có opcode là [6:0] = 0010011. Các lệnh I-format (trừ 3 lệnh SRAI, SRLI, SLLI) thực hiện lấy giá trị lưu ở thanh ghi rs1 và giá trị lưu ở imm[11:0] (được mở rộng dấu từ 12 bit thành 32 bit), thực hiện đưa vào khối ALU để tính toán. Kết quả được lưu vào thanh ghi rd trong khối REG.
Như trong bảng trên giá trị imm là một số 12 bit (Nghĩa là giá trị đưa vào nằm trong khoảng
[-(2^(n-1)): (2^(n-1)) – 1] = [-2048:2047]
Một điều đặc biệt trong bảng trên nữa là có 3 câu lệnh slli, srli, srai không dùng imm[11:0] mà dùng thành ghi.
Giá trị shamt được biểu diễn bởi 5 bit data biểu diễn cho các thanh ghi từ R0 đến R31.
instruction rd, rs1, A
Hoặc
instruction rd, rs1, rs2 (cho lệnh slli, srli, srai)
Trong đó “instruction” là các lệnh “addi, ori, xori….” trong bảng trên.
rd, rs1, rs2 : là các thanh ghi.
A là một số nguyên được biểu diễn bởi 12 bit.
Nhóm lệnh này có opcode là [6:0] = 0010011. Các lệnh I-format (trừ 3 lệnh SRAI, SRLI, SLLI) thực hiện lấy giá trị lưu ở thanh ghi rs1 và giá trị lưu ở imm[11:0] (được mở rộng dấu từ 12 bit thành 32 bit), thực hiện đưa vào khối ALU để tính toán. Kết quả được lưu vào thanh ghi rd trong khối REG.
Như trong bảng trên giá trị imm là một số 12 bit (Nghĩa là giá trị đưa vào nằm trong khoảng
[-(2^(n-1)): (2^(n-1)) – 1] = [-2048:2047]
Một điều đặc biệt trong bảng trên nữa là có 3 câu lệnh slli, srli, srai không dùng imm[11:0] mà dùng thành ghi.
Giá trị shamt được biểu diễn bởi 5 bit data biểu diễn cho các thanh ghi từ R0 đến R31.
Nhóm câu lệnh R-format (trong bài 3) và 3 lệnh slli, srli, srai sẽ sử dùng path màu xanh trong hình trên. Inst[24:20] là 5 bit biểu diễn cho thanh ghi rs2 (giá trị từ 0 -> 31 đi vào khối Reg, dựa vào tên thanh ghi, khối reg sẽ trích xuất giá trị 32 bit ra và đưa vào khối ALU để tính toán).
Các nhóm lệnh I-fromat còn lại không dùng path màu xanh mà dùng path màu tím.
12 bit data inst[31:20] được đưa vào khối imm. Khối này có chức năng đó là mở rông bit dấu từ 1 giá trị 12 bit sang một giá trị 32 bit data rồi đưa vào khối ALU để tiến hành tính toán.
Các khối còn lại thức hiện các bước tương tự như bài 3.
Mình tóm lại các bước thực hiện khối lệnh I-format trong RISC-V như sau:
- Giá trị PC được đưa vào IMEM (Cũng có thể xem giá trị PC là ADDRESS, Và khối IMEM sẽ đưa ra giá trị lưu tại address đó). IMEM sẽ gửi ra một chuổi 32 bit. Chuỗi này mang một ý nghĩa nhất định là các câu lệnh theo mã nhị phân.
- 32 bit out từ IMEM sẽ được phân tích theo các vị trí riêng và gửi vào khối REG, Khối IMM.
- Khối IMM sẽ mở rộng bit dấu cho 12 bit data đưa vào thành 32 bit data và gửi sang khối ALU cho việc tính toán.
- Khối ALU tính toán kết quả và gửi về khối REG nhằm lưu kết quả vào thanh ghi rd.
- Lúc này PC = PC + 4. Để tiếp tục đọc câu lệnh tiếp theo.
Bên dưới là RTL cho khối IMM:
//Author: TrongTran
module imm (Imm_in, Imm_out, ImmSel);
input [24:0] Imm_in;
input [2:0] ImmSel;
output [31:0] Imm_out;
wire [31:0] Imm_out;
assign Imm_out = (ImmSel==3'b000)? {{21{Imm_in[24]}},Imm_in[23:13]}:
(ImmSel==3'b001)? {{21{Imm_in[24]}},Imm_in[23:18], Imm_in[4:0]}:
(ImmSel==3'b010)? {{20{Imm_in[24]}}, Imm_in[0], Imm_in[23:18],Imm_in[4:1], 1'b0} :
(ImmSel==3'b011)? {Imm_in[24:5], {12{1'b0}}} :
(ImmSel==3'b100)? {{21{Imm_in[24]}},Imm_in[23:13]} :
(ImmSel==3'b101)? {{13{Imm_in[24]}}, Imm_in[12:5], Imm_in[13], Imm_in[23:14],1'b0} : 32'h0000_0000;
endmodule
Code này mình đưa vào input 25 bit chứ không phải 12 bit như đề cập bên trên. Lí do là nó support cho những câu lệnh khác nữa.
ImmSel là tín hiệu control từ khối control. Tín hiệu này sẽ cho biết đây là câu lệnh gì và khối imm sẽ dựa vào đó để mở rộng bit cho đúng tuỳ vào loại câu lệnh.
Nếu bài của mình có sai sót gì mong nhận được sự góp
ý nhiệt tình từ mọi người. Vì bản thân không phải là chuyên gia, cũng mài mò học
hỏi nên không tránh khỏi sai sót.
No comments:
Post a Comment