Merge branch 'master' into compressed

This commit is contained in:
Clifford Wolf 2016-04-05 11:59:42 +02:00
commit 7909b2a7d9
3 changed files with 161 additions and 67 deletions

View File

@ -27,24 +27,20 @@ check.smt2: picorv32.v
test_sp: testbench_sp.exe firmware/firmware.hex test_sp: testbench_sp.exe firmware/firmware.hex
vvp -N testbench_sp.exe vvp -N testbench_sp.exe
test_axi: testbench_axi.exe firmware/firmware.hex test_axi: testbench.exe firmware/firmware.hex
vvp -N testbench_axi.exe vvp -N testbench.exe +axi_test
test_synth: testbench_synth.exe firmware/firmware.hex test_synth: testbench_synth.exe firmware/firmware.hex
vvp -N testbench_synth.exe vvp -N testbench_synth.exe
testbench.exe: testbench.v picorv32.v testbench.exe: testbench.v picorv32.v
iverilog -o testbench.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) testbench.v picorv32.v iverilog -o testbench.exe $(subst C,-DCOMPRESSED_ISA,$(COMPRESSED_ISA)) testbench.v picorv32.v
chmod -x testbench.exe chmod -x testbench.exe
testbench_sp.exe: testbench.v picorv32.v testbench_sp.exe: testbench.v picorv32.v
iverilog -o testbench_sp.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) -DSP_TEST testbench.v picorv32.v iverilog -o testbench_sp.exe $(subst C,-DCOMPRESSED_ISA,$(COMPRESSED_ISA)) -DSP_TEST testbench.v picorv32.v
chmod -x testbench_sp.exe chmod -x testbench_sp.exe
testbench_axi.exe: testbench.v picorv32.v
iverilog -o testbench_axi.exe $(subst $(COMPRESSED_ISA),C,-DCOMPRESSED_ISA) -DAXI_TEST testbench.v picorv32.v
chmod -x testbench_axi.exe
testbench_synth.exe: testbench.v synth.v testbench_synth.exe: testbench.v synth.v
iverilog -o testbench_synth.exe testbench.v synth.v iverilog -o testbench_synth.exe testbench.v synth.v
chmod -x testbench_synth.exe chmod -x testbench_synth.exe
@ -81,7 +77,7 @@ toc:
clean: clean:
rm -vrf $(FIRMWARE_OBJS) $(TEST_OBJS) check.smt2 check.vcd synth.v synth.log \ rm -vrf $(FIRMWARE_OBJS) $(TEST_OBJS) check.smt2 check.vcd synth.v synth.log \
firmware/firmware.elf firmware/firmware.bin firmware/firmware.hex firmware/firmware.map \ firmware/firmware.elf firmware/firmware.bin firmware/firmware.hex firmware/firmware.map \
testbench.exe testbench_sp.exe testbench_axi.exe testbench_synth.exe testbench.vcd testbench.exe testbench_sp.exe testbench_synth.exe testbench.vcd
.PHONY: test view test_sp test_axi test_synth toc clean .PHONY: test view test_sp test_axi test_synth toc clean

View File

@ -299,7 +299,8 @@ that can run one memory transfer at a time:
The core initiates a memory transfer by asserting `mem_valid`. The valid The core initiates a memory transfer by asserting `mem_valid`. The valid
signal stays high until the peer asserts `mem_ready`. All core outputs signal stays high until the peer asserts `mem_ready`. All core outputs
are stable over the `mem_valid` period. are stable over the `mem_valid` period. If the memory transfer is an
instruction fetch, the core asserts `mem_instr`.
#### Read Transfer #### Read Transfer
@ -318,6 +319,11 @@ In a write transfer `mem_wstrb` is not 0 and `mem_rdata` is unused. The memory
write the data at `mem_wdata` to the address `mem_addr` and acknowledges the write the data at `mem_wdata` to the address `mem_addr` and acknowledges the
transfer by asserting `mem_ready`. transfer by asserting `mem_ready`.
The 4 bits of `mem_wstrb` are write enables for the four bytes in the addressed
word. Only the 8 values `0000`, `1111`, `1100`, `0011`, `1000`, `0100`, `0010`,
and `0001` are possible, i.e. no write, write 32 bits, write upper 16 bits,
write lower 16, or write a single byte respectively.
There is no need for an external wait cycle. The memory can acknowledge the There is no need for an external wait cycle. The memory can acknowledge the
write immediately with `mem_ready` going high in the same cycle as write immediately with `mem_ready` going high in the same cycle as
`mem_valid`, or `mem_ready` being tied to constant 1. `mem_valid`, or `mem_ready` being tied to constant 1.

View File

@ -6,20 +6,15 @@
// means. // means.
`timescale 1 ns / 1 ps `timescale 1 ns / 1 ps
// `define VERBOSE
module testbench; `ifndef VERILATOR
module testbench #(
parameter AXI_TEST = 0,
parameter VERBOSE = 0
);
reg clk = 1; reg clk = 1;
reg resetn = 0; reg resetn = 0;
reg [31:0] irq;
wire trap;
always @* begin
irq = 0;
irq[4] = &uut.picorv32_core.count_cycle[12:0];
irq[5] = &uut.picorv32_core.count_cycle[15:0];
end
always #5 clk = ~clk; always #5 clk = ~clk;
@ -28,27 +23,92 @@ module testbench;
resetn <= 1; resetn <= 1;
end end
initial begin
if ($test$plusargs("vcd")) begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
end
repeat (1000000) @(posedge clk);
$display("TIMEOUT");
$finish;
end
picorv32_wrapper #(
.AXI_TEST (AXI_TEST),
.VERBOSE (VERBOSE)
) top (
.clk (clk ),
.resetn (resetn)
);
endmodule
`endif
module picorv32_wrapper #(
parameter AXI_TEST = 0,
parameter VERBOSE = 0
) (
input clk,
input resetn
);
wire trap;
reg [31:0] irq;
always @* begin
irq = 0;
irq[4] = &uut.picorv32_core.count_cycle[12:0];
irq[5] = &uut.picorv32_core.count_cycle[15:0];
end
wire mem_axi_awvalid; wire mem_axi_awvalid;
reg mem_axi_awready = 0; wire mem_axi_awready;
wire [31:0] mem_axi_awaddr; wire [31:0] mem_axi_awaddr;
wire [ 2:0] mem_axi_awprot; wire [ 2:0] mem_axi_awprot;
wire mem_axi_wvalid; wire mem_axi_wvalid;
reg mem_axi_wready = 0; wire mem_axi_wready;
wire [31:0] mem_axi_wdata; wire [31:0] mem_axi_wdata;
wire [ 3:0] mem_axi_wstrb; wire [ 3:0] mem_axi_wstrb;
reg mem_axi_bvalid = 0; wire mem_axi_bvalid;
wire mem_axi_bready; wire mem_axi_bready;
wire mem_axi_arvalid; wire mem_axi_arvalid;
reg mem_axi_arready = 0; wire mem_axi_arready;
wire [31:0] mem_axi_araddr; wire [31:0] mem_axi_araddr;
wire [ 2:0] mem_axi_arprot; wire [ 2:0] mem_axi_arprot;
reg mem_axi_rvalid = 0; wire mem_axi_rvalid;
wire mem_axi_rready; wire mem_axi_rready;
reg [31:0] mem_axi_rdata; wire [31:0] mem_axi_rdata;
axi4_memory #(
.AXI_TEST (AXI_TEST),
.VERBOSE (VERBOSE)
) mem (
.clk (clk ),
.mem_axi_awvalid (mem_axi_awvalid ),
.mem_axi_awready (mem_axi_awready ),
.mem_axi_awaddr (mem_axi_awaddr ),
.mem_axi_awprot (mem_axi_awprot ),
.mem_axi_wvalid (mem_axi_wvalid ),
.mem_axi_wready (mem_axi_wready ),
.mem_axi_wdata (mem_axi_wdata ),
.mem_axi_wstrb (mem_axi_wstrb ),
.mem_axi_bvalid (mem_axi_bvalid ),
.mem_axi_bready (mem_axi_bready ),
.mem_axi_arvalid (mem_axi_arvalid ),
.mem_axi_arready (mem_axi_arready ),
.mem_axi_araddr (mem_axi_araddr ),
.mem_axi_arprot (mem_axi_arprot ),
.mem_axi_rvalid (mem_axi_rvalid ),
.mem_axi_rready (mem_axi_rready ),
.mem_axi_rdata (mem_axi_rdata )
);
picorv32_axi #( picorv32_axi #(
`ifdef SP_TEST `ifdef SP_TEST
@ -83,8 +143,60 @@ module testbench;
.irq (irq ) .irq (irq )
); );
reg [31:0] memory [0:64*1024/4-1]; reg [1023:0] firmware_file;
initial $readmemh("firmware/firmware.hex", memory); initial begin
if(!$value$plusargs("firmware=%s", firmware_file))
firmware_file = "firmware/firmware.hex";
$readmemh(firmware_file, mem.memory);
end
integer cycle_counter;
always @(posedge clk) begin
cycle_counter <= resetn ? cycle_counter + 1 : 0;
if (resetn && trap) begin
`ifndef VERILATOR
repeat (10) @(posedge clk);
`endif
$display("TRAP after %1d clock cycles", cycle_counter);
$finish;
end
end
endmodule
module axi4_memory #(
parameter AXI_TEST = 0,
parameter VERBOSE = 0
) (
input clk,
input mem_axi_awvalid,
output reg mem_axi_awready = 0,
input [31:0] mem_axi_awaddr,
input [ 2:0] mem_axi_awprot,
input mem_axi_wvalid,
output reg mem_axi_wready = 0,
input [31:0] mem_axi_wdata,
input [ 3:0] mem_axi_wstrb,
output reg mem_axi_bvalid = 0,
input mem_axi_bready,
input mem_axi_arvalid,
output reg mem_axi_arready = 0,
input [31:0] mem_axi_araddr,
input [ 2:0] mem_axi_arprot,
output mem_axi_rvalid = 0,
input mem_axi_rready,
output reg [31:0] mem_axi_rdata
);
reg [31:0] memory [0:64*1024/4-1] /* verilator public */;
reg verbose;
initial verbose = $test$plusargs("verbose") || VERBOSE;
reg axi_test;
initial axi_test = $test$plusargs("axi_test") || AXI_TEST;
reg [63:0] xorshift64_state = 64'd88172645463325252; reg [63:0] xorshift64_state = 64'd88172645463325252;
@ -101,12 +213,12 @@ module testbench;
reg [4:0] async_axi_transaction = ~0; reg [4:0] async_axi_transaction = ~0;
reg [4:0] delay_axi_transaction = 0; reg [4:0] delay_axi_transaction = 0;
`ifdef AXI_TEST
always @(posedge clk) begin always @(posedge clk) begin
xorshift64_next; if (axi_test) begin
{fast_axi_transaction, async_axi_transaction, delay_axi_transaction} <= xorshift64_state; xorshift64_next;
{fast_axi_transaction, async_axi_transaction, delay_axi_transaction} <= xorshift64_state;
end
end end
`endif
reg latched_raddr_en = 0; reg latched_raddr_en = 0;
reg latched_waddr_en = 0; reg latched_waddr_en = 0;
@ -146,9 +258,8 @@ module testbench;
end endtask end endtask
task handle_axi_rvalid; begin task handle_axi_rvalid; begin
`ifdef VERBOSE if(verbose)
$display("RD: ADDR=%08x DATA=%08x%s", latched_raddr, memory[latched_raddr >> 2], latched_rinsn ? " INSN" : ""); $display("RD: ADDR=%08x DATA=%08x%s", latched_raddr, memory[latched_raddr >> 2], latched_rinsn ? " INSN" : "");
`endif
if (latched_raddr < 64*1024) begin if (latched_raddr < 64*1024) begin
mem_axi_rdata <= memory[latched_raddr >> 2]; mem_axi_rdata <= memory[latched_raddr >> 2];
mem_axi_rvalid <= 1; mem_axi_rvalid <= 1;
@ -160,9 +271,8 @@ module testbench;
end endtask end endtask
task handle_axi_bvalid; begin task handle_axi_bvalid; begin
`ifdef VERBOSE if (verbose)
$display("WR: ADDR=%08x DATA=%08x STRB=%04b", latched_waddr, latched_wdata, latched_wstrb); $display("WR: ADDR=%08x DATA=%08x STRB=%04b", latched_waddr, latched_wdata, latched_wstrb);
`endif
if (latched_waddr < 64*1024) begin if (latched_waddr < 64*1024) begin
if (latched_wstrb[0]) memory[latched_waddr >> 2][ 7: 0] <= latched_wdata[ 7: 0]; if (latched_wstrb[0]) memory[latched_waddr >> 2][ 7: 0] <= latched_wdata[ 7: 0];
if (latched_wstrb[1]) memory[latched_waddr >> 2][15: 8] <= latched_wdata[15: 8]; if (latched_wstrb[1]) memory[latched_waddr >> 2][15: 8] <= latched_wdata[15: 8];
@ -170,15 +280,17 @@ module testbench;
if (latched_wstrb[3]) memory[latched_waddr >> 2][31:24] <= latched_wdata[31:24]; if (latched_wstrb[3]) memory[latched_waddr >> 2][31:24] <= latched_wdata[31:24];
end else end else
if (latched_waddr == 32'h1000_0000) begin if (latched_waddr == 32'h1000_0000) begin
`ifdef VERBOSE if (verbose) begin
if (32 <= latched_wdata && latched_wdata < 128) if (32 <= latched_wdata && latched_wdata < 128)
$display("OUT: '%c'", latched_wdata); $display("OUT: '%c'", latched_wdata[7:0]);
else else
$display("OUT: %3d", latched_wdata); $display("OUT: %3d", latched_wdata);
`else end else begin
$write("%c", latched_wdata); $write("%c", latched_wdata[7:0]);
$fflush(); `ifndef VERILATOR
$fflush();
`endif `endif
end
end else begin end else begin
$display("OUT-OF-BOUNDS MEMORY WRITE TO %08x", latched_waddr); $display("OUT-OF-BOUNDS MEMORY WRITE TO %08x", latched_waddr);
$finish; $finish;
@ -237,24 +349,4 @@ module testbench;
if (!mem_axi_rvalid && latched_raddr_en && !delay_axi_transaction[3]) handle_axi_rvalid; if (!mem_axi_rvalid && latched_raddr_en && !delay_axi_transaction[3]) handle_axi_rvalid;
if (!mem_axi_bvalid && latched_waddr_en && latched_wdata_en && !delay_axi_transaction[4]) handle_axi_bvalid; if (!mem_axi_bvalid && latched_waddr_en && latched_wdata_en && !delay_axi_transaction[4]) handle_axi_bvalid;
end end
initial begin
if ($test$plusargs("vcd")) begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
end
repeat (1000000) @(posedge clk);
$display("TIMEOUT");
$finish;
end
integer cycle_counter;
always @(posedge clk) begin
cycle_counter <= resetn ? cycle_counter + 1 : 0;
if (resetn && trap) begin
repeat (10) @(posedge clk);
$display("TRAP after %1d clock cycles", cycle_counter);
$finish;
end
end
endmodule endmodule