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