From 6c7125b380c3d8f5428bae9306e91b5d327f1a61 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 19 Jul 2015 16:09:19 +0200 Subject: [PATCH] Improved icestorm example --- scripts/icestorm/Makefile | 42 ++++++++++++++++ scripts/icestorm/build.sh | 6 --- scripts/icestorm/example.pcf | 9 ++++ scripts/icestorm/example.v | 94 +++++++++++++++++++++++++++++++++++ scripts/icestorm/example_tb.v | 30 +++++++++++ scripts/icestorm/firmware.S | 12 +++++ scripts/icestorm/firmware.c | 28 +++++++++++ scripts/icestorm/firmware.lds | 11 ++++ scripts/icestorm/top.v | 70 -------------------------- 9 files changed, 226 insertions(+), 76 deletions(-) create mode 100644 scripts/icestorm/Makefile delete mode 100644 scripts/icestorm/build.sh create mode 100644 scripts/icestorm/example.pcf create mode 100644 scripts/icestorm/example.v create mode 100644 scripts/icestorm/example_tb.v create mode 100644 scripts/icestorm/firmware.S create mode 100644 scripts/icestorm/firmware.c create mode 100644 scripts/icestorm/firmware.lds delete mode 100644 scripts/icestorm/top.v diff --git a/scripts/icestorm/Makefile b/scripts/icestorm/Makefile new file mode 100644 index 0000000..296c8ed --- /dev/null +++ b/scripts/icestorm/Makefile @@ -0,0 +1,42 @@ + +TOOLCHAIN_PREFIX = riscv64-unknown-elf- +ICECUBE_DIR = /opt/lscc/iCEcube2.2014.08 + +all: example.bin + +firmware.elf: firmware.S firmware.c firmware.lds + $(TOOLCHAIN_PREFIX)gcc -Os -m32 -ffreestanding -nostdlib -o firmware.elf firmware.S firmware.c \ + --std=gnu99 -Wl,-Bstatic,-T,firmware.lds,-Map,firmware.map,--strip-debug -lgcc + +firmware.bin: firmware.elf + $(TOOLCHAIN_PREFIX)objcopy -O binary firmware.elf firmware.bin + +firmware.hex: firmware.bin + python3 ../../firmware/makehex.py firmware.bin 128 > firmware.hex + +synth.blif: example.v firmware.hex + yosys -v3 -l synth.log -p 'synth_ice40 -top top -blif synth.blif; write_verilog -attr2comment synth.v' ../../picorv32.v example.v + +example.txt: synth.blif + arachne-pnr -d 8k -o example.txt -p example.pcf synth.blif + +example.bin: example.txt + icepack example.txt example.bin + +example_tb.exe: example_tb.v example.v firmware.hex + iverilog -o example_tb.exe -s testbench example.v example_tb.v ../../picorv32.v # $(ICECUBE_DIR)/verilog/sb_ice_syn.v + chmod -x example_tb.exe + +sim: example_tb.exe + vvp -N example_tb.exe # +vcd + +prog_sram: + iceprog -S example.bin + +clean: + rm -f firmware.elf firmware.map firmware.bin firmware.hex + rm -f synth.log synth.v synth.blif example.txt example.bin + rm -f example_tb.exe example.vcd + +.PHONY: all sim prog_sram clean + diff --git a/scripts/icestorm/build.sh b/scripts/icestorm/build.sh deleted file mode 100644 index cdefd04..0000000 --- a/scripts/icestorm/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -ex -echo -n > firmware.hex -yosys -l synth.log -p 'synth_ice40 -top top -blif synth.blif' ../../picorv32.v top.v -arachne-pnr -d 8k -o synth.txt synth.blif -icepack synth.txt synth.bin diff --git a/scripts/icestorm/example.pcf b/scripts/icestorm/example.pcf new file mode 100644 index 0000000..5f21bd6 --- /dev/null +++ b/scripts/icestorm/example.pcf @@ -0,0 +1,9 @@ +set_io LED0 B5 +set_io LED1 B4 +set_io LED2 A2 +set_io LED3 A1 +set_io LED4 C5 +set_io LED5 C4 +set_io LED6 B3 +set_io LED7 C3 +set_io clk_pin J3 diff --git a/scripts/icestorm/example.v b/scripts/icestorm/example.v new file mode 100644 index 0000000..5c40661 --- /dev/null +++ b/scripts/icestorm/example.v @@ -0,0 +1,94 @@ +`timescale 1 ns / 1 ps + +module top ( + input clk_pin, + output reg LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 +); + // ------------------------------- + // Clock Buffer + + wire clk; + +`ifdef USE_SB_GB_IO + SB_GB_IO #( + .PIN_TYPE(6'b 0000_01) + ) clk_gb ( + .PACKAGE_PIN(clk_pin), + .GLOBAL_BUFFER_OUTPUT(clk) + ); +`else + assign clk = clk_pin; +`endif + + // ------------------------------- + // Reset Generator + + reg [7:0] resetn_counter = 0; + wire resetn = &resetn_counter; + + always @(posedge clk) begin + if (!resetn) + resetn_counter <= resetn_counter + 1; + end + + // ------------------------------- + // PicoRV32 Core + + wire mem_valid; + wire [31:0] mem_addr; + wire [31:0] mem_wdata; + wire [3:0] mem_wstrb; + + reg mem_ready; + reg [31:0] mem_rdata; + + picorv32 #( + .ENABLE_COUNTERS(0), + .LATCHED_MEM_RDATA(1), + .TWO_STAGE_SHIFT(0), + .TWO_CYCLE_ALU(1), + .CATCH_MISALIGN(0), + .CATCH_ILLINSN(0) + ) cpu ( + .clk (clk ), + .resetn (resetn ), + .mem_valid(mem_valid), + .mem_ready(mem_ready), + .mem_addr (mem_addr ), + .mem_wdata(mem_wdata), + .mem_wstrb(mem_wstrb), + .mem_rdata(mem_rdata) + ); + + // ------------------------------- + // Memory/IO Interface + + // 128 32bit words = 512 bytes memory + localparam MEM_SIZE = 128; + reg [31:0] memory [0:MEM_SIZE-1]; + initial $readmemh("firmware.hex", memory); + + always @(posedge clk) begin + mem_ready <= 0; + if (resetn && mem_valid && !mem_ready) begin + (* parallel_case *) + case (1) + !mem_wstrb && (mem_addr >> 2) < MEM_SIZE: begin + mem_rdata <= memory[mem_addr >> 2]; + mem_ready <= 1; + end + |mem_wstrb && (mem_addr >> 2) < MEM_SIZE: begin + if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0]; + if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8]; + if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16]; + if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24]; + mem_ready <= 1; + end + |mem_wstrb && mem_addr == 32'h1000_0000: begin + {LED7, LED6, LED5, LED4, LED3, LED2, LED1, LED0} <= mem_wdata; + mem_ready <= 1; + end + endcase + end + end +endmodule diff --git a/scripts/icestorm/example_tb.v b/scripts/icestorm/example_tb.v new file mode 100644 index 0000000..7fda120 --- /dev/null +++ b/scripts/icestorm/example_tb.v @@ -0,0 +1,30 @@ +`timescale 1 ns / 1 ps + +module testbench; + reg clk_pin = 1; + always #5 clk_pin = ~clk_pin; + wire LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7; + + top uut ( + .clk_pin(clk_pin), + .LED0(LED0), + .LED1(LED1), + .LED2(LED2), + .LED3(LED3), + .LED4(LED4), + .LED5(LED5), + .LED6(LED6), + .LED7(LED7) + ); + + initial begin + if ($test$plusargs("vcd")) begin + $dumpfile("example.vcd"); + $dumpvars(0, testbench); + end + + $monitor(LED7, LED6, LED5, LED4, LED3, LED2, LED1, LED0); + repeat (10000000) @(posedge clk_pin); + $finish; + end +endmodule diff --git a/scripts/icestorm/firmware.S b/scripts/icestorm/firmware.S new file mode 100644 index 0000000..e6c6e42 --- /dev/null +++ b/scripts/icestorm/firmware.S @@ -0,0 +1,12 @@ +.section .init +.global main + +/* set stack pointer */ +lui sp, %hi(512) +addi sp, sp, %lo(512) + +/* call main */ +jal ra, main + +/* break */ +sbreak diff --git a/scripts/icestorm/firmware.c b/scripts/icestorm/firmware.c new file mode 100644 index 0000000..b400ba0 --- /dev/null +++ b/scripts/icestorm/firmware.c @@ -0,0 +1,28 @@ +#include + +#define SHIFT_COUNTER_BITS 16 + +void output(uint8_t c) +{ + *(volatile char*)0x10000000 = c; +} + +void output_gray(uint8_t c) +{ + unsigned int in_buf = c, out_buf = 0; + for (int i = 0; i < 8; i++) { + unsigned int bit = (in_buf & 1) ^ ((in_buf >> 1) & 1); + in_buf = in_buf >> 1; + out_buf = (out_buf << 1) | bit; + } + output(out_buf); +} + +void main() +{ + for (uint32_t counter = (2+4+32+64) << SHIFT_COUNTER_BITS;; counter++) { + asm volatile ("" : : "r"(counter)); + if ((counter & ~(~0 << SHIFT_COUNTER_BITS)) == 0) + output_gray(counter >> SHIFT_COUNTER_BITS); + } +} diff --git a/scripts/icestorm/firmware.lds b/scripts/icestorm/firmware.lds new file mode 100644 index 0000000..970000a --- /dev/null +++ b/scripts/icestorm/firmware.lds @@ -0,0 +1,11 @@ +SECTIONS { + .memory : { + . = 0x000000; + *(.init); + *(.text); + *(*); + . = ALIGN(4); + end = .; + } +} + diff --git a/scripts/icestorm/top.v b/scripts/icestorm/top.v deleted file mode 100644 index 026321d..0000000 --- a/scripts/icestorm/top.v +++ /dev/null @@ -1,70 +0,0 @@ -`timescale 1 ns / 1 ps - -module top ( - input clk, - input resetn, - output trap, - output reg [7:0] out_byte, - output reg out_byte_en -); - // 1024 32bit words = 4kB memory - parameter MEM_SIZE = 1024; - - wire mem_valid; - wire mem_instr; - wire mem_ready; - wire [31:0] mem_addr; - wire [31:0] mem_wdata; - wire [3:0] mem_wstrb; - reg [31:0] mem_rdata; - - wire mem_la_read; - wire mem_la_write; - wire [31:0] mem_la_addr; - wire [31:0] mem_la_wdata; - wire [3:0] mem_la_wstrb; - - picorv32 #( - .ENABLE_COUNTERS(0), - .TWO_STAGE_SHIFT(0), - .CATCH_MISALIGN(0), - .CATCH_ILLINSN(0) - ) uut ( - .clk (clk ), - .resetn (resetn ), - .trap (trap ), - .mem_valid (mem_valid ), - .mem_instr (mem_instr ), - .mem_ready (mem_ready ), - .mem_addr (mem_addr ), - .mem_wdata (mem_wdata ), - .mem_wstrb (mem_wstrb ), - .mem_rdata (mem_rdata ), - .mem_la_read (mem_la_read ), - .mem_la_write(mem_la_write), - .mem_la_addr (mem_la_addr ), - .mem_la_wdata(mem_la_wdata), - .mem_la_wstrb(mem_la_wstrb) - ); - - reg [31:0] memory [0:MEM_SIZE-1]; - initial $readmemh("firmware.hex", memory); - - assign mem_ready = 1; - - always @(posedge clk) begin - out_byte_en <= 0; - mem_rdata <= memory[mem_la_addr >> 2]; - if (mem_la_write && (mem_la_addr >> 2) < MEM_SIZE) begin - if (mem_la_wstrb[0]) memory[mem_la_addr >> 2][ 7: 0] <= mem_la_wdata[ 7: 0]; - if (mem_la_wstrb[1]) memory[mem_la_addr >> 2][15: 8] <= mem_la_wdata[15: 8]; - if (mem_la_wstrb[2]) memory[mem_la_addr >> 2][23:16] <= mem_la_wdata[23:16]; - if (mem_la_wstrb[3]) memory[mem_la_addr >> 2][31:24] <= mem_la_wdata[31:24]; - end - else - if (mem_la_write && mem_la_addr == 32'h1000_0000) begin - out_byte_en <= 1; - out_byte <= mem_la_wdata; - end - end -endmodule