Add initial fetch/decode stages

This commit is contained in:
Graham Edgecombe 2017-11-30 22:30:49 +00:00
commit 4a4dee334d
10 changed files with 400 additions and 0 deletions

7
.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
.*
*~
*.asc
*.bin
*.blif
!.git*
!.mailmap

37
Makefile Normal file
View 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
View file

@ -0,0 +1 @@
set_io clk J3

25
rv32.sv Normal file
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,9 @@
`include "rv32.sv"
module top (
input logic clk
);
rv32 rv32 (
.clk(clk)
);
endmodule

6
top.ys Normal file
View file

@ -0,0 +1,6 @@
read_verilog -sv top.sv
proc
opt
alumacc
share -aggressive
synth_ice40 -top top -blif top.blif