aboutsummaryrefslogtreecommitdiffstats
path: root/picosoc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-08-07 22:36:58 +0200
committerClifford Wolf <clifford@clifford.at>2017-08-07 22:36:58 +0200
commit8821696748afe0dab113c845910be9db9d772438 (patch)
treeba7b55cefc5386a911c9b75a994bf29b9e3f431a /picosoc
parentff7855900d4f4b8d3ccd840e54f5d9c940c4f7e4 (diff)
downloadpicorv32-8821696748afe0dab113c845910be9db9d772438.tar.gz
picorv32-8821696748afe0dab113c845910be9db9d772438.zip
Major rewrite of picosoc spimemio core
Diffstat (limited to 'picosoc')
-rw-r--r--picosoc/.gitignore3
-rw-r--r--picosoc/Makefile18
-rw-r--r--picosoc/firmware.s35
-rw-r--r--picosoc/hx8kdemo_tb.v66
-rw-r--r--picosoc/spimemio.v369
5 files changed, 410 insertions, 81 deletions
diff --git a/picosoc/.gitignore b/picosoc/.gitignore
index 905623b..cef6edf 100644
--- a/picosoc/.gitignore
+++ b/picosoc/.gitignore
@@ -11,3 +11,6 @@
/hx8kdemo.blif
/hx8kdemo.log
/hx8kdemo.rpt
+/hx8kdemo_syn.v
+/hx8kdemo_syn_tb.vvp
+/hx8kdemo_tb.vvp
diff --git a/picosoc/Makefile b/picosoc/Makefile
index 8900ecb..8297a63 100644
--- a/picosoc/Makefile
+++ b/picosoc/Makefile
@@ -19,9 +19,24 @@ hx8kprog: hx8kdemo.bin firmware.bin
iceprog hx8kdemo.bin
iceprog -o 1M firmware.bin
+hx8ksim: hx8kdemo_tb.vvp firmware.hex
+ vvp -N $<
+
+hx8ksynsim: hx8kdemo_syn_tb.vvp firmware.hex
+ vvp -N $<
+
hx8kdemo.blif: hx8kdemo.v spimemio.v picosoc.v ../picorv32.v
yosys -ql hx8kdemo.log -p 'synth_ice40 -top hx8kdemo -blif hx8kdemo.blif' $^
+hx8kdemo_tb.vvp: hx8kdemo_tb.v hx8kdemo.v spimemio.v picosoc.v ../picorv32.v spiflash.v
+ iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v`
+
+hx8kdemo_syn_tb.vvp: hx8kdemo_tb.v hx8kdemo_syn.v spiflash.v
+ iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v`
+
+hx8kdemo_syn.v: hx8kdemo.blif
+ yosys -p 'read_blif -wideports hx8kdemo.blif; write_verilog hx8kdemo_syn.v'
+
hx8kdemo.asc: hx8kdemo.pcf hx8kdemo.blif
arachne-pnr -d 8k -o hx8kdemo.asc -p hx8kdemo.pcf hx8kdemo.blif
@@ -49,6 +64,7 @@ clean:
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd
rm -f firmware.elf firmware_vma.elf firmware.hex firmware.bin
rm -f hx8kdemo.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin
+ rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp
-.PHONY: testbench spiflash_tb hx8kprog clean
+.PHONY: testbench spiflash_tb hx8kprog hx8ksim hx8ksynsim clean
diff --git a/picosoc/firmware.s b/picosoc/firmware.s
index 69fedcc..1b8900f 100644
--- a/picosoc/firmware.s
+++ b/picosoc/firmware.s
@@ -19,8 +19,37 @@ sw x5,64(x0)
sw x5,68(x0)
sw x5,72(x0)
sw x5,76(x0)
-li x5,0x00008067 # ret
sw x5,80(x0)
+sw x5,84(x0)
+sw x5,88(x0)
+sw x5,92(x0)
+sw x5,96(x0)
+sw x5,100(x0)
+sw x5,104(x0)
+sw x5,108(x0)
+sw x5,112(x0)
+sw x5,116(x0)
+sw x5,120(x0)
+sw x5,124(x0)
+sw x5,128(x0)
+sw x5,132(x0)
+sw x5,136(x0)
+sw x5,140(x0)
+sw x5,144(x0)
+sw x5,148(x0)
+sw x5,152(x0)
+sw x5,156(x0)
+sw x5,160(x0)
+sw x5,164(x0)
+sw x5,168(x0)
+sw x5,172(x0)
+sw x5,176(x0)
+sw x5,180(x0)
+sw x5,184(x0)
+sw x5,188(x0)
+sw x5,192(x0)
+li x5,0x00008067 # ret
+sw x5,196(x0)
# setup gpio address in x5
li x5,0x02000000
@@ -48,8 +77,8 @@ sw x6,0(x0)
# calculate new entry point into RAM code
slli x3,x6,2
-andi x3,x3,63
-addi x3,x3,4
+andi x3,x3,127
+addi x3,x3,32
# execute RAM code, come back to start of loop
mv x1,x4
diff --git a/picosoc/hx8kdemo_tb.v b/picosoc/hx8kdemo_tb.v
new file mode 100644
index 0000000..ffb292f
--- /dev/null
+++ b/picosoc/hx8kdemo_tb.v
@@ -0,0 +1,66 @@
+/*
+ * PicoSoC - A simple example SoC using PicoRV32
+ *
+ * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+`timescale 1 ns / 1 ps
+
+module testbench;
+ reg clk;
+ always #5 clk = (clk === 1'b0);
+
+ initial begin
+ $dumpfile("testbench.vcd");
+ $dumpvars(0, testbench);
+
+ repeat (100000) @(posedge clk);
+ $finish;
+ end
+
+ wire [7:0] leds;
+
+ wire flash_csb;
+ wire flash_clk;
+ wire flash_io0;
+ wire flash_io1;
+ wire flash_io2;
+ wire flash_io3;
+
+ always @(leds) begin
+ $display("%b", leds);
+ end
+
+ hx8kdemo uut (
+ .clk (clk ),
+ .leds (leds ),
+ .flash_csb(flash_csb),
+ .flash_clk(flash_clk),
+ .flash_io0(flash_io0),
+ .flash_io1(flash_io1),
+ .flash_io2(flash_io2),
+ .flash_io3(flash_io3)
+ );
+
+ spiflash spiflash (
+ .csb(flash_csb),
+ .clk(flash_clk),
+ .io0(flash_io0),
+ .io1(flash_io1),
+ .io2(flash_io2),
+ .io3(flash_io3)
+ );
+endmodule
diff --git a/picosoc/spimemio.v b/picosoc/spimemio.v
index 57347cc..93227cb 100644
--- a/picosoc/spimemio.v
+++ b/picosoc/spimemio.v
@@ -21,10 +21,225 @@ module spimemio (
input clk, resetn,
input valid,
- output reg ready,
+ output ready,
input [23:0] addr,
output reg [31:0] rdata,
+ output flash_csb,
+ output flash_clk,
+
+ output flash_io0_oe,
+ output flash_io1_oe,
+ output flash_io2_oe,
+ output flash_io3_oe,
+
+ output flash_io0_do,
+ output flash_io1_do,
+ output flash_io2_do,
+ output flash_io3_do,
+
+ input flash_io0_di,
+ input flash_io1_di,
+ input flash_io2_di,
+ input flash_io3_di
+);
+ reg xfer_resetn;
+ reg din_valid;
+ wire din_ready;
+ reg [7:0] din_data;
+ reg din_cont;
+ reg din_qspi;
+ reg din_ddr;
+ reg din_rd;
+
+ wire dout_valid;
+ wire [7:0] dout_data;
+
+ reg [23:0] buffer;
+ reg [3:0] buffer_wen;
+
+ reg [23:0] rd_addr;
+ reg rd_valid;
+ reg rd_wait;
+ reg rd_inc;
+
+ assign ready = valid && (addr == rd_addr) && rd_valid;
+ wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
+
+ spimemio_xfer xfer (
+ .clk (clk ),
+ .resetn (xfer_resetn ),
+ .din_valid (din_valid ),
+ .din_ready (din_ready ),
+ .din_data (din_data ),
+ .din_cont (din_cont ),
+ .din_qspi (din_qspi ),
+ .din_ddr (din_ddr ),
+ .din_rd (din_rd ),
+ .dout_valid (dout_valid ),
+ .dout_data (dout_data ),
+ .flash_csb (flash_csb ),
+ .flash_clk (flash_clk ),
+ .flash_io0_oe (flash_io0_oe),
+ .flash_io1_oe (flash_io1_oe),
+ .flash_io2_oe (flash_io2_oe),
+ .flash_io3_oe (flash_io3_oe),
+ .flash_io0_do (flash_io0_do),
+ .flash_io1_do (flash_io1_do),
+ .flash_io2_do (flash_io2_do),
+ .flash_io3_do (flash_io3_do),
+ .flash_io0_di (flash_io0_di),
+ .flash_io1_di (flash_io1_di),
+ .flash_io2_di (flash_io2_di),
+ .flash_io3_di (flash_io3_di)
+ );
+
+ reg [3:0] state;
+
+ always @(posedge clk) begin
+ xfer_resetn <= 1;
+ din_valid <= 0;
+ din_data <= 8'h 00;
+
+ if (!resetn) begin
+ state <= 0;
+ xfer_resetn <= 0;
+ rd_valid <= 0;
+ din_cont <= 0;
+ din_qspi <= 0;
+ din_ddr <= 0;
+ din_rd <= 0;
+ end else begin
+ if (dout_valid && buffer_wen[0]) buffer[ 7: 0] <= dout_data;
+ if (dout_valid && buffer_wen[1]) buffer[15: 8] <= dout_data;
+ if (dout_valid && buffer_wen[2]) buffer[23:16] <= dout_data;
+ if (dout_valid && buffer_wen[3]) begin
+ rdata <= {dout_data, buffer};
+ rd_addr <= rd_inc ? rd_addr + 4 : addr;
+ rd_valid <= 1;
+ rd_wait <= rd_inc;
+ rd_inc <= 1;
+ end
+
+ if (dout_valid && buffer_wen) begin
+ buffer_wen <= 0;
+ end
+
+ if (valid)
+ rd_wait <= 0;
+
+ case (state)
+ 0: begin
+ din_valid <= 1;
+ din_data <= 8'h ff;
+ if (din_ready)
+ state <= 1;
+ end
+ 1: begin
+ if (dout_valid) begin
+ xfer_resetn <= 0;
+ state <= 2;
+ end
+ end
+ 2: begin
+ din_valid <= 1;
+ din_data <= 8'h ab;
+ if (din_ready)
+ state <= 3;
+ end
+ 3: begin
+ if (dout_valid) begin
+ xfer_resetn <= 0;
+ state <= 4;
+ end
+ end
+ 4: begin
+ rd_inc <= 0;
+ din_valid <= 1;
+ din_data <= 8'h 03;
+ if (din_ready)
+ state <= 5;
+ end
+ 5: begin
+ if (valid && !ready) begin
+ din_valid <= 1;
+ din_data <= addr[23:16];
+ if (din_ready)
+ state <= 6;
+ end
+ end
+ 6: begin
+ din_valid <= 1;
+ din_data <= addr[15:8];
+ if (din_ready)
+ state <= 7;
+ end
+ 7: begin
+ din_valid <= 1;
+ din_data <= addr[7:0];
+ if (din_ready)
+ state <= 8;
+ end
+ 8: begin
+ din_valid <= 1;
+ din_data <= 8'h 00;
+ if (din_ready) begin
+ buffer_wen <= 4'b 0001;
+ state <= 9;
+ end
+ end
+ 9: begin
+ din_valid <= 1;
+ din_data <= 8'h 00;
+ if (din_ready) begin
+ buffer_wen <= 4'b 0010;
+ state <= 10;
+ end
+ end
+ 10: begin
+ din_valid <= 1;
+ din_data <= 8'h 00;
+ if (din_ready) begin
+ buffer_wen <= 4'b 0100;
+ state <= 11;
+ end
+ end
+ 11: begin
+ if (!rd_wait || valid) begin
+ din_valid <= 1;
+ din_data <= 8'h 00;
+ if (din_ready) begin
+ buffer_wen <= 4'b 1000;
+ state <= 8;
+ end
+ end
+ end
+ endcase
+
+ if (jump) begin
+ rd_inc <= 0;
+ rd_valid <= 0;
+ xfer_resetn <= 0;
+ state <= 4;
+ end
+ end
+ end
+endmodule
+
+module spimemio_xfer (
+ input clk, resetn,
+
+ input din_valid,
+ output din_ready,
+ input [7:0] din_data,
+ input din_cont,
+ input din_qspi,
+ input din_ddr,
+ input din_rd,
+
+ output dout_valid,
+ output [7:0] dout_data,
+
output reg flash_csb,
output reg flash_clk,
@@ -43,91 +258,91 @@ module spimemio (
input flash_io2_di,
input flash_io3_di
);
- parameter ENABLE_PREFETCH = 1;
+ localparam [3:0] mode_spi = 0;
+ reg [3:0] mode;
- reg [23:0] addr_q;
- reg addr_q_vld;
+ reg [7:0] obuffer;
+ reg [7:0] ibuffer;
- reg [31:0] buffer;
- reg [6:0] xfer_cnt;
- reg pulse_csb_8;
- reg xfer_wait;
- reg prefetch;
+ reg [3:0] count;
+ reg xfer_cont;
+ reg xfer_qspi;
+ reg xfer_ddr;
+ reg xfer_rd;
- always @(posedge clk) begin
- ready <= 0;
- if (!resetn) begin
- addr_q_vld <= 0;
- xfer_wait <= 0;
- prefetch <= 0;
+ reg [7:0] next_obuffer;
+ reg [7:0] next_ibuffer;
+ reg [3:0] next_count;
+
+ reg fetch_next;
+ reg last_fetch_next;
+
+ assign din_ready = din_valid && resetn && fetch_next;
+
+ assign dout_valid = fetch_next && !last_fetch_next;
+ assign dout_data = ibuffer;
+
+ always @* begin
+ flash_io0_oe = 0;
+ flash_io1_oe = 0;
+ flash_io2_oe = 0;
+ flash_io3_oe = 0;
+
+ flash_io0_do = 0;
+ flash_io1_do = 0;
+ flash_io2_do = 0;
+ flash_io3_do = 0;
+
+ next_obuffer = obuffer;
+ next_ibuffer = ibuffer;
+ next_count = count;
+ fetch_next = 0;
- xfer_cnt <= 16;
- pulse_csb_8 <= 1;
- buffer <= {8'h FF, 8'h AB, 16'h 0000};
+ case (mode)
+ mode_spi: begin
+ flash_io0_oe = 1;
+ flash_io0_do = obuffer[7];
+ if (flash_clk) begin
+ next_obuffer = {obuffer[6:0], 1'b 0};
+ next_count = count - |count;
+ end else begin
+ next_ibuffer = {ibuffer[6:0], flash_io1_di};
+ end
+
+ fetch_next = (next_count == 0);
+ end
+ endcase
+ end
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ mode <= mode_spi;
+ last_fetch_next <= 1;
flash_csb <= 1;
- flash_clk <= 1;
-
- flash_io0_oe <= 0;
- flash_io1_oe <= 0;
- flash_io2_oe <= 0;
- flash_io3_oe <= 0;
-
- flash_io0_do <= 0;
- flash_io1_do <= 0;
- flash_io2_do <= 0;
- flash_io3_do <= 0;
- end else
- if (xfer_cnt) begin
- if (xfer_cnt == 8 && pulse_csb_8) begin
- pulse_csb_8 <= 0;
- flash_csb <= 1;
- end else
- if (flash_csb) begin
+ flash_clk <= 0;
+ count <= 0;
+ end else begin
+ last_fetch_next <= fetch_next;
+ if (count) begin
+ flash_clk <= !flash_clk && !flash_csb;
+ obuffer <= next_obuffer;
+ ibuffer <= next_ibuffer;
+ count <= next_count;
+ end
+ if (din_valid && din_ready) begin
flash_csb <= 0;
- end else
- if (flash_clk) begin
flash_clk <= 0;
- flash_io0_oe <= 1;
- flash_io0_do <= buffer[31];
- end else begin
- flash_clk <= 1;
- buffer <= {buffer, flash_io1_di};
- xfer_cnt <= xfer_cnt - 1;
- end
- end else
- if (xfer_wait) begin
- ready <= 1;
- rdata <= {buffer[7:0], buffer[15:8], buffer[23:16], buffer[31:24]};
- xfer_wait <= 0;
- end else
- if (valid && !ready) begin
- if (addr_q_vld && addr_q == addr) begin
- addr_q <= addr + 4;
- addr_q_vld <= 1;
- if (!prefetch)
- xfer_cnt <= 32;
- xfer_wait <= 1;
- prefetch <= 0;
- end else begin
- flash_csb <= 1;
- buffer <= {8'h 03, addr};
- addr_q <= addr + 4;
- addr_q_vld <= 1;
- xfer_cnt <= 64;
- xfer_wait <= 1;
- prefetch <= 0;
- end
- end else if (ENABLE_PREFETCH && !prefetch) begin
- prefetch <= 1;
- xfer_cnt <= 32;
- end
- if (ENABLE_PREFETCH && resetn && prefetch && valid && !ready && addr_q != addr) begin
- prefetch <= 0;
- xfer_cnt <= 0;
- xfer_wait <= 0;
- flash_clk <= 1;
+ obuffer <= din_data;
+ ibuffer <= 8'h 00;
+ count <= 8;
+
+ xfer_cont <= din_cont;
+ xfer_qspi <= din_qspi;
+ xfer_ddr <= din_ddr;
+ xfer_rd <= din_rd;
+ end
end
end
endmodule