2021-09-08 23:43:15 -06:00
|
|
|
`timescale 1ns/1ps
|
|
|
|
|
|
|
|
module tb();
|
|
|
|
|
|
|
|
localparam ADDR_FAILCODE = 32'h800;
|
|
|
|
localparam WATCHDOG_MAX = 32'h00001000;
|
|
|
|
|
|
|
|
initial $timeformat(-9, 2, " ns", 20);
|
|
|
|
initial begin: dump
|
|
|
|
integer i;
|
|
|
|
$dumpfile("tb.vcd");
|
|
|
|
$dumpvars(0, tb);
|
|
|
|
// for (i=0; i<32; i=i+1) begin
|
|
|
|
// $dumpvars(0, dut.regfile[i]);
|
|
|
|
// end
|
2021-09-09 00:06:15 -06:00
|
|
|
// $dumpvars(0, mem[ADDR_FAILCODE]);
|
2021-09-08 23:43:15 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
reg clk, reset;
|
|
|
|
wire dummy_out;
|
|
|
|
|
|
|
|
// Memory Parameters
|
|
|
|
localparam MEM_ROM_LENGTH = 2048; // bytes
|
|
|
|
localparam MEM_LENGTH = MEM_ROM_LENGTH + 2048; // bytes
|
|
|
|
localparam DATA_INVALID = 32'hdeadbeef;
|
|
|
|
|
|
|
|
// Memory
|
|
|
|
reg [7:0] mem [0:MEM_LENGTH-1];
|
|
|
|
initial $readmemh("tb.hex", mem);
|
|
|
|
|
|
|
|
// Instruction Memory
|
|
|
|
wire [31:0] mem_inst_addr;
|
|
|
|
reg [31:0] mem_inst_data;
|
|
|
|
always @(*) begin
|
|
|
|
if (mem_inst_addr < MEM_LENGTH - 3) begin
|
|
|
|
mem_inst_data[ 7: 0] = mem[mem_inst_addr+0];
|
|
|
|
mem_inst_data[15: 8] = mem[mem_inst_addr+1];
|
|
|
|
mem_inst_data[23:16] = mem[mem_inst_addr+2];
|
|
|
|
mem_inst_data[31:24] = mem[mem_inst_addr+3];
|
|
|
|
end else begin
|
|
|
|
mem_inst_data = DATA_INVALID;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// Data memory
|
|
|
|
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;
|
|
|
|
reg mem_data_wready;
|
|
|
|
reg mem_data_rvalid;
|
|
|
|
|
|
|
|
always @(mem_data_addr) begin
|
|
|
|
mem_data_rvalid = 1'b1;
|
|
|
|
if (mem_data_addr < MEM_LENGTH - 3) begin
|
|
|
|
mem_data_rdata[ 7: 0] = mem[mem_data_addr+0];
|
|
|
|
if (mem_data_addr[0] == 0) begin
|
|
|
|
mem_data_rdata[15: 8] = mem[mem_data_addr+1];
|
|
|
|
if (mem_data_addr[1] == 0) begin
|
|
|
|
mem_data_rdata[23:16] = mem[mem_data_addr+2];
|
|
|
|
mem_data_rdata[31:24] = mem[mem_data_addr+3];
|
|
|
|
end else begin
|
|
|
|
mem_data_rdata[31:16] = 0;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
mem_data_rdata[31:8] = 0;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
mem_data_rdata = DATA_INVALID;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge clk) begin
|
|
|
|
if (mem_data_we) begin
|
|
|
|
if (mem_data_wready) begin
|
|
|
|
mem_data_wready = 1'b0;
|
|
|
|
if (mem_data_addr < MEM_LENGTH && mem_data_addr >= MEM_ROM_LENGTH) begin
|
|
|
|
if (mem_data_wmask[0]) begin
|
|
|
|
mem[mem_data_addr+0] <= mem_data_wdata[7:0];
|
|
|
|
end
|
|
|
|
if (mem_data_wmask[1]) begin
|
|
|
|
mem[mem_data_addr+1] <= mem_data_wdata[15:8];
|
|
|
|
end
|
|
|
|
if (mem_data_wmask[2]) begin
|
|
|
|
mem[mem_data_addr+2] <= mem_data_wdata[23:16];
|
|
|
|
end
|
|
|
|
if (mem_data_wmask[3]) begin
|
|
|
|
mem[mem_data_addr+3] <= mem_data_wdata[31:24];
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
// ignore illegal writes
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
mem_data_wready = 1'b1;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
mem_data_wready = 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
// Main control
|
|
|
|
initial begin
|
|
|
|
#0
|
|
|
|
clk = 0;
|
|
|
|
reset = 1;
|
|
|
|
|
|
|
|
#10
|
|
|
|
reset = 0;
|
|
|
|
|
|
|
|
#10000
|
|
|
|
reset = 1;
|
|
|
|
$finish;
|
|
|
|
end
|
|
|
|
|
|
|
|
integer watchdog = 0;
|
|
|
|
logic [31:0] returnval;
|
|
|
|
always @(posedge clk) begin
|
|
|
|
#100
|
|
|
|
returnval = {mem[ADDR_FAILCODE+3], mem[ADDR_FAILCODE+2], mem[ADDR_FAILCODE+1], mem[ADDR_FAILCODE+0]};
|
|
|
|
case (returnval)
|
|
|
|
32'h00000000: begin
|
|
|
|
// Initial value
|
|
|
|
end
|
|
|
|
32'hffffffff: begin
|
|
|
|
// Success
|
|
|
|
#100
|
|
|
|
$display("%0t:\tSUCCESS: TEST PASSED", $time);
|
|
|
|
$finish;
|
|
|
|
end
|
|
|
|
default: begin
|
|
|
|
$display("%0t:\tERROR: FAILCODE = 0x%h", $time, returnval);
|
|
|
|
#200
|
|
|
|
$finish;
|
|
|
|
end
|
|
|
|
endcase
|
|
|
|
|
|
|
|
watchdog = watchdog + 1;
|
|
|
|
if (watchdog > WATCHDOG_MAX) begin
|
|
|
|
$display("%0t:\tERROR: WATCHDOG", $time);
|
|
|
|
#200
|
|
|
|
$finish;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always #2 clk = !clk;
|
|
|
|
|
|
|
|
core dut(
|
|
|
|
.clk(clk),
|
|
|
|
.reset(reset),
|
|
|
|
|
|
|
|
.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_rvalid(mem_data_rvalid),
|
|
|
|
.mem_data_wready(mem_data_wready),
|
|
|
|
|
|
|
|
// .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)
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
|
|
// 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()
|
|
|
|
// );
|
|
|
|
|
|
|
|
endmodule
|