Add initial fetch/decode stages
This commit is contained in:
commit
4a4dee334d
10 changed files with 400 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.*
|
||||
*~
|
||||
*.asc
|
||||
*.bin
|
||||
*.blif
|
||||
!.git*
|
||||
!.mailmap
|
||||
37
Makefile
Normal file
37
Makefile
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
QUIET = -q
|
||||
SRC = $(wildcard *.sv)
|
||||
TOP = top
|
||||
YS = $(TOP).ys
|
||||
BLIF = $(TOP).blif
|
||||
ASC = $(TOP).asc
|
||||
BIN = $(TOP).bin
|
||||
SPEED = hx
|
||||
DEVICE = 8k
|
||||
PACKAGE = ct256
|
||||
PCF = ice40hx8k-b-evn.pcf
|
||||
FREQ_OSC = 12
|
||||
|
||||
.PHONY: all clean time stat flash
|
||||
|
||||
all: $(TOP).bin
|
||||
|
||||
clean:
|
||||
$(RM) $(BLIF) $(ASC) $(BIN)
|
||||
|
||||
$(BLIF): $(YS) $(SRC)
|
||||
yosys $(QUIET) -s $<
|
||||
|
||||
$(ASC): $(BLIF) $(PCF)
|
||||
arachne-pnr $(QUIET) -d $(DEVICE) -P $(PACKAGE) -o $@ -p $(PCF) $<
|
||||
|
||||
$(BIN): $(ASC)
|
||||
icepack $< $@
|
||||
|
||||
time: $(ASC) $(PCF)
|
||||
icetime -t -m -d $(SPEED)$(DEVICE) -P $(PACKAGE) -p $(PCF) -c $(FREQ_OSC) $<
|
||||
|
||||
stat: $(ASC)
|
||||
icebox_stat $<
|
||||
|
||||
flash: $(BIN)
|
||||
iceprog -S $<
|
||||
1
ice40hx8k-b-evn.pcf
Normal file
1
ice40hx8k-b-evn.pcf
Normal file
|
|
@ -0,0 +1 @@
|
|||
set_io clk J3
|
||||
25
rv32.sv
Normal file
25
rv32.sv
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
`include "rv32_decode.sv"
|
||||
`include "rv32_fetch.sv"
|
||||
|
||||
module rv32 (
|
||||
input logic clk
|
||||
);
|
||||
rv32_fetch fetch (
|
||||
.clk(clk),
|
||||
|
||||
/* data out */
|
||||
.pc_out(fetch_pc),
|
||||
.instr_out(fetch_instr)
|
||||
);
|
||||
|
||||
logic [31:0] fetch_pc;
|
||||
logic [31:0] fetch_instr;
|
||||
|
||||
rv32_decode decode (
|
||||
.clk(clk),
|
||||
|
||||
/* data in */
|
||||
.pc_in(fetch_pc),
|
||||
.instr_in(fetch_instr)
|
||||
);
|
||||
endmodule
|
||||
227
rv32_decode.sv
Normal file
227
rv32_decode.sv
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
`include "rv32_opcodes.sv"
|
||||
`include "rv32_regs.sv"
|
||||
|
||||
module rv32_decode (
|
||||
input logic clk,
|
||||
|
||||
/* data in */
|
||||
input logic [31:0] pc_in,
|
||||
input logic [31:0] instr_in,
|
||||
|
||||
/* control out */
|
||||
output logic valid,
|
||||
|
||||
/* data out */
|
||||
output logic [31:0] pc_out,
|
||||
output logic [31:0] rs1_value_out,
|
||||
output logic [31:0] rs2_value_out,
|
||||
output logic [31:0] imm_out
|
||||
);
|
||||
logic [6:0] funct7 = instr_in[31:25];
|
||||
logic [4:0] rs2 = instr_in[24:20];
|
||||
logic [4:0] rs1 = instr_in[19:15];
|
||||
logic [2:0] funct3 = instr_in[14:12];
|
||||
logic [4:0] rd = instr_in[11:7];
|
||||
logic [6:0] opcode = instr_in[6:0];
|
||||
|
||||
logic sign = instr_in[31];
|
||||
|
||||
logic [31:0] imm_i = {{21{sign}}, instr_in[30:25], instr_in[24:21], instr_in[20]};
|
||||
logic [31:0] imm_s = {{21{sign}}, instr_in[30:25], instr_in[11:8], instr_in[7]};
|
||||
logic [31:0] imm_b = {{20{sign}}, instr_in[7], instr_in[30:25], instr_in[11:8], 1'b0};
|
||||
logic [31:0] imm_u = {sign, instr_in[30:20], instr_in[19:12], 12'b0};
|
||||
logic [31:0] imm_j = {{12{sign}}, instr_in[19:12], instr_in[20], instr_in[30:25], instr_in[24:1], 1'b0};
|
||||
|
||||
rv32_regs regs (
|
||||
.clk(clk),
|
||||
.rs1_in(rs1),
|
||||
.rs2_in(rs2),
|
||||
.rs1_value_out(rs1_value_out),
|
||||
.rs2_value_out(rs2_value_out)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
pc_out <= pc_in;
|
||||
|
||||
valid <= 0;
|
||||
imm_out <= 32'bx;
|
||||
|
||||
casez ({opcode, funct3, funct7})
|
||||
{RV32_OPCODE_LUI, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
|
||||
/* LUI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_u;
|
||||
end
|
||||
{RV32_OPCODE_AUIPC, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
|
||||
/* AUIPC */
|
||||
valid <= 1;
|
||||
imm_out <= imm_u;
|
||||
end
|
||||
{RV32_OPCODE_JAL, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
|
||||
/* JAL */
|
||||
valid <= 1;
|
||||
imm_out <= imm_j;
|
||||
end
|
||||
{RV32_OPCODE_JALR, RV32_FUNCT3_ZERO, RV32_FUNCT7_ANY}: begin
|
||||
/* JALR */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BEQ, RV32_FUNCT7_ANY}: begin
|
||||
/* BEQ */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BNE, RV32_FUNCT7_ANY}: begin
|
||||
/* BNE */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLT, RV32_FUNCT7_ANY}: begin
|
||||
/* BLT */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGE, RV32_FUNCT7_ANY}: begin
|
||||
/* BGE */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLTU, RV32_FUNCT7_ANY}: begin
|
||||
/* BLTU */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGEU, RV32_FUNCT7_ANY}: begin
|
||||
/* BGEU */
|
||||
valid <= 1;
|
||||
imm_out <= imm_b;
|
||||
end
|
||||
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LB, RV32_FUNCT7_ANY}: begin
|
||||
/* LB */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LH, RV32_FUNCT7_ANY}: begin
|
||||
/* LH */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LW, RV32_FUNCT7_ANY}: begin
|
||||
/* LW */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LBU, RV32_FUNCT7_ANY}: begin
|
||||
/* LBU */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LHU, RV32_FUNCT7_ANY}: begin
|
||||
/* LHU */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SB, RV32_FUNCT7_ANY}: begin
|
||||
/* SB */
|
||||
valid <= 1;
|
||||
imm_out <= imm_s;
|
||||
end
|
||||
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SH, RV32_FUNCT7_ANY}: begin
|
||||
/* SH */
|
||||
valid <= 1;
|
||||
imm_out <= imm_s;
|
||||
end
|
||||
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SW, RV32_FUNCT7_ANY}: begin
|
||||
/* SW */
|
||||
valid <= 1;
|
||||
imm_out <= imm_s;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ANY}: begin
|
||||
/* ADDI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ANY}: begin
|
||||
/* SLTI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ANY}: begin
|
||||
/* SLTIU */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ANY}: begin
|
||||
/* XORI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ANY}: begin
|
||||
/* ORI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ANY}: begin
|
||||
/* ANDI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
|
||||
/* SLLI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
|
||||
/* SRLI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
|
||||
/* SRAI */
|
||||
valid <= 1;
|
||||
imm_out <= imm_i;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ZERO}: begin
|
||||
/* ADD */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_OP_SUB}: begin
|
||||
/* SUB */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
|
||||
/* SLL */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ZERO}: begin
|
||||
/* SLT */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ZERO}: begin
|
||||
/* SLTU */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ZERO}: begin
|
||||
/* XOR */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
|
||||
/* SRL */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
|
||||
/* SRA */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ZERO}: begin
|
||||
/* OR */
|
||||
valid <= 1;
|
||||
end
|
||||
{RV32_OPCODE_OP, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ZERO}: begin
|
||||
/* AND */
|
||||
valid <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
16
rv32_fetch.sv
Normal file
16
rv32_fetch.sv
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
module rv32_fetch (
|
||||
input logic clk,
|
||||
|
||||
/* data out */
|
||||
output logic [31:0] pc_out,
|
||||
output logic [31:0] instr_out
|
||||
);
|
||||
logic [31:0] instr_mem [255:0];
|
||||
logic [31:0] pc;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
instr_out <= instr_mem[pc[31:2]];
|
||||
pc <= pc + 4;
|
||||
pc_out <= pc;
|
||||
end
|
||||
endmodule
|
||||
46
rv32_opcodes.sv
Normal file
46
rv32_opcodes.sv
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
localparam RV32_OPCODE_LOAD = 7'b0000011;
|
||||
localparam RV32_OPCODE_MISC_MEM = 7'b0001111;
|
||||
localparam RV32_OPCODE_OP_IMM = 7'b0010011;
|
||||
localparam RV32_OPCODE_AUIPC = 7'b0010111;
|
||||
localparam RV32_OPCODE_STORE = 7'b0100011;
|
||||
localparam RV32_OPCODE_OP = 7'b0110011;
|
||||
localparam RV32_OPCODE_LUI = 7'b0110111;
|
||||
localparam RV32_OPCODE_BRANCH = 7'b1100011;
|
||||
localparam RV32_OPCODE_JALR = 7'b1100111;
|
||||
localparam RV32_OPCODE_JAL = 7'b1101111;
|
||||
localparam RV32_OPCODE_SYSTEM = 7'b1110011;
|
||||
|
||||
localparam RV32_FUNCT3_ANY = 3'b???;
|
||||
localparam RV32_FUNCT3_ZERO = 3'b000;
|
||||
|
||||
localparam RV32_FUNCT3_BRANCH_BEQ = 3'b000;
|
||||
localparam RV32_FUNCT3_BRANCH_BNE = 3'b001;
|
||||
localparam RV32_FUNCT3_BRANCH_BLT = 3'b100;
|
||||
localparam RV32_FUNCT3_BRANCH_BGE = 3'b101;
|
||||
localparam RV32_FUNCT3_BRANCH_BLTU = 3'b110;
|
||||
localparam RV32_FUNCT3_BRANCH_BGEU = 3'b111;
|
||||
|
||||
localparam RV32_FUNCT3_LOAD_LB = 3'b000;
|
||||
localparam RV32_FUNCT3_LOAD_LH = 3'b001;
|
||||
localparam RV32_FUNCT3_LOAD_LW = 3'b010;
|
||||
localparam RV32_FUNCT3_LOAD_LBU = 3'b100;
|
||||
localparam RV32_FUNCT3_LOAD_LHU = 3'b101;
|
||||
|
||||
localparam RV32_FUNCT3_STORE_SB = 3'b000;
|
||||
localparam RV32_FUNCT3_STORE_SH = 3'b001;
|
||||
localparam RV32_FUNCT3_STORE_SW = 3'b010;
|
||||
|
||||
localparam RV32_FUNCT3_OP_ADD_SUB = 3'b000;
|
||||
localparam RV32_FUNCT3_OP_SLL = 3'b001;
|
||||
localparam RV32_FUNCT3_OP_SLT = 3'b010;
|
||||
localparam RV32_FUNCT3_OP_SLTU = 3'b011;
|
||||
localparam RV32_FUNCT3_OP_XOR = 3'b100;
|
||||
localparam RV32_FUNCT3_OP_SRL_SRA = 3'b101;
|
||||
localparam RV32_FUNCT3_OP_OR = 3'b110;
|
||||
localparam RV32_FUNCT3_OP_AND = 3'b111;
|
||||
|
||||
localparam RV32_FUNCT7_ANY = 7'b???????;
|
||||
localparam RV32_FUNCT7_ZERO = 7'b0000000;
|
||||
|
||||
localparam RV32_FUNCT7_OP_SRA = 7'b0100000;
|
||||
localparam RV32_FUNCT7_OP_SUB = 7'b0100000;
|
||||
26
rv32_regs.sv
Normal file
26
rv32_regs.sv
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
module rv32_regs (
|
||||
input logic clk,
|
||||
|
||||
/* control in */
|
||||
input logic [4:0] rs1_in,
|
||||
input logic [4:0] rs2_in,
|
||||
input logic [4:0] rd_in,
|
||||
input logic rd_writeback_in,
|
||||
|
||||
/* data in */
|
||||
input logic [31:0] rd_value_in,
|
||||
|
||||
/* data out */
|
||||
output logic [31:0] rs1_value_out,
|
||||
output logic [31:0] rs2_value_out
|
||||
);
|
||||
logic [31:0] regs [31:0];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
rs1_value_out <= regs[rs1_in];
|
||||
rs2_value_out <= regs[rs2_in];
|
||||
|
||||
if (rd_writeback_in && |rd_in)
|
||||
regs[rd_in] <= rd_value_in;
|
||||
end
|
||||
endmodule
|
||||
9
top.sv
Normal file
9
top.sv
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
`include "rv32.sv"
|
||||
|
||||
module top (
|
||||
input logic clk
|
||||
);
|
||||
rv32 rv32 (
|
||||
.clk(clk)
|
||||
);
|
||||
endmodule
|
||||
6
top.ys
Normal file
6
top.ys
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
read_verilog -sv top.sv
|
||||
proc
|
||||
opt
|
||||
alumacc
|
||||
share -aggressive
|
||||
synth_ice40 -top top -blif top.blif
|
||||
Loading…
Reference in a new issue