passes quick tests for: lui, addi, add, sub, and, or, xor, andi. jump works but does not link
This commit is contained in:
188
hdl/core.v
188
hdl/core.v
@ -1,23 +1,77 @@
|
||||
module core(
|
||||
input clk,
|
||||
input reset,
|
||||
output dummy_out,
|
||||
|
||||
output reg [31:0] mem_inst_addr,
|
||||
input [31:0] mem_inst_data,
|
||||
|
||||
output reg [31:0] mem_data_addr,
|
||||
output reg [31:0] mem_data_wdata,
|
||||
input [31:0] mem_data_rdata,
|
||||
output reg mem_data_en,
|
||||
output reg mem_data_we,
|
||||
input mem_data_valid,
|
||||
input mem_data_done
|
||||
// output reg [31:0] mem_data_addr,
|
||||
// output reg [31:0] mem_data_wdata,
|
||||
// input [31:0] mem_data_rdata,
|
||||
// output reg mem_data_en,
|
||||
// output reg mem_data_we,
|
||||
// input mem_data_valid,
|
||||
// input mem_data_done
|
||||
|
||||
|
||||
// // instruction memory
|
||||
// output axi_inst_ACLK,
|
||||
// output axi_inst_ARESETn,
|
||||
// output axi_inst_AWVALID,
|
||||
// output axi_inst_AWADDR,
|
||||
// output [2:0] axi_inst_AWPROT,
|
||||
// input axi_inst_AWREADY,
|
||||
// output axi_inst_WVALID,
|
||||
// output [DATA_WIDTH-1:0] axi_inst_WDATA,
|
||||
// output [(DATA_WIDTH/8)-1:0] axi_inst_WSTRB,
|
||||
// input axi_inst_WREADY,
|
||||
// input axi_inst_BVALID,
|
||||
// output axi_inst_BREADY,
|
||||
// input [1:0] axi_inst_BRESP,
|
||||
// output axi_inst_ARVALID,
|
||||
// output axi_inst_ARADDR,
|
||||
// output [2:0] axi_inst_ARPROT,
|
||||
// input axi_inst_ARREADY,
|
||||
// input axi_inst_RVALID,
|
||||
// input [DATA_WIDTH-1:0] axi_inst_RDATA,
|
||||
// input [1:0] axi_inst_RRESP,
|
||||
// output axi_inst_RREADY,
|
||||
|
||||
|
||||
// data memory
|
||||
// output axi_data_ACLK,
|
||||
// output axi_data_ARESETn,
|
||||
// output axi_data_AWVALID,
|
||||
// output axi_data_AWADDR,
|
||||
// output [2:0] axi_data_AWPROT,
|
||||
// input axi_data_AWREADY,
|
||||
// output axi_data_WVALID,
|
||||
// output [DATA_WIDTH-1:0] axi_data_WDATA,
|
||||
// output [(DATA_WIDTH/8)-1:0] axi_data_WSTRB,
|
||||
// input axi_data_WREADY,
|
||||
// input axi_data_BVALID,
|
||||
// output axi_data_BREADY,
|
||||
// input [1:0] axi_data_BRESP,
|
||||
// output axi_data_ARVALID,
|
||||
// output axi_data_ARADDR,
|
||||
// output [2:0] axi_data_ARPROT,
|
||||
// input axi_data_ARREADY,
|
||||
// input axi_data_RVALID,
|
||||
// input [DATA_WIDTH-1:0] axi_data_RDATA,
|
||||
// input [1:0] axi_data_RRESP,
|
||||
// output axi_data_RREADY,
|
||||
|
||||
output dummy_out
|
||||
);
|
||||
|
||||
// Register File
|
||||
reg [31:0] regfile [0:31];
|
||||
initial regfile[0] = 32'h00000000;
|
||||
initial begin : init_regfile
|
||||
integer i;
|
||||
for (i=0; i<32; i=i+1) begin
|
||||
regfile[i] = 32'h00000000;
|
||||
end
|
||||
end
|
||||
|
||||
// Registers
|
||||
reg [31:0] r_if_pc = 0, r_id_pc, r_ex_pc, r_mem_pc, r_wb_pc;
|
||||
@ -25,7 +79,7 @@ reg r_id_stall, r_ex_stall, r_mem_stall, r_wb_stall;
|
||||
reg [31:0] r_id_inst, r_ex_inst, r_mem_inst, r_wb_inst;
|
||||
reg [4:0] r_ex_rd, r_mem_rd, r_wb_rd;
|
||||
reg r_ex_alu_seed;
|
||||
reg [2:0] r_ex_aluop;
|
||||
reg [3:0] r_ex_aluop;
|
||||
reg [31:0] r_ex_s1, r_ex_s2, r_mem_s1, r_mem_s2;
|
||||
reg [31:0] r_mem_alu_out, r_wb_alu_out;
|
||||
reg r_mem_alu_zero;
|
||||
@ -62,7 +116,7 @@ reg [6:0] s_id_funct7;
|
||||
reg [4:0] s_id_rd, s_id_rs1, s_id_rs2;
|
||||
reg [31:0] s_id_immed_itype, s_id_immed_stype, s_id_immed_utype, s_id_immed_btype, s_id_immed_jtype;
|
||||
reg [31:0] s_id_s1, s_id_s2;
|
||||
reg [2:0] s_id_aluop;
|
||||
reg [3:0] s_id_aluop;
|
||||
reg s_id_alu_seed;
|
||||
reg s_id_invalid;
|
||||
reg s_id_jump, s_id_branch;
|
||||
@ -87,14 +141,16 @@ localparam OP_LUI = 7'b0110111,
|
||||
// TODO: add opcodes for other extensions
|
||||
|
||||
// ALU OPCODES
|
||||
localparam ALUOP_ADD = 0,
|
||||
ALUOP_XOR = 1,
|
||||
ALUOP_OR = 2,
|
||||
ALUOP_AND = 3,
|
||||
ALUOP_SL = 4,
|
||||
ALUOP_SR = 5,
|
||||
ALUOP_SLT = 6,
|
||||
ALUOP_SLTU = 7;
|
||||
localparam ALUOP_ADD = 4'b0000,
|
||||
ALUOP_SUB = 4'b0001,
|
||||
ALUOP_XOR = 4'b0010,
|
||||
ALUOP_OR = 4'b0011,
|
||||
ALUOP_AND = 4'b0100,
|
||||
ALUOP_SL = 4'b0101,
|
||||
ALUOP_SRL = 4'b0110,
|
||||
ALUOP_SRA = 4'b0111,
|
||||
ALUOP_SLT = 4'b1000,
|
||||
ALUOP_SLTU = 4'b1001;
|
||||
|
||||
|
||||
always @(*) begin
|
||||
@ -117,35 +173,31 @@ always @(*) begin
|
||||
s_id_immed_jtype = {{11{r_id_inst[31]}}, r_id_inst[31], r_id_inst[19:12], r_id_inst[20], r_id_inst[30:21], 1'b0};
|
||||
|
||||
case (s_id_opcode)
|
||||
OP_LUI: begin
|
||||
OP_LUI: begin // LUI
|
||||
s_id_s1 = 32'h00000000;
|
||||
s_id_s2 = s_id_immed_utype;
|
||||
s_id_aluop = ALUOP_ADD;
|
||||
s_id_alu_seed = 0;
|
||||
s_id_jump = 0;
|
||||
s_id_branch = 0;
|
||||
end
|
||||
OP_AUIPC: begin
|
||||
OP_AUIPC: begin // AUIPC
|
||||
s_id_s1 = r_id_pc;
|
||||
s_id_s2 = s_id_immed_utype;
|
||||
s_id_aluop = ALUOP_ADD;
|
||||
s_id_alu_seed = 0;
|
||||
s_id_jump = 0;
|
||||
s_id_branch = 0;
|
||||
end
|
||||
OP_JAL: begin
|
||||
OP_JAL: begin // JAL
|
||||
s_id_s1 = r_id_pc;
|
||||
s_id_s2 = s_id_immed_jtype;
|
||||
s_id_aluop = ALUOP_ADD;
|
||||
s_id_alu_seed = 0;
|
||||
s_id_jump = 1;
|
||||
s_id_branch = 0;
|
||||
end
|
||||
OP_JALR: begin
|
||||
OP_JALR: begin // JALR
|
||||
s_id_s1 = regfile[s_id_rs1];
|
||||
s_id_s2 = s_id_immed_itype;
|
||||
s_id_aluop = ALUOP_ADD;
|
||||
s_id_alu_seed = 0;
|
||||
s_id_jump = 1;
|
||||
s_id_branch = 0;
|
||||
end
|
||||
@ -164,15 +216,15 @@ always @(*) begin
|
||||
s_id_jump = 0;
|
||||
s_id_branch = 0;
|
||||
casex ({s_id_funct3, s_id_funct7})
|
||||
10'b000xxxxxxx: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b0; end // ADDI
|
||||
10'b010xxxxxxx: begin s_id_aluop = ALUOP_SLT; s_id_alu_seed = 1'bx; end // SLTI
|
||||
10'b011xxxxxxx: begin s_id_aluop = ALUOP_SLTU; s_id_alu_seed = 1'bx; end // SLTUI
|
||||
10'b100xxxxxxx: begin s_id_aluop = ALUOP_XOR; s_id_alu_seed = 1'bx; end // XORI
|
||||
10'b110xxxxxxx: begin s_id_aluop = ALUOP_OR; s_id_alu_seed = 1'bx; end // ORI
|
||||
10'b111xxxxxxx: begin s_id_aluop = ALUOP_AND; s_id_alu_seed = 1'bx; end // ANDI
|
||||
10'b0010000000: begin s_id_aluop = ALUOP_SL; s_id_alu_seed = 1'bx; end // SLLI
|
||||
10'b1010000000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b0; end // SRLI
|
||||
10'b1010100000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b1; end // SRAI
|
||||
10'b000xxxxxxx: s_id_aluop = ALUOP_ADD; // ADDI
|
||||
10'b010xxxxxxx: s_id_aluop = ALUOP_SLT; // SLTI
|
||||
10'b011xxxxxxx: s_id_aluop = ALUOP_SLTU; // SLTUI
|
||||
10'b100xxxxxxx: s_id_aluop = ALUOP_XOR; // XORI
|
||||
10'b110xxxxxxx: s_id_aluop = ALUOP_OR; // ORI
|
||||
10'b111xxxxxxx: s_id_aluop = ALUOP_AND; // ANDI
|
||||
10'b0010000000: s_id_aluop = ALUOP_SL; // SLLI
|
||||
10'b1010000000: s_id_aluop = ALUOP_SRL; // SRLI
|
||||
10'b1010100000: s_id_aluop = ALUOP_SRA; // SRAI
|
||||
default: begin
|
||||
s_id_s1 = 32'hxxxxxxxx;
|
||||
s_id_s2 = 32'hxxxxxxxx;
|
||||
@ -186,16 +238,16 @@ always @(*) begin
|
||||
s_id_jump = 0;
|
||||
s_id_branch = 0;
|
||||
case ({s_id_funct3, s_id_funct7})
|
||||
10'b0000000000: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b0; end // ADD
|
||||
10'b0000100000: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b1; end // SUB
|
||||
10'b0010000000: begin s_id_aluop = ALUOP_SL; s_id_alu_seed = 1'bx; end // SLL
|
||||
10'b0100000000: begin s_id_aluop = ALUOP_SLT; s_id_alu_seed = 1'bx; end // SLT
|
||||
10'b0110000000: begin s_id_aluop = ALUOP_SLTU; s_id_alu_seed = 1'bx; end // SLTU
|
||||
10'b1000000000: begin s_id_aluop = ALUOP_XOR; s_id_alu_seed = 1'bx; end // XOR
|
||||
10'b1100000000: begin s_id_aluop = ALUOP_OR; s_id_alu_seed = 1'bx; end // OR
|
||||
10'b1110000000: begin s_id_aluop = ALUOP_AND; s_id_alu_seed = 1'bx; end // AND
|
||||
10'b1010000000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b0; end // SRL
|
||||
10'b1010100000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b1; end // SRA
|
||||
10'b0000000000: s_id_aluop = ALUOP_ADD; // ADD
|
||||
10'b0000100000: s_id_aluop = ALUOP_SUB; // SUB
|
||||
10'b0010000000: s_id_aluop = ALUOP_SL; // SLL
|
||||
10'b0100000000: s_id_aluop = ALUOP_SLT; // SLT
|
||||
10'b0110000000: s_id_aluop = ALUOP_SLTU; // SLTU
|
||||
10'b1000000000: s_id_aluop = ALUOP_XOR; // XOR
|
||||
10'b1100000000: s_id_aluop = ALUOP_OR; // OR
|
||||
10'b1110000000: s_id_aluop = ALUOP_AND; // AND
|
||||
10'b1010000000: s_id_aluop = ALUOP_SRL; // SRL
|
||||
10'b1010100000: s_id_aluop = ALUOP_SRA; // SRA
|
||||
default: begin
|
||||
s_id_s1 = 32'hxxxxxxxx;
|
||||
s_id_s2 = 32'hxxxxxxxx;
|
||||
@ -219,7 +271,7 @@ always @(*) begin
|
||||
endcase
|
||||
|
||||
if (s_id_invalid) begin
|
||||
$display("Invalid instruction at PC=0x%h", r_id_pc);
|
||||
$display("%0t:\tInvalid instruction at PC=0x%h", $time, r_id_pc);
|
||||
s_id_halt = 1'b1;
|
||||
s_id_aluop = 3'hx;
|
||||
s_id_alu_seed = 1'bx;
|
||||
@ -236,12 +288,16 @@ reg [31:0] s_ex_ra;
|
||||
always @(*) begin
|
||||
s_ex_halt = 0;
|
||||
|
||||
// NOTE: s_ex_data* exist for adding data paths bypassing regfile in the future
|
||||
s_ex_data1 = r_ex_s1;
|
||||
s_ex_data2 = r_ex_s2;
|
||||
|
||||
case (r_ex_aluop)
|
||||
ALUOP_ADD: begin // seed=1: subtract
|
||||
s_ex_alu_out = s_ex_data1 + (s_ex_data2 ^ {32{r_ex_alu_seed}}) + r_ex_alu_seed;
|
||||
ALUOP_ADD: begin
|
||||
s_ex_alu_out = s_ex_data1 + s_ex_data2;
|
||||
end
|
||||
ALUOP_SUB: begin
|
||||
s_ex_alu_out = s_ex_data1 - s_ex_data2;
|
||||
end
|
||||
ALUOP_XOR: begin
|
||||
s_ex_alu_out = s_ex_data1 ^ s_ex_data2;
|
||||
@ -255,11 +311,11 @@ always @(*) begin
|
||||
ALUOP_SL: begin
|
||||
s_ex_alu_out = s_ex_data1 << s_ex_data2;
|
||||
end
|
||||
ALUOP_SR: begin // seed=1: arithmetic
|
||||
ALUOP_SRL: begin
|
||||
s_ex_alu_out = s_ex_data1 >> s_ex_data2;
|
||||
if (r_ex_alu_seed) begin
|
||||
s_ex_alu_out = s_ex_data1 >>> s_ex_data2;
|
||||
end
|
||||
end
|
||||
ALUOP_SRA: begin
|
||||
s_ex_alu_out = s_ex_data1 >>> s_ex_data2;
|
||||
end
|
||||
ALUOP_SLT: begin
|
||||
s_ex_alu_out = $signed(s_ex_data1) < $signed(s_ex_data2);
|
||||
@ -285,19 +341,19 @@ always @(*) begin
|
||||
s_mem_halt = 0;
|
||||
s_mem_bp = 0;
|
||||
|
||||
if (r_mem_store) begin
|
||||
mem_data_en = 1;
|
||||
mem_data_we = 1;
|
||||
s_mem_bp = !mem_data_done;
|
||||
end else if (r_mem_load) begin
|
||||
mem_data_en = 1;
|
||||
mem_data_we = 0;
|
||||
s_mem_bp = !mem_data_valid;
|
||||
end else begin
|
||||
mem_data_en = 0;
|
||||
mem_data_we = 0;
|
||||
s_mem_bp = 0;
|
||||
end
|
||||
// if (r_mem_store) begin
|
||||
// mem_data_en = 1;
|
||||
// mem_data_we = 1;
|
||||
// s_mem_bp = !mem_data_done;
|
||||
// end else if (r_mem_load) begin
|
||||
// mem_data_en = 1;
|
||||
// mem_data_we = 0;
|
||||
// s_mem_bp = !mem_data_valid;
|
||||
// end else begin
|
||||
// mem_data_en = 0;
|
||||
// mem_data_we = 0;
|
||||
// s_mem_bp = 0;
|
||||
// end
|
||||
end
|
||||
|
||||
// WB
|
||||
|
Reference in New Issue
Block a user