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

This commit is contained in:
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(
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

View File

@@ -2,108 +2,35 @@
module core_tb();
initial $timeformat(-9, 2, " ns", 20);
localparam MEM_INST_LENGTH = 256;
localparam MEM_DATA_LENGTH = 256;
localparam INST_NOP = 32'h00000013; // nop
reg clk, reset;
reg [31:0] mem_inst [0:MEM_INST_LENGTH-1];
wire [31:0] mem_inst_addr;
wire [31:0] mem_inst_idx = mem_inst_addr >> 2;
reg [31:0] mem_inst_data;
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;
wire [31:0] mem_inst_data = mem_inst_idx < MEM_INST_LENGTH ? mem_inst[mem_inst_idx] : INST_NOP;
localparam OP_LUI = 7'b0110111,
OP_AUIPC = 7'b0010111,
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
initial begin: mem_inst_init
integer i;
for (i=0; i<MEM_INST_LENGTH; i=i+1) begin
mem_inst[i] = INST_NOP;
end
$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
initial begin
end
always @(*) begin
if (mem_inst_idx < MEM_INST_LENGTH) begin
mem_inst_data = mem_inst[mem_inst_idx];
end else begin
mem_inst_data = INST_NOP;
end
end
reg [31:0] mem_data [0:MEM_DATA_LENGTH-1];
wire [31:0] mem_data_waddr;
wire [31:0] mem_data_wdata;
wire [3:0] mem_data_wmask;
wire mem_data_we;
wire [31:0] mem_data_raddr;
reg [31:0] mem_data_rdata;
wire [3:0] mem_data_rmask;
initial begin
#0
@@ -125,15 +52,92 @@ core dut(
.reset(reset),
.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_wdata(mem_data_wdata),
.mem_data_rdata(mem_data_rdata),
.mem_data_en(mem_data_en),
.mem_data_we(mem_data_we),
.mem_data_valid(mem_data_valid),
.mem_data_done(mem_data_done)
// .mem_data_addr(mem_data_addr),
// .mem_data_wdata(mem_data_wdata),
// .mem_data_rdata(mem_data_rdata),
// .mem_data_en(mem_data_en),
// .mem_data_we(mem_data_we),
// .mem_data_valid(mem_data_valid),
// .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