From 1afe3af452212b424a96d2e0d1b89aab0259e50e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Aug 2018 20:17:21 +0200 Subject: [PATCH] Add PicoSoC IceBreaker demo Signed-off-by: Clifford Wolf --- picosoc/.gitignore | 8 +++ picosoc/Makefile | 43 +++++++++++- picosoc/firmware.c | 2 +- picosoc/icebreaker.pcf | 25 +++++++ picosoc/icebreaker.v | 140 ++++++++++++++++++++++++++++++++++++++++ picosoc/icebreaker_tb.v | 117 +++++++++++++++++++++++++++++++++ picosoc/picosoc.v | 14 ++-- 7 files changed, 341 insertions(+), 8 deletions(-) create mode 100644 picosoc/icebreaker.pcf create mode 100644 picosoc/icebreaker.v create mode 100644 picosoc/icebreaker_tb.v diff --git a/picosoc/.gitignore b/picosoc/.gitignore index 4a2e42e..c8e45ae 100644 --- a/picosoc/.gitignore +++ b/picosoc/.gitignore @@ -11,5 +11,13 @@ /hx8kdemo_syn.v /hx8kdemo_syn_tb.vvp /hx8kdemo_tb.vvp +/icebreaker.asc +/icebreaker.bin +/icebreaker.json +/icebreaker.log +/icebreaker.rpt +/icebreaker_syn.v +/icebreaker_syn_tb.vvp +/icebreaker_tb.vvp /testbench.vcd /cmos.log diff --git a/picosoc/Makefile b/picosoc/Makefile index 0faf167..3615f91 100644 --- a/picosoc/Makefile +++ b/picosoc/Makefile @@ -33,10 +33,44 @@ hx8kprog: hx8kdemo.bin firmware.bin hx8kprog_fw: firmware.bin iceprog -o 1M firmware.bin +# ---- iCE40 IceBreaker Board ---- + +icebsim: icebreaker_tb.vvp firmware.hex + vvp -N $< + +icebsynsim: icebreaker_syn_tb.vvp firmware.hex + vvp -N $< + +icebreaker.json: icebreaker.v spimemio.v simpleuart.v picosoc.v ../picorv32.v + yosys -ql icebreaker.log -p 'synth_ice40 -top icebreaker -json icebreaker.json' $^ + +icebreaker_tb.vvp: icebreaker_tb.v icebreaker.v spimemio.v simpleuart.v picosoc.v ../picorv32.v spiflash.v + iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v` + +icebreaker_syn_tb.vvp: icebreaker_tb.v icebreaker_syn.v spiflash.v + iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v` + +icebreaker_syn.v: icebreaker.json + yosys -p 'read_json icebreaker.json; write_verilog icebreaker_syn.v' + +icebreaker.asc: icebreaker.pcf icebreaker.json + nextpnr-ice40 --freq 13 --up5k --asc icebreaker.asc --pcf icebreaker.pcf --json icebreaker.json + +icebreaker.bin: icebreaker.asc + icetime -d up5k -c 12 -mtr icebreaker.rpt icebreaker.asc + icepack icebreaker.asc icebreaker.bin + +icebprog: icebreaker.bin firmware.bin + iceprog icebreaker.bin + iceprog -o 1M firmware.bin + +icebprog_fw: firmware.bin + iceprog -o 1M firmware.bin + # ---- Example Firmware ---- firmware.elf: sections.lds start.s firmware.c - riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf start.s firmware.c + riscv32-unknown-elf-gcc -march=rv32ic -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf start.s firmware.c firmware.hex: firmware.elf riscv32-unknown-elf-objcopy -O verilog firmware.elf firmware.hex @@ -64,6 +98,9 @@ clean: rm -f firmware.elf firmware.hex firmware.bin cmos.log rm -f hx8kdemo.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp + rm -f icebreaker.json icebreaker.log icebreaker.asc icebreaker.rpt icebreaker.bin + rm -f icebreaker_syn.v icebreaker_syn_tb.vvp icebreaker_tb.vvp -.PHONY: spiflash_tb hx8kprog hx8kprog_fw hx8ksim hx8ksynsim clean - +.PHONY: spiflash_tb clean +.PHONY: hx8kprog hx8kprog_fw hx8ksim hx8ksynsim +.PHONY: icebprog icebprog_fw icebsim icebsynsim diff --git a/picosoc/firmware.c b/picosoc/firmware.c index f1ffbd3..2db2588 100644 --- a/picosoc/firmware.c +++ b/picosoc/firmware.c @@ -32,7 +32,7 @@ void set_flash_qspi_flag() { uint8_t buffer[8]; -#if 0 +#if 1 uint32_t addr_cr1v = 0x800002; // Read Any Register (RDAR 65h) diff --git a/picosoc/icebreaker.pcf b/picosoc/icebreaker.pcf new file mode 100644 index 0000000..86cf78e --- /dev/null +++ b/picosoc/icebreaker.pcf @@ -0,0 +1,25 @@ +# 12 MHz clock +set_io clk 35 + +# RS232 +set_io ser_rx 6 +set_io ser_tx 9 + +# SPI Flash +set_io flash_clk 15 +set_io flash_csb 16 +set_io flash_io0 14 +set_io flash_io1 17 +set_io flash_io2 12 +set_io flash_io3 13 + +# LEDs (PMOD 2) +set_io led1 27 +set_io led2 25 +set_io led3 21 +set_io led4 23 +set_io led5 26 + +# Onboard LEDs +set_io ledr_n 11 +set_io ledg_n 37 diff --git a/picosoc/icebreaker.v b/picosoc/icebreaker.v new file mode 100644 index 0000000..ef9b9ac --- /dev/null +++ b/picosoc/icebreaker.v @@ -0,0 +1,140 @@ +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf + * + * 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. + * + */ + +module icebreaker ( + input clk, + + output ser_tx, + input ser_rx, + + output led1, + output led2, + output led3, + output led4, + output led5, + + output ledr_n, + output ledg_n, + + output flash_csb, + output flash_clk, + inout flash_io0, + inout flash_io1, + inout flash_io2, + inout flash_io3 +); + reg [5:0] reset_cnt = 0; + wire resetn = &reset_cnt; + + always @(posedge clk) begin + reset_cnt <= reset_cnt + !resetn; + end + + wire [7:0] leds; + + assign led1 = leds[1]; + assign led2 = leds[2]; + assign led3 = leds[3]; + assign led4 = leds[4]; + assign led5 = leds[5]; + + assign ledr_n = !leds[6]; + assign ledg_n = !leds[7]; + + wire flash_io0_oe, flash_io0_do, flash_io0_di; + wire flash_io1_oe, flash_io1_do, flash_io1_di; + wire flash_io2_oe, flash_io2_do, flash_io2_di; + wire flash_io3_oe, flash_io3_do, flash_io3_di; + + SB_IO #( + .PIN_TYPE(6'b 1010_01), + .PULLUP(1'b 0) + ) flash_io_buf [3:0] ( + .PACKAGE_PIN({flash_io3, flash_io2, flash_io1, flash_io0}), + .OUTPUT_ENABLE({flash_io3_oe, flash_io2_oe, flash_io1_oe, flash_io0_oe}), + .D_OUT_0({flash_io3_do, flash_io2_do, flash_io1_do, flash_io0_do}), + .D_IN_0({flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}) + ); + + wire iomem_valid; + reg iomem_ready; + wire [3:0] iomem_wstrb; + wire [31:0] iomem_addr; + wire [31:0] iomem_wdata; + reg [31:0] iomem_rdata; + + reg [31:0] gpio; + assign leds = gpio; + + always @(posedge clk) begin + if (!resetn) begin + gpio <= 0; + end else begin + iomem_ready <= 0; + if (iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 03) begin + iomem_ready <= 1; + iomem_rdata <= gpio; + if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0]; + if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8]; + if (iomem_wstrb[2]) gpio[23:16] <= iomem_wdata[23:16]; + if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24]; + end + end + end + + picosoc #( + .BARREL_SHIFTER(0), + .ENABLE_MULDIV(0) + ) soc ( + .clk (clk ), + .resetn (resetn ), + + .ser_tx (ser_tx ), + .ser_rx (ser_rx ), + + .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), + + .irq_5 (1'b0 ), + .irq_6 (1'b0 ), + .irq_7 (1'b0 ), + + .iomem_valid (iomem_valid ), + .iomem_ready (iomem_ready ), + .iomem_wstrb (iomem_wstrb ), + .iomem_addr (iomem_addr ), + .iomem_wdata (iomem_wdata ), + .iomem_rdata (iomem_rdata ) + ); +endmodule diff --git a/picosoc/icebreaker_tb.v b/picosoc/icebreaker_tb.v new file mode 100644 index 0000000..2126ca2 --- /dev/null +++ b/picosoc/icebreaker_tb.v @@ -0,0 +1,117 @@ +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf + * + * 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); + + localparam ser_half_period = 53; + event ser_sample; + + initial begin + $dumpfile("testbench.vcd"); + $dumpvars(0, testbench); + + repeat (6) begin + repeat (50000) @(posedge clk); + $display("+50000 cycles"); + end + $finish; + end + + integer cycle_cnt = 0; + + always @(posedge clk) begin + cycle_cnt <= cycle_cnt + 1; + end + + wire led1, led2, led3, led4, led5; + wire ledr_n, ledg_n; + + wire [6:0] leds = {!ledg_n, !ledr_n, led5, led4, led3, led2, led1}; + + wire ser_rx; + wire ser_tx; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + always @(leds) begin + #1 $display("%b", leds); + end + + icebreaker uut ( + .clk (clk ), + .led1 (led1 ), + .led2 (led2 ), + .led3 (led3 ), + .led4 (led4 ), + .led5 (led5 ), + .ledr_n (ledr_n ), + .ledg_n (ledg_n ), + .ser_rx (ser_rx ), + .ser_tx (ser_tx ), + .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) + ); + + reg [7:0] buffer; + + always begin + @(negedge ser_tx); + + repeat (ser_half_period) @(posedge clk); + -> ser_sample; // start bit + + repeat (8) begin + repeat (ser_half_period) @(posedge clk); + repeat (ser_half_period) @(posedge clk); + buffer = {ser_tx, buffer[7:1]}; + -> ser_sample; // data bit + end + + repeat (ser_half_period) @(posedge clk); + repeat (ser_half_period) @(posedge clk); + -> ser_sample; // stop bit + + if (buffer < 32 || buffer >= 127) + $display("Serial data: %d", buffer); + else + $display("Serial data: '%c'", buffer); + end +endmodule diff --git a/picosoc/picosoc.v b/picosoc/picosoc.v index b38d6f2..353f2ef 100644 --- a/picosoc/picosoc.v +++ b/picosoc/picosoc.v @@ -61,7 +61,12 @@ module picosoc ( input flash_io2_di, input flash_io3_di ); + parameter [0:0] BARREL_SHIFTER = 1; + parameter [0:0] ENABLE_MULDIV = 1; + parameter [0:0] ENABLE_COMPRESSED = 1; + parameter [0:0] ENABLE_COUNTERS = 1; parameter [0:0] ENABLE_IRQ_QREGS = 0; + parameter integer MEM_WORDS = 256; parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash @@ -120,10 +125,11 @@ module picosoc ( .STACKADDR(STACKADDR), .PROGADDR_RESET(PROGADDR_RESET), .PROGADDR_IRQ(PROGADDR_IRQ), - .BARREL_SHIFTER(1), - .COMPRESSED_ISA(1), - .ENABLE_MUL(1), - .ENABLE_DIV(1), + .BARREL_SHIFTER(BARREL_SHIFTER), + .COMPRESSED_ISA(ENABLE_COMPRESSED), + .ENABLE_COUNTERS(ENABLE_COUNTERS), + .ENABLE_MUL(ENABLE_MULDIV), + .ENABLE_DIV(ENABLE_MULDIV), .ENABLE_IRQ(1), .ENABLE_IRQ_QREGS(ENABLE_IRQ_QREGS) ) cpu (