diff --git a/hdl/core.v b/hdl/core.v
index c9f9780..b7b2e7d 100644
--- a/hdl/core.v
+++ b/hdl/core.v
@@ -2,16 +2,30 @@ module core(
input clk,
input reset,
+ // Memory - instruction
output reg [31:0] mem_inst_addr,
input [31:0] mem_inst_data,
- // output reg [31:0] mem_data_addr,
+ // // Memory - data
+ output reg [31:0] mem_data_addr,
+ input [31:0] mem_data_rdata,
+ output reg [31:0] mem_data_wdata,
+ output reg [(32/8)-1:0] mem_data_wmask,
+ output reg mem_data_we,
+
+ // output reg [31:0] mem_data_waddr,
// 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 [3:0] mem_data_wmask,
+ // output reg mem_data_wvalid,
+ // input wire mem_data_wready,
+
+ // output reg [31:0] mem_data_raddr,
+ // output reg mem_data_raddr_valid,
+ // input wire mem_data_raddr_ready,
+
+ // input wire [31:0] mem_data_rdata,
+ // input wire mem_data_rdata_valid,
+ // output reg mem_data_rdata_ready,
// // instruction memory
@@ -78,21 +92,26 @@ initial begin : init_regfile
end
// Registers
-reg [31:0] r_if_pc = 0, r_id_pc, r_ex_pc, r_mem_pc, r_wb_pc;
-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 [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;
-reg r_ex_jump;
-reg r_ex_store, r_mem_store;
-reg r_ex_load, r_mem_load;
-reg [31:0] r_mem_wdata, r_wb_wdata;
-reg r_id_valid=0, r_ex_valid=0, r_mem_valid=0, r_wb_valid=0;
-reg r_ex_branch_pol;
-reg r_ex_branch, r_mem_branch, r_wb_branch;
-reg [31:0] r_ex_immed_btype;
+reg [31:0] r_if_pc = 0, r_id_pc, r_ex_pc, r_mem_pc, r_wb_pc;
+reg [31:0] r_id_inst, r_ex_inst, r_mem_inst, r_wb_inst;
+reg r_id_valid=0, r_ex_valid=0, r_mem_valid=0, r_wb_valid=0;
+reg [4:0] r_ex_rs1, r_mem_rs1, r_wb_rs1;
+reg [4:0] r_ex_rs2, r_mem_rs2, r_wb_rs2;
+reg [4:0] r_ex_rd, r_mem_rd, r_wb_rd;
+reg [3:0] r_ex_aluop;
+reg [31:0] r_ex_s1, r_mem_s1;
+reg [31:0] r_ex_s2, r_mem_s2;
+reg [31:0] r_mem_alu_out, r_wb_alu_out;
+reg r_mem_alu_zero;
+reg r_ex_jump, r_mem_jump, r_wb_jump;
+reg r_ex_store, r_mem_store;
+reg r_ex_load, r_mem_load, r_wb_load;
+reg [31:0] r_mem_wdata, r_wb_wdata;
+reg r_ex_branch_pol;
+reg r_ex_branch, r_mem_branch, r_wb_branch;
+reg [31:0] r_ex_immed_btype;
+reg [31:0] r_mem_ra, r_wb_ra;
+reg [31:0] r_wb_load_data;
// IF
reg s_if_stall = 0;
@@ -240,9 +259,12 @@ always @(*) begin
// OP_LOAD: begin
// end
- // OP_STORE: begin
-
- // end
+ OP_STORE: begin
+ s_id_store = 1;
+ s_id_s1 = regfile[s_id_rs1];
+ s_id_s2 = s_id_immed_stype;
+ // TODO: finish parsing (byte vs word. For now always assume word)
+ end
OP_IMM: begin
s_id_s1 = regfile[s_id_rs1];
s_id_s2 = s_id_immed_itype;
@@ -309,9 +331,9 @@ reg s_ex_stall = 0;
reg [31:0] s_ex_data1, s_ex_data2;
reg [31:0] s_ex_alu_out;
reg s_ex_alu_zero;
-reg [31:0] s_ex_wdata;
reg s_ex_take_branch;
reg [31:0] s_ex_branch_addr;
+reg [31:0] s_ex_ra;
always @(*) begin
s_ex_stall = s_mem_stall;
@@ -358,11 +380,10 @@ always @(*) begin
s_ex_alu_zero = (s_ex_alu_out == 0);
s_ex_take_branch = r_ex_valid && (r_ex_jump || (r_ex_branch && (s_ex_alu_zero ^ r_ex_branch_pol)));
+ s_ex_ra = r_ex_pc + 4;
if (r_ex_jump) begin
- s_ex_wdata = r_ex_pc + 4;
s_ex_branch_addr = s_ex_alu_out;
end else begin
- s_ex_wdata = s_ex_alu_out;
s_ex_branch_addr = r_ex_pc + r_ex_immed_btype;
end
end
@@ -370,24 +391,17 @@ end
// MEM
reg s_mem_stall = 0;
reg s_mem_bp;
+reg [31:0] s_mem_load_data;
always @(*) begin
s_mem_stall = 0; // TODO: add stall logic when actually reading/writing
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
+ mem_data_addr = r_mem_alu_out;
+ mem_data_wdata = regfile[r_mem_rs2];
+ mem_data_wmask = 4'b1111; // TODO: implement smaller writes
+ mem_data_we = r_mem_store && r_mem_valid;
+ s_mem_load_data = mem_data_rdata; // TODO: implement smaller reads
end
// WB
@@ -397,7 +411,13 @@ reg s_wb_write;
always @(*) begin
// load instructions do not use output of alu in wb
- s_wb_data = r_wb_wdata;
+ if (r_wb_jump) begin
+ s_wb_data = r_wb_ra;
+ end else if (r_wb_load) begin
+ s_wb_data = r_wb_load_data;
+ end else begin
+ s_wb_data = r_wb_alu_out;
+ end
// FIXME: always writes!!!
s_wb_write = (r_wb_branch == 0);
@@ -433,13 +453,10 @@ always @(posedge clk) begin: pipeline_update
r_mem_alu_zero <= 0;
r_mem_store <= 0;
r_mem_load <= 0;
- r_mem_wdata <= 0;
r_wb_pc <= 0;
r_wb_inst <= INST_NOP;
r_wb_rd <= 0;
- r_wb_alu_out <= 0;
- r_wb_wdata <= 0;
for (i=1; i<32; i=i+1) begin
regfile[i] <= 0;
@@ -462,6 +479,8 @@ always @(posedge clk) begin: pipeline_update
if (!s_ex_stall) begin
r_ex_pc <= r_id_pc;
r_ex_inst <= r_id_inst;
+ r_ex_rs1 <= s_id_rs1;
+ r_ex_rs2 <= s_id_rs2;
r_ex_rd <= s_id_rd;
r_ex_s1 <= s_id_s1;
r_ex_s2 <= s_id_s2;
@@ -480,6 +499,8 @@ always @(posedge clk) begin: pipeline_update
if (!s_mem_stall) begin
r_mem_pc <= r_ex_pc;
r_mem_inst <= r_ex_inst;
+ r_mem_rs1 <= r_ex_rs1;
+ r_mem_rs2 <= r_ex_rs2;
r_mem_rd <= r_ex_rd;
r_mem_s1 <= r_ex_s1;
r_mem_s2 <= r_ex_s2;
@@ -487,20 +508,26 @@ always @(posedge clk) begin: pipeline_update
r_mem_alu_zero <= s_ex_alu_zero;
r_mem_store <= r_ex_store;
r_mem_load <= r_ex_load;
- r_mem_wdata <= s_ex_wdata;
r_mem_valid <= r_ex_valid;
r_mem_branch <= r_ex_branch;
+ r_mem_ra <= s_ex_ra;
+ r_mem_jump <= r_ex_jump;
end
// WB
if (1) begin
r_wb_pc <= r_mem_pc;
r_wb_inst <= r_mem_inst;
+ r_wb_rs1 <= r_mem_rs1;
+ r_wb_rs2 <= r_mem_rs2;
r_wb_rd <= r_mem_rd;
r_wb_alu_out <= r_mem_alu_out;
- r_wb_wdata <= r_mem_wdata;
r_wb_valid <= r_mem_valid;
r_wb_branch <= r_mem_branch;
+ r_wb_ra <= r_mem_ra;
+ r_wb_jump <= r_mem_jump;
+ r_wb_load <= r_mem_load;
+ r_wb_load_data <= s_mem_load_data;
end
// Register File
diff --git a/hdl/tb/core_tb.v b/hdl/tb/core_tb.v
index d2417d8..bbf733e 100644
--- a/hdl/tb/core_tb.v
+++ b/hdl/tb/core_tb.v
@@ -10,7 +10,8 @@ localparam MEM_INST_LENGTH = 256; // words
localparam MEM_DATA_LENGTH = 256; // words
localparam INST_NOP = 32'h00000013; // nop
-localparam DATA_DEFAULT = 32'hdeadbeef;
+localparam DATA_DEFAULT = 32'h00000000;
+localparam DATA_INVALID = 32'hdeadbeef;
reg clk, reset;
@@ -30,13 +31,11 @@ end
// Data memory
reg [31:0] mem_data [0:MEM_DATA_LENGTH-1];
-wire [31:0] mem_data_waddr;
+wire [31:0] mem_data_addr;
+reg [31:0] mem_data_rdata;
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: mem_data_init
integer i;
@@ -54,7 +53,7 @@ initial begin
#10
reset = 0;
- #1000
+ #2000
reset = 1;
$stop;
end
@@ -68,6 +67,12 @@ core dut(
.mem_inst_addr(mem_inst_addr),
.mem_inst_data(mem_inst_data),
+ .mem_data_addr(mem_data_addr),
+ .mem_data_rdata(mem_data_rdata),
+ .mem_data_wdata(mem_data_wdata),
+ .mem_data_wmask(mem_data_wmask),
+ .mem_data_we(mem_data_we),
+
// .mem_data_addr(mem_data_addr),
// .mem_data_wdata(mem_data_wdata),
// .mem_data_rdata(mem_data_rdata),
@@ -79,81 +84,84 @@ core dut(
.dummy_out(dummy_out)
);
-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;
+// 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),
+// 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_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()
-);
+// .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;
+wire [31:0] mem_data_idx = mem_data_addr >> 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]}}});
+ if (mem_data_idx < MEM_DATA_LENGTH) begin
+ mem_data_rdata = mem_data[mem_data_idx];
+ if (mem_data_we) begin
+ if (mem_data_wmask[0]) begin
+ mem_data[mem_data_idx][7:0] <= mem_data_wdata[7:0];
+ end
+ if (mem_data_wmask[1]) begin
+ mem_data[mem_data_idx][15:8] <= mem_data_wdata[15:8];
+ end
+ if (mem_data_wmask[2]) begin
+ mem_data[mem_data_idx][23:16] <= mem_data_wdata[23:16];
+ end
+ if (mem_data_wmask[3]) begin
+ mem_data[mem_data_idx][31:24] <= mem_data_wdata[31:24];
+ end
end
+ end else begin
+ mem_data_rdata = DATA_INVALID;
// 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
\ No newline at end of file
diff --git a/sim/core_tb.wcfg b/sim/core_tb.wcfg
index 4400b6b..2cd9504 100644
--- a/sim/core_tb.wcfg
+++ b/sim/core_tb.wcfg
@@ -10,7 +10,7 @@
-
+
clk
clk
@@ -19,6 +19,11 @@
reset
reset
+
+ mem_data[0:255,31:0]
+ mem_data[0:255,31:0]
+ HEXRADIX
+
regfile[0:31,31:0]
regfile[0:31,31:0]
@@ -432,6 +437,14 @@
r_mem_alu_zero
r_mem_alu_zero
+
+ r_mem_store
+ r_mem_store
+
+
+ r_mem_load
+ r_mem_load
+
WB
@@ -450,16 +463,25 @@
r_wb_inst[31:0]
HEXRADIX
-
- r_wb_alu_out[31:0]
- r_wb_alu_out[31:0]
- HEXRADIX
-
r_wb_rd[4:0]
r_wb_rd[4:0]
UNSIGNEDDECRADIX
+
+ r_wb_ra
+ r_wb_ra
+
+
+ r_wb_load_data[31:0]
+ r_wb_load_data[31:0]
+ HEXRADIX
+
+
+ r_wb_alu_out[31:0]
+ r_wb_alu_out[31:0]
+ HEXRADIX
+
s_wb_data[31:0]
s_wb_data[31:0]
diff --git a/test/Makefile b/test/Makefile
index fb01f9c..f213c35 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -16,8 +16,8 @@ LDFLAGS = -T test.ld
%.o: %.c
$(CC) $(CFLAGS) $^ -o $@
-%.elf: %.o
- $(LD) $(LDFLAGS) $^ -o $@
+%.elf: %.o %.ld
+ $(LD) $(LDFLAGS) $< -o $@
text.hex: test.elf
riscv64-linux-gnu-objdump -s $^ | sed -n '/.text/,$$p' | tail -n+2 | sed -n '/.data/,$$!p' | cut -f3-6 -d ' ' | sed -e 's/ /\n/g' | sed 's/^\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/' > $@
diff --git a/test/decoder.xlsx b/test/decoder.xlsx
index 5626da2..dd78cea 100644
Binary files a/test/decoder.xlsx and b/test/decoder.xlsx differ
diff --git a/test/test.S b/test/test.S
index 67372ba..a17eec7 100644
--- a/test/test.S
+++ b/test/test.S
@@ -27,7 +27,7 @@ _start:
# or
or x9, x1, x2 # x9 = 0xffffffff
or x10, x1, x0 # x10 = 0xfedcb789
- or x11, x4, x3 # x11 = 0x0xfedcb79a
+ or x11, x4, x3 # x11 = 0xfedcb79a
# xor
xor x12, x1, x2 # x12 = 0x01234876
@@ -209,27 +209,29 @@ test9:
j fail
test10:
- # now for some memory stuff
-# # sw
-# la x9, someint # x9 = start of .bss
-# li x10, 0x12345678 # x10 = 0x12345678
-# nop
-# nop
-# nop
-# nop
-# nop
-# sw x10, 0(x9) # someint = 0x12345678
-# nop
-# nop
-# nop
-# nop
-# nop
-# lw x11, 0(x9) # x11 = 0x12345678
-# nop
-# nop
-# nop
-# nop
-# nop
+ addi x30, x0, 10 # x30 = 10
+ # # now for some memory stuff
+ # # sw
+ # la x9, someint # x9 = start of .bss
+ # lui x10, 0x12345 # x10 = 0x12345000
+ # addi x10, x10, 0x678 # x10 = 0x12345678
+ # nop
+ # nop
+ # nop
+ # nop
+ # nop
+ # sw x10, 0(x9) # someint = 0x12345678
+ # nop
+ # nop
+ # nop
+ # nop
+ # nop
+ # # lw x11, 0(x9) # x11 = 0x12345678
+ # nop
+ # nop
+ # nop
+ # nop
+ # nop
done:
diff --git a/test/test.ld b/test/test.ld
index 13d874c..057f3bf 100644
--- a/test/test.ld
+++ b/test/test.ld
@@ -3,7 +3,7 @@ ENTRY(_start)
MEMORY
{
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 1024
- RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 512
+ RAM (rwx) : ORIGIN = 0x00100000, LENGTH = 1024
/* FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 512 */
}
@@ -11,20 +11,20 @@ SECTIONS
{
.text :
{
- . = ALIGN(4);
+ /* . = ALIGN(4); */
_text = .;
*(.text*)
*(.rodata*)
_etext = .;
- . = ALIGN(4);
+ /* . = ALIGN(4); */
} > ROM
.data :
{
- . = ALIGN(4);
+ /* . = ALIGN(4); */
_data = .;
*(.data*)
_edata = .;
- . = ALIGN(4);
+ /* . = ALIGN(4); */
} > RAM /*AT> FLASH*/
}
\ No newline at end of file