mirror of
https://gitlab.com/brendanhaines/cpu.git
synced 2024-12-25 18:46:53 -07:00
passes quick tests for: lui, addi, add, sub, and, or, xor, andi. jump works but does not link
This commit is contained in:
parent
3fbd96ca27
commit
2c24c19a72
152
hdl/axi_lite_memory.v
Normal file
152
hdl/axi_lite_memory.v
Normal 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
|
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
|
||||
|
|
198
hdl/tb/core_tb.v
198
hdl/tb/core_tb.v
|
@ -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
|
|
@ -2,7 +2,8 @@ XILINX = /opt/Xilinx/14.7/ISE_DS/ISE/
|
|||
PROJECT = riscv_core
|
||||
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
|
||||
|
||||
VTEST = hdl/tb/core_tb.v
|
||||
|
|
123
test/test.S
123
test/test.S
|
@ -1,88 +1,105 @@
|
|||
.global _start
|
||||
.text
|
||||
_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.
|
||||
# 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
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
lui x1, 0xfedcb # x1 = 0xfedcb000
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# addi
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
addi x1, x1, 0x789 # x1 = 0xfedcb789
|
||||
addi x2, x0, -1 # x2 = 0xffffffff
|
||||
nop
|
||||
nop
|
||||
addi x3, x1, -0x777 # x3 = 0xfedcb012
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# add
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
add x4, x1, x2 # x4 = 0xfedcb788
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# sub
|
||||
sub x5, x1, x3 # x5 = 0x00000777
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
add x5, x1, x3 # x5 = 0x00000777 incorrect
|
||||
|
||||
# and
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
and x6, x1, x2 # x6 = 0xfedcb789
|
||||
and x7, x1, x0 # x7 = 0x00000000
|
||||
and x8, x4, x3 # x8 = 0xfedcb002 incorrect
|
||||
and x8, x4, x3 # x8 = 0xfedcb000
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# or
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
or x9, x1, x2 # x9 = 0xffffffff
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user