passes quick tests for: lui, addi, add, sub, and, or, xor, andi. jump works but does not link

This commit is contained in:
Brendan Haines 2020-10-11 23:03:14 -06:00
parent 3fbd96ca27
commit 2c24c19a72
5 changed files with 447 additions and 217 deletions

152
hdl/axi_lite_memory.v Normal file
View File

@ -0,0 +1,152 @@
module axi_lite_memory(
// Global
input ACLK,
input ARESETn,
// Write address
input AWVALID,
input [ADDR_WIDTH-1:0] AWADDR,
input [2:0] AWPROT,
output reg AWREADY,
// Write data
input WVALID,
input [DATA_WIDTH-1:0] WDATA,
input [(DATA_WIDTH/8)-1:0] WSTRB,
output reg WREADY,
// Write response
output reg BVALID,
input BREADY,
output reg [1:0] BRESP,
// Read address
input ARVALID,
input [ADDR_WIDTH-1:0] ARADDR,
input [2:0] ARPROT, // IGNORED
output reg ARREADY,
// Read data
output reg RVALID,
output reg [DATA_WIDTH-1:0] RDATA,
output reg [1:0] RRESP,
input RREADY,
// Wishbone write
output reg [ADDR_WIDTH-1:0] WB_WADDR,
output reg [2:0] WB_WPROT,
output reg [DATA_WIDTH-1:0] WB_WDATA,
output reg [(DATA_WIDTH/8)-1:0] WB_WSTRB,
output reg WB_WVALID = 0,
input WB_WREADY,
// Wishbone read
output reg [ADDR_WIDTH-1:0] WB_RADDR,
input [DATA_WIDTH-1:0] WB_RDATA,
input WB_RVALID,
output reg WB_RREADY
);
parameter DATA_WIDTH = 32; // Only 32 allowed for now (AXI-Lite allows 32 or 64). 64 might work but I haven't investigated it yet.
parameter ADDR_WIDTH = 12; // No minimum requirement. Typically at least 12b (4KB)
parameter SYNC_DEPTH = 1; // Minimum recommended: 2. Larger synchronizer depth allows for larger delay between AXI address and data without stalling.
reg [ADDR_WIDTH-1:0] sync_awaddr [0:SYNC_DEPTH-1];
reg [2:0] sync_awprot [0:SYNC_DEPTH-1];
reg [$clog2(SYNC_DEPTH)+1:0] sync_aw_fill = 0;
reg [DATA_WIDTH-1:0] sync_wdata [0:SYNC_DEPTH-1];
reg [(DATA_WIDTH/8)-1:0] sync_wstrb [0:SYNC_DEPTH-1];
reg [$clog2(SYNC_DEPTH)+1:0] sync_w_fill = 0;
reg [1:0] sync_bresp [0:SYNC_DEPTH-1]; // TODO: make this not be the same sync_depth?
reg [$clog2(SYNC_DEPTH)+1:0] sync_b_fill = 0;
localparam RESP_OKAY = 2'b00,
RESP_EXOKAY = 2'b01,
RESP_SLVERR = 2'b10,
RESP_DECERR = 2'b11;
always @(*) begin
AWREADY = sync_aw_fill < SYNC_DEPTH;
WREADY = sync_w_fill < SYNC_DEPTH;
BRESP = RESP_OKAY; // TODO: add support for responses other than OKAY
BVALID = sync_b_fill > 0;
end
always @(posedge ACLK or negedge ARESETn) begin: clk_update
integer i;
// Write direction
integer event_wb_write;
integer event_aw;
integer event_w;
integer event_b;
// Read direction
integer event_wb_read;
integer event_ar;
integer event_r;
// Write direction
event_wb_write = 0;
event_aw = 0;
event_w = 0;
event_b = 0;
// Read direction
event_wb_read = 0;
event_ar = 0;
event_r = 0;
if (ARESETn == 0) begin
// TODO: deal with reset
sync_aw_fill <= 0;
sync_w_fill <= 0;
sync_b_fill <= 0;
end else begin
if (AWREADY && AWVALID) begin
event_aw = 1;
for (i=0; i<sync_aw_fill; i=i+1) begin
sync_awaddr[i+1] <= sync_awaddr[i];
sync_awprot[i+1] <= sync_awprot[i];
end
sync_awaddr[0] <= AWADDR;
sync_awprot[0] <= AWPROT;
end
if (WREADY && WVALID) begin
event_w = 1;
for (i=0; i<sync_w_fill; i=i+1) begin
sync_wdata[i+1] <= sync_wstrb[i];
sync_wstrb[i+1] <= sync_wstrb[i];
end
sync_wdata[sync_w_fill] <= WDATA;
sync_wstrb[sync_w_fill] <= WSTRB;
end
if (BREADY && BVALID) begin
event_b = 1;
end
if (WB_WREADY || !WB_WVALID) begin
event_wb_write = 1;
if (sync_aw_fill > 0 && sync_w_fill > 0) begin
WB_WVALID <= 1'b1;
WB_WADDR <= sync_awaddr[sync_aw_fill-1];
WB_WPROT <= sync_awprot[sync_aw_fill-1];
WB_WDATA <= sync_wdata[sync_w_fill-1];
WB_WSTRB <= sync_wstrb[sync_w_fill-1];
end else begin
WB_WVALID <= 1'b0;
end
end
sync_aw_fill <= sync_aw_fill + event_aw - event_wb_write;
sync_w_fill <= sync_w_fill + event_w - event_wb_write;
sync_b_fill <= sync_b_fill - event_b + event_wb_write; // TODO: is this right?
end
end
endmodule

View File

@ -1,23 +1,77 @@
module core( module core(
input clk, input clk,
input reset, input reset,
output dummy_out,
output reg [31:0] mem_inst_addr, output reg [31:0] mem_inst_addr,
input [31:0] mem_inst_data, input [31:0] mem_inst_data,
output reg [31:0] mem_data_addr, // output reg [31:0] mem_data_addr,
output reg [31:0] mem_data_wdata, // output reg [31:0] mem_data_wdata,
input [31:0] mem_data_rdata, // input [31:0] mem_data_rdata,
output reg mem_data_en, // output reg mem_data_en,
output reg mem_data_we, // output reg mem_data_we,
input mem_data_valid, // input mem_data_valid,
input mem_data_done // 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 // Register File
reg [31:0] regfile [0:31]; 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 // Registers
reg [31:0] r_if_pc = 0, r_id_pc, r_ex_pc, r_mem_pc, r_wb_pc; 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 [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 [4:0] r_ex_rd, r_mem_rd, r_wb_rd;
reg r_ex_alu_seed; 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_ex_s1, r_ex_s2, r_mem_s1, r_mem_s2;
reg [31:0] r_mem_alu_out, r_wb_alu_out; reg [31:0] r_mem_alu_out, r_wb_alu_out;
reg r_mem_alu_zero; 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 [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_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 [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_alu_seed;
reg s_id_invalid; reg s_id_invalid;
reg s_id_jump, s_id_branch; reg s_id_jump, s_id_branch;
@ -87,14 +141,16 @@ localparam OP_LUI = 7'b0110111,
// TODO: add opcodes for other extensions // TODO: add opcodes for other extensions
// ALU OPCODES // ALU OPCODES
localparam ALUOP_ADD = 0, localparam ALUOP_ADD = 4'b0000,
ALUOP_XOR = 1, ALUOP_SUB = 4'b0001,
ALUOP_OR = 2, ALUOP_XOR = 4'b0010,
ALUOP_AND = 3, ALUOP_OR = 4'b0011,
ALUOP_SL = 4, ALUOP_AND = 4'b0100,
ALUOP_SR = 5, ALUOP_SL = 4'b0101,
ALUOP_SLT = 6, ALUOP_SRL = 4'b0110,
ALUOP_SLTU = 7; ALUOP_SRA = 4'b0111,
ALUOP_SLT = 4'b1000,
ALUOP_SLTU = 4'b1001;
always @(*) begin 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}; 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) case (s_id_opcode)
OP_LUI: begin OP_LUI: begin // LUI
s_id_s1 = 32'h00000000; s_id_s1 = 32'h00000000;
s_id_s2 = s_id_immed_utype; s_id_s2 = s_id_immed_utype;
s_id_aluop = ALUOP_ADD; s_id_aluop = ALUOP_ADD;
s_id_alu_seed = 0;
s_id_jump = 0; s_id_jump = 0;
s_id_branch = 0; s_id_branch = 0;
end end
OP_AUIPC: begin OP_AUIPC: begin // AUIPC
s_id_s1 = r_id_pc; s_id_s1 = r_id_pc;
s_id_s2 = s_id_immed_utype; s_id_s2 = s_id_immed_utype;
s_id_aluop = ALUOP_ADD; s_id_aluop = ALUOP_ADD;
s_id_alu_seed = 0;
s_id_jump = 0; s_id_jump = 0;
s_id_branch = 0; s_id_branch = 0;
end end
OP_JAL: begin OP_JAL: begin // JAL
s_id_s1 = r_id_pc; s_id_s1 = r_id_pc;
s_id_s2 = s_id_immed_jtype; s_id_s2 = s_id_immed_jtype;
s_id_aluop = ALUOP_ADD; s_id_aluop = ALUOP_ADD;
s_id_alu_seed = 0;
s_id_jump = 1; s_id_jump = 1;
s_id_branch = 0; s_id_branch = 0;
end end
OP_JALR: begin OP_JALR: begin // JALR
s_id_s1 = regfile[s_id_rs1]; s_id_s1 = regfile[s_id_rs1];
s_id_s2 = s_id_immed_itype; s_id_s2 = s_id_immed_itype;
s_id_aluop = ALUOP_ADD; s_id_aluop = ALUOP_ADD;
s_id_alu_seed = 0;
s_id_jump = 1; s_id_jump = 1;
s_id_branch = 0; s_id_branch = 0;
end end
@ -164,15 +216,15 @@ always @(*) begin
s_id_jump = 0; s_id_jump = 0;
s_id_branch = 0; s_id_branch = 0;
casex ({s_id_funct3, s_id_funct7}) casex ({s_id_funct3, s_id_funct7})
10'b000xxxxxxx: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b0; end // ADDI 10'b000xxxxxxx: s_id_aluop = ALUOP_ADD; // ADDI
10'b010xxxxxxx: begin s_id_aluop = ALUOP_SLT; s_id_alu_seed = 1'bx; end // SLTI 10'b010xxxxxxx: s_id_aluop = ALUOP_SLT; // SLTI
10'b011xxxxxxx: begin s_id_aluop = ALUOP_SLTU; s_id_alu_seed = 1'bx; end // SLTUI 10'b011xxxxxxx: s_id_aluop = ALUOP_SLTU; // SLTUI
10'b100xxxxxxx: begin s_id_aluop = ALUOP_XOR; s_id_alu_seed = 1'bx; end // XORI 10'b100xxxxxxx: s_id_aluop = ALUOP_XOR; // XORI
10'b110xxxxxxx: begin s_id_aluop = ALUOP_OR; s_id_alu_seed = 1'bx; end // ORI 10'b110xxxxxxx: s_id_aluop = ALUOP_OR; // ORI
10'b111xxxxxxx: begin s_id_aluop = ALUOP_AND; s_id_alu_seed = 1'bx; end // ANDI 10'b111xxxxxxx: s_id_aluop = ALUOP_AND; // ANDI
10'b0010000000: begin s_id_aluop = ALUOP_SL; s_id_alu_seed = 1'bx; end // SLLI 10'b0010000000: s_id_aluop = ALUOP_SL; // SLLI
10'b1010000000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b0; end // SRLI 10'b1010000000: s_id_aluop = ALUOP_SRL; // SRLI
10'b1010100000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b1; end // SRAI 10'b1010100000: s_id_aluop = ALUOP_SRA; // SRAI
default: begin default: begin
s_id_s1 = 32'hxxxxxxxx; s_id_s1 = 32'hxxxxxxxx;
s_id_s2 = 32'hxxxxxxxx; s_id_s2 = 32'hxxxxxxxx;
@ -186,16 +238,16 @@ always @(*) begin
s_id_jump = 0; s_id_jump = 0;
s_id_branch = 0; s_id_branch = 0;
case ({s_id_funct3, s_id_funct7}) case ({s_id_funct3, s_id_funct7})
10'b0000000000: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b0; end // ADD 10'b0000000000: s_id_aluop = ALUOP_ADD; // ADD
10'b0000100000: begin s_id_aluop = ALUOP_ADD; s_id_alu_seed = 1'b1; end // SUB 10'b0000100000: s_id_aluop = ALUOP_SUB; // SUB
10'b0010000000: begin s_id_aluop = ALUOP_SL; s_id_alu_seed = 1'bx; end // SLL 10'b0010000000: s_id_aluop = ALUOP_SL; // SLL
10'b0100000000: begin s_id_aluop = ALUOP_SLT; s_id_alu_seed = 1'bx; end // SLT 10'b0100000000: s_id_aluop = ALUOP_SLT; // SLT
10'b0110000000: begin s_id_aluop = ALUOP_SLTU; s_id_alu_seed = 1'bx; end // SLTU 10'b0110000000: s_id_aluop = ALUOP_SLTU; // SLTU
10'b1000000000: begin s_id_aluop = ALUOP_XOR; s_id_alu_seed = 1'bx; end // XOR 10'b1000000000: s_id_aluop = ALUOP_XOR; // XOR
10'b1100000000: begin s_id_aluop = ALUOP_OR; s_id_alu_seed = 1'bx; end // OR 10'b1100000000: s_id_aluop = ALUOP_OR; // OR
10'b1110000000: begin s_id_aluop = ALUOP_AND; s_id_alu_seed = 1'bx; end // AND 10'b1110000000: s_id_aluop = ALUOP_AND; // AND
10'b1010000000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b0; end // SRL 10'b1010000000: s_id_aluop = ALUOP_SRL; // SRL
10'b1010100000: begin s_id_aluop = ALUOP_SR; s_id_alu_seed = 1'b1; end // SRA 10'b1010100000: s_id_aluop = ALUOP_SRA; // SRA
default: begin default: begin
s_id_s1 = 32'hxxxxxxxx; s_id_s1 = 32'hxxxxxxxx;
s_id_s2 = 32'hxxxxxxxx; s_id_s2 = 32'hxxxxxxxx;
@ -219,7 +271,7 @@ always @(*) begin
endcase endcase
if (s_id_invalid) begin 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_halt = 1'b1;
s_id_aluop = 3'hx; s_id_aluop = 3'hx;
s_id_alu_seed = 1'bx; s_id_alu_seed = 1'bx;
@ -236,12 +288,16 @@ reg [31:0] s_ex_ra;
always @(*) begin always @(*) begin
s_ex_halt = 0; 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_data1 = r_ex_s1;
s_ex_data2 = r_ex_s2; s_ex_data2 = r_ex_s2;
case (r_ex_aluop) case (r_ex_aluop)
ALUOP_ADD: begin // seed=1: subtract ALUOP_ADD: begin
s_ex_alu_out = s_ex_data1 + (s_ex_data2 ^ {32{r_ex_alu_seed}}) + r_ex_alu_seed; 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 end
ALUOP_XOR: begin ALUOP_XOR: begin
s_ex_alu_out = s_ex_data1 ^ s_ex_data2; s_ex_alu_out = s_ex_data1 ^ s_ex_data2;
@ -255,11 +311,11 @@ always @(*) begin
ALUOP_SL: begin ALUOP_SL: begin
s_ex_alu_out = s_ex_data1 << s_ex_data2; s_ex_alu_out = s_ex_data1 << s_ex_data2;
end end
ALUOP_SR: begin // seed=1: arithmetic ALUOP_SRL: begin
s_ex_alu_out = s_ex_data1 >> s_ex_data2; s_ex_alu_out = s_ex_data1 >> s_ex_data2;
if (r_ex_alu_seed) begin end
s_ex_alu_out = s_ex_data1 >>> s_ex_data2; ALUOP_SRA: begin
end s_ex_alu_out = s_ex_data1 >>> s_ex_data2;
end end
ALUOP_SLT: begin ALUOP_SLT: begin
s_ex_alu_out = $signed(s_ex_data1) < $signed(s_ex_data2); s_ex_alu_out = $signed(s_ex_data1) < $signed(s_ex_data2);
@ -285,19 +341,19 @@ always @(*) begin
s_mem_halt = 0; s_mem_halt = 0;
s_mem_bp = 0; s_mem_bp = 0;
if (r_mem_store) begin // if (r_mem_store) begin
mem_data_en = 1; // mem_data_en = 1;
mem_data_we = 1; // mem_data_we = 1;
s_mem_bp = !mem_data_done; // s_mem_bp = !mem_data_done;
end else if (r_mem_load) begin // end else if (r_mem_load) begin
mem_data_en = 1; // mem_data_en = 1;
mem_data_we = 0; // mem_data_we = 0;
s_mem_bp = !mem_data_valid; // s_mem_bp = !mem_data_valid;
end else begin // end else begin
mem_data_en = 0; // mem_data_en = 0;
mem_data_we = 0; // mem_data_we = 0;
s_mem_bp = 0; // s_mem_bp = 0;
end // end
end end
// WB // WB

View File

@ -2,108 +2,35 @@
module core_tb(); module core_tb();
initial $timeformat(-9, 2, " ns", 20);
localparam MEM_INST_LENGTH = 256; localparam MEM_INST_LENGTH = 256;
localparam MEM_DATA_LENGTH = 256; localparam MEM_DATA_LENGTH = 256;
localparam INST_NOP = 32'h00000013; // nop
reg clk, reset; reg clk, reset;
reg [31:0] mem_inst [0:MEM_INST_LENGTH-1];
wire [31:0] mem_inst_addr; wire [31:0] mem_inst_addr;
wire [31:0] mem_inst_idx = mem_inst_addr >> 2; wire [31:0] mem_inst_idx = mem_inst_addr >> 2;
reg [31:0] mem_inst_data; wire [31:0] mem_inst_data = mem_inst_idx < MEM_INST_LENGTH ? mem_inst[mem_inst_idx] : INST_NOP;
reg [31:0] mem_inst [0:MEM_INST_LENGTH-1];
reg [31:0] mem_data [0:MEM_DATA_LENGTH-1];
wire [31:0] mem_data_addr;
wire [31:0] mem_data_wdata;
reg [31:0] mem_data_rdata;
wire mem_data_en;
wire mem_data_we;
reg mem_data_valid;
reg mem_data_done;
integer i;
localparam OP_LUI = 7'b0110111, initial begin: mem_inst_init
OP_AUIPC = 7'b0010111, integer i;
OP_JAL = 7'b1101111,
OP_JALR = 7'b1100111,
OP_BRANCH = 7'b1100011,
OP_LOAD = 7'b0000011,
OP_STORE = 7'b0100011,
OP_IMM = 7'b0010011,
OP_ALU = 7'b0110011,
OP_FENCE = 7'b0001111,
OP_SYSTEM = 7'b1110011;
localparam INST_NOP = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd0, OP_ALU}; // nop
initial begin
for (i=0; i<MEM_INST_LENGTH; i=i+1) begin for (i=0; i<MEM_INST_LENGTH; i=i+1) begin
mem_inst[i] = INST_NOP; mem_inst[i] = INST_NOP;
end end
$readmemh("../test/test.hex", mem_inst); $readmemh("../test/test.hex", mem_inst);
// // Initialize all registers
// mem_inst[0] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd1, OP_ALU}; // add x1, x0, x0
// mem_inst[1] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd2, OP_ALU}; // add x2, x0, x0
// mem_inst[2] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd3, OP_ALU}; // add x3, x0, x0
// mem_inst[3] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd4, OP_ALU}; // add x4, x0, x0
// mem_inst[4] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd5, OP_ALU}; // add x5, x0, x0
// mem_inst[5] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd6, OP_ALU}; // add x6, x0, x0
// mem_inst[6] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd7, OP_ALU}; // add x7, x0, x0
// mem_inst[7] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd8, OP_ALU}; // add x8, x0, x0
// mem_inst[8] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd9, OP_ALU}; // add x9, x0, x0
// mem_inst[9] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd10, OP_ALU}; // add x10, x0, x0
// mem_inst[10] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd11, OP_ALU}; // add x11, x0, x0
// mem_inst[11] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd12, OP_ALU}; // add x12, x0, x0
// mem_inst[12] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd13, OP_ALU}; // add x13, x0, x0
// mem_inst[13] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd14, OP_ALU}; // add x14, x0, x0
// mem_inst[14] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd15, OP_ALU}; // add x15, x0, x0
// mem_inst[15] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd16, OP_ALU}; // add x16, x0, x0
// mem_inst[16] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd17, OP_ALU}; // add x17, x0, x0
// mem_inst[17] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd18, OP_ALU}; // add x18, x0, x0
// mem_inst[18] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd19, OP_ALU}; // add x19, x0, x0
// mem_inst[19] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd20, OP_ALU}; // add x20, x0, x0
// mem_inst[20] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd21, OP_ALU}; // add x21, x0, x0
// mem_inst[21] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd22, OP_ALU}; // add x22, x0, x0
// mem_inst[22] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd23, OP_ALU}; // add x23, x0, x0
// mem_inst[23] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd24, OP_ALU}; // add x24, x0, x0
// mem_inst[24] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd25, OP_ALU}; // add x25, x0, x0
// mem_inst[25] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd26, OP_ALU}; // add x26, x0, x0
// mem_inst[26] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd27, OP_ALU}; // add x27, x0, x0
// mem_inst[27] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd28, OP_ALU}; // add x28, x0, x0
// mem_inst[28] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd29, OP_ALU}; // add x29, x0, x0
// mem_inst[29] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd30, OP_ALU}; // add x30, x0, x0
// mem_inst[30] = {7'b0000000, 5'd0, 5'd0, 3'b000, 5'd31, OP_ALU}; // add x31, x0, x0
// mem_inst[36] = {12'd1, 5'd0, 3'b000, 5'd2, OP_IMM}; // addi x2, x0, 1
// mem_inst[42] = {7'b0000000, 5'd2, 5'd1, 3'b000, 5'd3, OP_ALU}; // add x3, x1, x2
// mem_inst[48] = {7'b0000000, 5'd2, 5'd3, 3'b000, 5'd3, OP_ALU}; // add x3, x3, x2
// mem_inst[54] = {7'b0000000, 5'd3, 5'd3, 3'b000, 5'd3, OP_ALU}; // add x3, x3, x3
// mem_inst[60] = {12'h123, 5'd0, 3'b000, 5'd4, OP_IMM}; // addi x4, x0, 0x123
// mem_inst[66] = {12'h000, 5'd4, 3'b000, 5'd5, OP_IMM}; // addi x5, x4, 0
// mem_inst[72] = {12'hfff, 5'd5, 3'b000, 5'd5, OP_IMM}; // addi x5, x5, -1
// mem_inst[78] = {20'hedcba, 5'd7, OP_LUI}; // lui x7, 0xedcba
// mem_inst[84] = {12'h987, 5'd7, 3'b000, 5'd7, OP_IMM}; // addi x7, x7, 0x987
// mem_inst[90] = {20'h00032, 5'd8, OP_AUIPC}; // auipc x8, 0x32 // 90*4 + 0x32000 = 0x32168
// // mem_inst[96] = {12'd288, 5'd0, 3'b000, 5'd9, OP_JALR}; // jalr x9, x0, 72*4 // unconditional jump to index 72 = 288/4
// mem_inst[102] = {1'b0, 10'd12, 1'b0, 8'b0, 5'd9, OP_JAL}; // jal x10, +12 // unconditional jump to index +12 = 24*2/4
// mem_inst[108] = {12'd4, 5'd0, 3'b000, 5'd2, OP_IMM}; // addi x11, x0, 4 // this should be skipped
// mem_inst[114] = {12'd5, 5'd0, 3'b000, 5'd2, OP_IMM}; // addi x12, x0, 5
// mem_inst[120] = {12'd5, 5'd0, 3'b000, 5'd2, OP_IMM}; // addi x12, x12, 6
end end
initial begin reg [31:0] mem_data [0:MEM_DATA_LENGTH-1];
end wire [31:0] mem_data_waddr;
wire [31:0] mem_data_wdata;
always @(*) begin wire [3:0] mem_data_wmask;
if (mem_inst_idx < MEM_INST_LENGTH) begin wire mem_data_we;
mem_inst_data = mem_inst[mem_inst_idx]; wire [31:0] mem_data_raddr;
end else begin reg [31:0] mem_data_rdata;
mem_inst_data = INST_NOP; wire [3:0] mem_data_rmask;
end
end
initial begin initial begin
#0 #0
@ -125,15 +52,92 @@ core dut(
.reset(reset), .reset(reset),
.mem_inst_addr(mem_inst_addr), .mem_inst_addr(mem_inst_addr),
.mem_inst_data(mem_inst_data), .mem_inst_data(mem_inst_data)
.mem_data_addr(mem_data_addr), // .mem_data_addr(mem_data_addr),
.mem_data_wdata(mem_data_wdata), // .mem_data_wdata(mem_data_wdata),
.mem_data_rdata(mem_data_rdata), // .mem_data_rdata(mem_data_rdata),
.mem_data_en(mem_data_en), // .mem_data_en(mem_data_en),
.mem_data_we(mem_data_we), // .mem_data_we(mem_data_we),
.mem_data_valid(mem_data_valid), // .mem_data_valid(mem_data_valid),
.mem_data_done(mem_data_done) // .mem_data_done(mem_data_done)
); );
wire axi_mem_data_awvalid;
wire [11:0] axi_mem_data_awaddr;
wire [2:0] axi_mem_data_awprot;
wire axi_mem_data_awready;
wire axi_mem_data_wvalid;
wire [31:0] axi_mem_data_wdata;
wire [3:0] axi_mem_data_wstrb;
wire axi_mem_data_wready;
wire axi_mem_data_bvalid;
wire axi_mem_data_bready;
wire [1:0] axi_mem_data_bresp;
wire axi_mem_data_arvalid;
wire [11:0] axi_mem_data_araddr;
wire [2:0] axi_mem_data_arprot;
wire axi_mem_data_arready;
wire axi_mem_data_rvalid;
wire [31:0] axi_mem_data_rdata;
wire [1:0] axi_mem_data_resp;
wire axi_mem_data_rready;
axi_lite_memory axi_mem_data(
.ACLK(clk),
.ARESETn(!reset),
.AWVALID(axi_mem_data_awvalid),
.AWADDR(axi_mem_data_awaddr),
.AWPROT(axi_mem_data_awprot),
.AWREADY(axi_mem_data_awready),
.WVALID(axi_mem_data_wvalid),
.WDATA(axi_mem_data_wdata),
.WSTRB(axi_mem_data_wstrb),
.WREADY(axi_mem_data_wready),
.BVALID(axi_mem_data_bvalid),
.BREADY(axi_mem_data_bready),
.BRESP(axi_mem_data_bresp),
.ARVALID(axi_mem_data_arvalid),
.ARADDR(axi_mem_data_araddr),
.ARPROT(axi_mem_data_arprot),
.ARREADY(axi_mem_data_arready),
.RVALID(axi_mem_data_rvalid),
.RDATA(axi_mem_data_rdata),
.RRESP(axi_mem_data_resp),
.RREADY(axi_mem_data_rready),
.WB_WADDR(mem_data_waddr),
.WB_WPROT(),
.WB_WDATA(mem_data_wdata),
.WB_WSTRB(mem_data_wmask),
.WB_WVALID(mem_data_we),
.WB_WREADY(1'b1),
.WB_RADDR(mem_data_raddr),
.WB_RDATA(mem_data_rdata),
.WB_RVALID(1'b1),
.WB_RREADY()
);
wire [31:0] mem_data_widx = mem_data_waddr >> 2;
always @(posedge clk) begin
if (mem_data_we) begin
if (mem_data_widx < MEM_DATA_LENGTH) begin
mem_inst[mem_data_widx] <= (mem_inst[mem_data_widx] & ~{{8{mem_data_wmask[3]}}, {8{mem_data_wmask[2]}}, {8{mem_data_wmask[1]}}, {8{mem_data_wmask[0]}}}) | (mem_data_wdata & {{8{mem_data_wmask[3]}}, {8{mem_data_wmask[2]}}, {8{mem_data_wmask[1]}}, {8{mem_data_wmask[0]}}});
end
// ignore illegal writes
end
end
wire [31:0] mem_data_ridx = mem_data_raddr >> 2;
always @(*) begin
if (mem_data_ridx < MEM_DATA_LENGTH) begin
mem_data_rdata = mem_inst[mem_data_ridx] & {{8{mem_data_rmask[3]}}, {8{mem_data_rmask[2]}}, {8{mem_data_rmask[1]}}, {8{mem_data_rmask[0]}}};
end else begin
mem_data_rdata = 32'h00000000;
end
end
endmodule endmodule

View File

@ -2,7 +2,8 @@ XILINX = /opt/Xilinx/14.7/ISE_DS/ISE/
PROJECT = riscv_core PROJECT = riscv_core
TARGET_PART = xc6slx25-3-ftg256 TARGET_PART = xc6slx25-3-ftg256
VSOURCE = hdl/core.v hdl/top.v SVSOURCE = hdl/test.sv
VSOURCE = hdl/core.v hdl/top.v hdl/axi_lite_memory.v
# VHDSOURCE = hdl/*.vhd # VHDSOURCE = hdl/*.vhd
VTEST = hdl/tb/core_tb.v VTEST = hdl/tb/core_tb.v

View File

@ -1,88 +1,105 @@
.global _start .global _start
.text .text
_start: _start:
add x1, x0, x0
add x2, x0, x0
add x3, x0, x0
add x4, x0, x0
add x5, x0, x0
add x6, x0, x0
add x7, x0, x0
add x8, x0, x0
add x9, x0, x0
add x10, x0, x0
add x11, x0, x0
add x12, x0, x0
add x13, x0, x0
add x14, x0, x0
add x15, x0, x0
add x16, x0, x0
add x17, x0, x0
add x18, x0, x0
add x19, x0, x0
add x20, x0, x0
add x21, x0, x0
add x22, x0, x0
add x23, x0, x0
add x24, x0, x0
add x25, x0, x0
add x26, x0, x0
add x27, x0, x0
add x28, x0, x0
add x29, x0, x0
add x30, x0, x0
add x31, x0, x0
# NOTE: nop required because cpu currently does not detect when something is needed from a later stage of the pipeline. # NOTE: nop required because cpu currently does not detect when something is needed from a later stage of the pipeline.
# 4 clocks allows one instruction to finish before the next starts # 4 clocks allows one instruction to finish before the next reads the regfile
# AUIPC
# JAL
# JALR
# XORI
# ORI
# SLLI
# SRLI
# SRAI
# SLTI
# SLTUI
# SLL
# SRL
# SRA
# SLT
# SLTU
# lui # lui
nop
nop
nop
lui x1, 0xfedcb # x1 = 0xfedcb000 lui x1, 0xfedcb # x1 = 0xfedcb000
nop
nop
nop
# addi # addi
nop
nop
nop
addi x1, x1, 0x789 # x1 = 0xfedcb789 addi x1, x1, 0x789 # x1 = 0xfedcb789
addi x2, x0, -1 # x2 = 0xffffffff addi x2, x0, -1 # x2 = 0xffffffff
nop nop
nop nop
addi x3, x1, -0x777 # x3 = 0xfedcb012 addi x3, x1, -0x777 # x3 = 0xfedcb012
nop
nop
nop
# add # add
nop
nop
nop
add x4, x1, x2 # x4 = 0xfedcb788 add x4, x1, x2 # x4 = 0xfedcb788
nop
nop
nop
# sub # sub
sub x5, x1, x3 # x5 = 0x00000777
nop nop
nop nop
nop nop
add x5, x1, x3 # x5 = 0x00000777 incorrect
# and # and
nop
nop
nop
and x6, x1, x2 # x6 = 0xfedcb789 and x6, x1, x2 # x6 = 0xfedcb789
and x7, x1, x0 # x7 = 0x00000000 and x7, x1, x0 # x7 = 0x00000000
and x8, x4, x3 # x8 = 0xfedcb002 incorrect and x8, x4, x3 # x8 = 0xfedcb000
nop
nop
nop
# or # or
nop
nop
nop
or x9, x1, x2 # x9 = 0xffffffff or x9, x1, x2 # x9 = 0xffffffff
or x10, x1, x0 # x10 = 0xfedcb789 or x10, x1, x0 # x10 = 0xfedcb789
or x11, x4, x3 # x11 = 0x0xfedcb798 incorrect or x11, x4, x3 # x11 = 0x0xfedcb79a
nop
nop
nop
# xor
xor x12, x1, x2 # x12 = 0x01234876
xor x13, x1, x1 # x13 = 0x00000000
xor x14, x0, x2 # x14 = 0xffffffff
nop
nop
nop
# andi
andi x15, x2, -1348 # x15 = 0xfffffabc -1348 = 0xfffffabc
andi x16, x2, 0x123 # x16 = 0x00000123
andi x17, x1, -1645 # x17 = 0xfedcb181 -1645 = 0xfffff993
nop
nop
nop
# # ori
# ori x9, x1, x2 # x9 = 0xffffffff
# ori x10, x1, x0 # x10 = 0xfedcb789
# ori x11, x4, x3 # x11 = 0x0xfedcb79a
# nop
# nop
# nop
# # xori
# xori x12, x1, x2 # x12 = 0x01234876
# xori x13, x1, x1 # x13 = 0x00000000
# xori x14, x0, x2 # x14 = 0xffffffff
# nop
# nop
# nop
# counter and infinite loop
nop nop
nop nop
nop nop