From 31d3d054ca374ae82f695f805749db62af91b07f Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Sep 2018 14:19:04 +0100 Subject: [PATCH 1/4] Adding camera interface to control SoC Signed-off-by: David Shah --- demo/Makefile | 35 +++++++++++++++++++++++++++++------ demo/camera/cameraif.v | 23 ++++++++++++++++++++--- demo/ctrlsoc.pcf | 10 ++++++++++ demo/ctrlsoc.v | 42 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 98 insertions(+), 12 deletions(-) diff --git a/demo/Makefile b/demo/Makefile index 7e55d75..7a6c199 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -2,21 +2,44 @@ CTRLSOC_DEV = MLACCEL_DEV = SEED = 1234 +CAMERA_RTL = \ + camera/phy/dphy_iserdes.v \ + camera/phy/byte_aligner.v \ + camera/phy/word_combiner.v \ + camera/csi/header_ecc.v \ + camera/csi/rx_packet_handler.v \ + camera/link/csi_rx_ice40.v \ + camera/misc/downsample.v \ + camera/cameraif.v + +SPI_RTL = \ + spiflash.v + +SOC_RTL = \ + ctrlsoc.v \ + picorv32.v + +ML_RTL = \ + ../rtl/top.v \ + ../rtl/sequencer.v \ + ../rtl/compute.v \ + ../rtl/memory.v + ##################################################################### testbench.vcd: testbench flashinit.hex ctrlsoc_fw.hex vvp -N testbench -testbench: testbench.v spiflash.v ctrlsoc.v picorv32.v ../rtl/top.v ../rtl/sequencer.v ../rtl/compute.v ../rtl/memory.v - iverilog -s testbench -o $@ testbench.v spiflash.v ctrlsoc.v picorv32.v ../rtl/top.v ../rtl/sequencer.v ../rtl/compute.v ../rtl/memory.v $(shell yosys-config --datdir/ice40/cells_sim.v) +testbench: testbench.v $(SPI_RTL) $(SOC_RTL) $(ML_RTL) $(CAMERA_RTL) + iverilog -s testbench -o $@ $^ $(shell yosys-config --datdir/ice40/cells_sim.v) flashinit.hex: flashinit.py python3 flashinit.py ##################################################################### -ctrlsoc.json: ctrlsoc.v picorv32.v flashinit.hex - yosys -ql ctrlsoc.log -p 'synth_ice40 -top ctrlsoc -json ctrlsoc.json' ctrlsoc.v picorv32.v +ctrlsoc.json: $(SOC_RTL) $(CAMERA_RTL) flashinit.hex + yosys -ql ctrlsoc.log -p 'synth_ice40 -top ctrlsoc -json ctrlsoc.json' $(filter %.v, $^) ctrlsoc.asc: ctrlsoc.pcf ctrlsoc.json nextpnr-ice40 --freq 13 --up5k --asc ctrlsoc.asc --pcf ctrlsoc.pcf --json ctrlsoc.json @@ -57,8 +80,8 @@ clean_ctrlsoc: ##################################################################### mlaccel.blif: mlaccel.json -mlaccel.json: ../rtl/top.v ../rtl/sequencer.v ../rtl/compute.v ../rtl/memory.v - yosys -ql mlaccel.log -p 'synth_ice40 -top mlaccel_top -json mlaccel.json -blif mlaccel.blif' ../rtl/top.v ../rtl/sequencer.v ../rtl/compute.v ../rtl/memory.v +mlaccel.json: $(ML_RTL) + yosys -ql mlaccel.log -p 'synth_ice40 -top mlaccel_top -json mlaccel.json -blif mlaccel.blif' $(ML_RTL) mlaccel.asc: mlaccel.pcf mlaccel.json nextpnr-ice40 --seed $(SEED) --freq 25 --up5k --asc mlaccel.asc --pcf mlaccel.pcf --json mlaccel.json diff --git a/demo/camera/cameraif.v b/demo/camera/cameraif.v index 8b044bf..45facec 100644 --- a/demo/camera/cameraif.v +++ b/demo/camera/cameraif.v @@ -115,9 +115,26 @@ module cameraif( reg [1:0] i2c_gpio; reg [1:0] i2c_read; - assign i2c_din = {cam_scl, cam_sda}; - assign cam_sda = i2c_gpio[0] ? 1'bz : 1'b0; - assign cam_scl = i2c_gpio[1] ? 1'bz : 1'b0; + SB_IO #( + .PIN_TYPE(6'b 1010_01), + .PULLUP(1'b 1) + ) scl_buf ( + .PACKAGE_PIN(cam_sda), + .OUTPUT_ENABLE(i2c_gpio[0]), + .D_OUT_0(1'b0), + .D_IN_0(i2c_din[0]) + ); + + SB_IO #( + .PIN_TYPE(6'b 1010_01), + .PULLUP(1'b 1) + ) sda_buf ( + .PACKAGE_PIN(cam_scl), + .OUTPUT_ENABLE(i2c_gpio[1]), + .D_OUT_0(1'b0), + .D_IN_0(i2c_din[1]) + ); + assign cam_enable = 1'b1; always @(posedge sys_clk) begin diff --git a/demo/ctrlsoc.pcf b/demo/ctrlsoc.pcf index b8632fc..72a1ff2 100644 --- a/demo/ctrlsoc.pcf +++ b/demo/ctrlsoc.pcf @@ -27,3 +27,13 @@ set_io led5 26 # ML QPI (on PMOD2) set_io ml_csb 20 set_io ml_clk 18 + +# Camera pins +set_io cam_enable 3 #P1A7 +set_io cam_sda 34 #P1B3 +set_io cam_scl 28 #P1B10 + +set_io dphy_clk 32 #P1B9 +set_io dphy_data[0] 42 #P1B7 +set_io dphy_data[1] 43 #P1B1 +set_io dphy_lp 48 #P1A8 diff --git a/demo/ctrlsoc.v b/demo/ctrlsoc.v index e049c8f..346838c 100644 --- a/demo/ctrlsoc.v +++ b/demo/ctrlsoc.v @@ -46,7 +46,15 @@ module ctrlsoc ( // mlaccel ctrl pins output ml_csb, - output ml_clk + output ml_clk, + + // Camera interface (PMOD 1A/1B) + input dphy_clk, + input [1:0] dphy_data, + input dphy_lp, + + inout cam_sda, cam_scl, + output cam_enable, ); reg resetn = 0; reg [5:0] reset_cnt = 0; @@ -75,8 +83,10 @@ module ctrlsoc ( assign ledg_n = flash_csb || ((|last_flash_clk) == (&last_flash_clk)); reg led5_r, led4_r, led3_r, led2_r, led1_r; + wire camera_heartbeat; - assign led1 = led1_r; + //assign led1 = led1_r; + assign led1 = camera_heartbeat; assign led2 = led2_r; assign led3 = led3_r; assign led4 = led4_r; @@ -101,6 +111,9 @@ module ctrlsoc ( wire rxtx_ready; wire [31:0] rxtx_rdata; + wire camera_ready; + wire [31:0] camera_rdata; + picorv32 #( .ENABLE_COUNTERS(0), .CATCH_MISALIGN(1), @@ -113,7 +126,7 @@ module ctrlsoc ( .trap (trap ), .mem_valid (mem_valid), .mem_instr (mem_instr), - .mem_ready (mem_ready || flash_ready || rxtx_ready), + .mem_ready (mem_ready || flash_ready || rxtx_ready || camera_ready), .mem_addr (mem_addr ), .mem_wdata (mem_wdata), .mem_wstrb (mem_wstrb), @@ -123,6 +136,7 @@ module ctrlsoc ( spram1_rselect ? spram1_rdata : flash_ready ? flash_rdata : rxtx_ready ? rxtx_rdata : + camera_ready ? camera_rdata : mem_rdata ) ); @@ -130,6 +144,7 @@ module ctrlsoc ( wire addr_spram0 = mem_addr < 64*1024; wire addr_spram1 = (mem_addr < 128*1024) && !(mem_addr < 64*1024); wire addr_flash = (mem_addr < 2*16*1024*1024) && !(mem_addr < 128*1024); + wire addr_camera = mem_addr[31:24] == 8'h03; ctrlsoc_rxtx rxtx ( .clk (clk ), @@ -284,6 +299,27 @@ module ctrlsoc ( .flash_io2_oe (flash_io2_oe), .flash_io3_oe (flash_io3_oe) ); + + cameraif cam ( + .dphy_clk(dphy_clk), + .dphy_data(dphy_data), + .dphy_lp(dphy_lp), + + .cam_sda(cam_sda), + .cam_scl(cam_scl), + .cam_enable(cam_enable), + + .cam_heartbeat(camera_heartbeat), + + .sys_clk(clk), + .resetn(resetn), + .addr(mem_addr[15:0]), + .wdata(mem_wdata), + .wstrb(mem_wstrb), + .valid(addr_camera && mem_valid && !camera_ready), + .rdata(camera_rdata), + .ready(camera_ready) + ); endmodule module ctrlsoc_spram ( From 7ac93f9c26cc122e54a5da478c5477ab2e68515d Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Sep 2018 15:50:15 +0100 Subject: [PATCH 2/4] Adding firmware for camera Signed-off-by: David Shah --- demo/Makefile | 4 +- demo/camera/camera.c | 168 ++++++++++++++++++++++++++++++++ demo/camera/camera.h | 33 +++++++ demo/camera/cameraif.v | 11 ++- demo/camera/link/csi_rx_ice40.v | 12 +-- demo/camera/phy/byte_aligner.v | 4 +- demo/ctrlsoc.v | 3 + demo/firmware.c | 5 + demo/testbench.v | 7 +- 9 files changed, 233 insertions(+), 14 deletions(-) create mode 100644 demo/camera/camera.c create mode 100644 demo/camera/camera.h diff --git a/demo/Makefile b/demo/Makefile index 7a6c199..6a456b4 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -48,8 +48,8 @@ ctrlsoc.bin: ctrlsoc.asc icetime -d up5k -c 12 -mtr ctrlsoc.rpt ctrlsoc.asc icepack ctrlsoc.asc ctrlsoc.bin -ctrlsoc_fw.elf: sections.lds start.S firmware.c demodat.inc - riscv32-unknown-elf-gcc -O1 -Wall -Wextra -march=rv32i -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o ctrlsoc_fw.elf start.S firmware.c +ctrlsoc_fw.elf: sections.lds start.S firmware.c demodat.inc camera/camera.c + riscv32-unknown-elf-gcc -O1 -Wall -Wextra -march=rv32i -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o ctrlsoc_fw.elf start.S firmware.c camera/camera.c ctrlsoc_fw.hex: ctrlsoc_fw.elf riscv32-unknown-elf-objcopy -O verilog ctrlsoc_fw.elf ctrlsoc_fw.hex diff --git a/demo/camera/camera.c b/demo/camera/camera.c new file mode 100644 index 0000000..77268b8 --- /dev/null +++ b/demo/camera/camera.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2018 David Shah + * + * 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. + * + */ + +#include "camera.h" +#define CAMERA_BASE 0x03000000 + +#define reg_camera_i2c (*(volatile uint32_t*)CAMERA_BASE) +#define reg_camera_fb ((volatile uint32_t*)(CAMERA_BASE + 0x8000)) + +static void i2c_delay() { + for (volatile int i = 0; i < 10; i++) + ; +} + +static void set_i2c_io(uint8_t sda, uint8_t scl) { + reg_camera_i2c = ((scl & 0x1) << 1) | (sda & 0x1); + i2c_delay(); +} + +static void i2c_start() { + set_i2c_io(1, 1); + set_i2c_io(0, 1); + set_i2c_io(0, 0); +} + +static void i2c_send(uint8_t data) { + for (int i = 7; i >= 0; i--) { + uint8_t bit = (data >> i) & 0x1; + set_i2c_io(bit, 0); + set_i2c_io(bit, 1); + set_i2c_io(bit, 0); + } + set_i2c_io(1, 0); + set_i2c_io(1, 1); + set_i2c_io(1, 0); +} + +static void i2c_stop() { + set_i2c_io(0, 0); + set_i2c_io(0, 1); + set_i2c_io(1, 1); +} + +void camera_i2c_write(uint16_t address, uint8_t data) { + i2c_start(); + i2c_send(0x10 << 1); + i2c_send((address >> 8) & 0xFF); + i2c_send(address & 0xFF); + i2c_send(data); + i2c_stop(); +} + +const int framelength = 666; +const int linelength = 3448; + +void camera_init() { + // Based on "Preview Setting" from a Linux driver + camera_i2c_write(0x0100, 0x00); //standby mode + camera_i2c_write(0x30EB, 0x05); //mfg specific access begin + camera_i2c_write(0x30EB, 0x0C); // + camera_i2c_write(0x300A, 0xFF); // + camera_i2c_write(0x300B, 0xFF); // + camera_i2c_write(0x30EB, 0x05); // + camera_i2c_write(0x30EB, 0x09); //mfg specific access end + camera_i2c_write(0x0114, 0x01); //CSI_LANE_MODE: 2-lane + camera_i2c_write(0x0128, 0x00); //DPHY_CTRL: auto mode (?) + camera_i2c_write(0x012A, 0x18); //EXCK_FREQ[15:8] = 24MHz + camera_i2c_write(0x012B, 0x00); //EXCK_FREQ[7:0] + camera_i2c_write(0x0160, ((framelength >> 8) & 0xFF)); //framelength + camera_i2c_write(0x0161, (framelength & 0xFF)); + camera_i2c_write(0x0162, ((linelength >> 8) & 0xFF)); + camera_i2c_write(0x0163, (linelength & 0xFF)); + camera_i2c_write(0x0164, 0x00); //X_ADD_STA_A[11:8] + camera_i2c_write(0x0165, 0x00); //X_ADD_STA_A[7:0] + camera_i2c_write(0x0166, 0x0A); //X_ADD_END_A[11:8] + camera_i2c_write(0x0167, 0x00); //X_ADD_END_A[7:0] + camera_i2c_write(0x0168, 0x00); //Y_ADD_STA_A[11:8] + camera_i2c_write(0x0169, 0x00); //Y_ADD_STA_A[7:0] + camera_i2c_write(0x016A, 0x07); //Y_ADD_END_A[11:8] + camera_i2c_write(0x016B, 0x80); //Y_ADD_END_A[7:0] + camera_i2c_write(0x016C, 0x02); //x_output_size[11:8] = 640 + camera_i2c_write(0x016D, 0x80); //x_output_size[7:0] + camera_i2c_write(0x016E, 0x01); //y_output_size[11:8] = 480 + camera_i2c_write(0x016F, 0xE0); //y_output_size[7:0] + camera_i2c_write(0x0170, 0x01); //X_ODD_INC_A + camera_i2c_write(0x0171, 0x01); //Y_ODD_INC_A + camera_i2c_write(0x0174, 0x02); //BINNING_MODE_H_A = x4-binning + camera_i2c_write(0x0175, 0x02); //BINNING_MODE_V_A = x4-binning + camera_i2c_write(0x018C, 0x08); //CSI_DATA_FORMAT_A[15:8] + camera_i2c_write(0x018D, 0x08); //CSI_DATA_FORMAT_A[7:0] + camera_i2c_write(0x0301, 0x08); //VTPXCK_DIV + camera_i2c_write(0x0303, 0x01); //VTSYCK_DIV + camera_i2c_write(0x0304, 0x03); //PREPLLCK_VT_DIV + camera_i2c_write(0x0305, 0x03); //PREPLLCK_OP_DIV + camera_i2c_write(0x0306, 0x00); //PLL_VT_MPY[10:8] + camera_i2c_write(0x0307, 0x14); //PLL_VT_MPY[7:0] + camera_i2c_write(0x0309, 0x08); //OPPXCK_DIV + camera_i2c_write(0x030B, 0x02); //OPSYCK_DIV + camera_i2c_write(0x030C, 0x00); //PLL_OP_MPY[10:8] + camera_i2c_write(0x030D, 0x0A); //PLL_OP_MPY[7:0] + camera_i2c_write(0x455E, 0x00); //?? + camera_i2c_write(0x471E, 0x4B); //?? + camera_i2c_write(0x4767, 0x0F); //?? + camera_i2c_write(0x4750, 0x14); //?? + camera_i2c_write(0x4540, 0x00); //?? + camera_i2c_write(0x47B4, 0x14); //?? + camera_i2c_write(0x4713, 0x30); //?? + camera_i2c_write(0x478B, 0x10); //?? + camera_i2c_write(0x478F, 0x10); //?? + camera_i2c_write(0x4793, 0x10); //?? + camera_i2c_write(0x4797, 0x0E); //?? + camera_i2c_write(0x479B, 0x0E); //?? + + //camera_i2c_write(0x0157, 232); // ANA_GAIN_GLOBAL_A + //camera_i2c_write(0x0257, 232); // ANA_GAIN_GLOBAL_B + + + //camera_i2c_write(0x0600, 0x00); // Test pattern: disable + //camera_i2c_write(0x0601, 0x00); // Test pattern: disable + +#if 0 + camera_i2c_write(0x0600, 0x00); // Test pattern: solid colour + camera_i2c_write(0x0601, 0x01); // + + camera_i2c_write(0x0602, 0x02); // Test pattern: red + camera_i2c_write(0x0603, 0xAA); // + + camera_i2c_write(0x0604, 0x02); // Test pattern: greenR + camera_i2c_write(0x0605, 0xAA); // + + camera_i2c_write(0x0606, 0x02); // Test pattern: blue + camera_i2c_write(0x0607, 0xAA); // + + camera_i2c_write(0x0608, 0x02); // Test pattern: greenB + camera_i2c_write(0x0609, 0xAA); // + + + camera_i2c_write(0x0624, 0x0A); // Test pattern width + camera_i2c_write(0x0625, 0x00); // + + camera_i2c_write(0x0626, 0x07); // Test pattern height + camera_i2c_write(0x0627, 0x80); // + + +#endif + + camera_i2c_write(0x0100, 0x01); +} + +void acquire_image(uint8_t *buffer) { + for (int y = 0; y < 30; y++) + for (int x = 0; x < 40; x++) + *(buffer++) = reg_camera_fb[((y << 6) | x) << 2]; +} diff --git a/demo/camera/camera.h b/demo/camera/camera.h new file mode 100644 index 0000000..1709491 --- /dev/null +++ b/demo/camera/camera.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 David Shah + * + * 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. + * + */ + + +#ifndef CAMERA_H +#define CAMERA_H + +#include + +// Write to camera register +void camera_i2c_write(uint16_t address, uint8_t data); + +// Init camera with default config +void camera_init(); + +// Copy 40x30 to buffer +void acquire_image(uint8_t *buffer); + +#endif diff --git a/demo/camera/cameraif.v b/demo/camera/cameraif.v index 45facec..a41478a 100644 --- a/demo/camera/cameraif.v +++ b/demo/camera/cameraif.v @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 David Shah * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -114,6 +114,7 @@ module cameraif( wire [1:0] i2c_din; reg [1:0] i2c_gpio; reg [1:0] i2c_read; + reg i2c_read_last; SB_IO #( .PIN_TYPE(6'b 1010_01), @@ -141,10 +142,14 @@ module cameraif( if (reset) begin i2c_gpio <= 2'b11; i2c_read <= 2'b11; + i2c_read_last <= 1'b0; end else if (addr == 16'h0000 && valid) begin if (wstrb[0]) i2c_gpio <= wdata[1:0]; i2c_read <= i2c_din; + i2c_read_last <= 1'b1; + end else begin + i2c_read_last <= 1'b0; end end @@ -156,8 +161,8 @@ module cameraif( end end - assign rdata = (addr == 16'h0000) ? {30'b0, i2c_read} : - {24'b0, ds_read_data}; + assign rdata = i2c_read_last ? {30'b0, i2c_read} : + {24'b0, ds_read_data}; // Debugging reg [22:0] hb_ctr; diff --git a/demo/camera/link/csi_rx_ice40.v b/demo/camera/link/csi_rx_ice40.v index a3408db..fed8c32 100644 --- a/demo/camera/link/csi_rx_ice40.v +++ b/demo/camera/link/csi_rx_ice40.v @@ -67,12 +67,12 @@ module csi_rx_ice40 #( .PACKAGE_PIN(dphy_clk_lane), .D_IN_0(dphy_clk_pre) ); - + SB_GB clk_gbuf ( .USER_SIGNAL_TO_GLOBAL_BUFFER(dphy_clk_pre), .GLOBAL_BUFFER_OUTPUT(dphy_clk) ); - + wire dphy_lp; SB_IO #( .PIN_TYPE(6'b000001), @@ -89,7 +89,7 @@ module csi_rx_ice40 #( else div <= div + 1'b1; assign word_clk = div[1]; - + wire sreset; reg [7:0] sreset_ctr; always @(posedge word_clk or posedge areset) @@ -97,9 +97,9 @@ module csi_rx_ice40 #( sreset_ctr <= 0; else if (!(&sreset_ctr)) sreset_ctr <= sreset_ctr + 1'b1; - + assign sreset = !(&sreset_ctr); - + wire byte_packet_done, wait_for_sync; wire [LANES*8-1:0] aligned_bytes; wire [LANES-1:0] aligned_bytes_valid; @@ -107,7 +107,7 @@ module csi_rx_ice40 #( generate genvar ii; - for (ii = 0; ii < LANES; ii++) begin + for (ii = 0; ii < LANES; ii=ii+1) begin wire [1:0] din_raw; SB_IO #( .PIN_TYPE(6'b000000), diff --git a/demo/camera/phy/byte_aligner.v b/demo/camera/phy/byte_aligner.v index 50b35c6..03259ec 100644 --- a/demo/camera/phy/byte_aligner.v +++ b/demo/camera/phy/byte_aligner.v @@ -51,7 +51,7 @@ module dphy_rx_byte_align( reg [7:0] curr_byte; reg [7:0] last_byte; - reg [7:0] shifted_byte; + wire [7:0] shifted_byte; reg found_sync; reg [2:0] sync_offs; // found offset of sync pattern @@ -94,7 +94,7 @@ module dphy_rx_byte_align( found_sync = 1'b0; sync_offs = 0; for (i = 0; i < 8; i = i + 1) begin - if ((concat_word[(1+i) +: 8] == sync_word) && (last_byte[i:0] == 0)) begin + if ((concat_word[(1+i) +: 8] == sync_word) /*&& (last_byte[i:0] == 0)*/) begin was_found = 1'b1; offset = i; end diff --git a/demo/ctrlsoc.v b/demo/ctrlsoc.v index 346838c..039be83 100644 --- a/demo/ctrlsoc.v +++ b/demo/ctrlsoc.v @@ -213,6 +213,9 @@ module ctrlsoc ( addr_flash: begin buserror <= |mem_wstrb; end + addr_camera: begin + /* nothing to do here */ + end mem_addr == 32'h 02000000: begin mem_ready <= 1; if (mem_wstrb[0]) begin diff --git a/demo/firmware.c b/demo/firmware.c index 3efe75b..eb568df 100644 --- a/demo/firmware.c +++ b/demo/firmware.c @@ -21,6 +21,8 @@ #include #include +#include "camera/camera.h" + // a pointer to this is a null pointer, but the compiler does not // know that because "sram" is a linker symbol from sections.lds. extern uint32_t sram; @@ -413,8 +415,11 @@ void main() { print("\n\n\n\n\n"); print("Booting..\n"); + ml_test(); print("\n"); + camera_init(); + print ("Initialised camera\n"); reg_leds = 127; while (!RUN_LOOP) { diff --git a/demo/testbench.v b/demo/testbench.v index d11ecb6..7afb254 100644 --- a/demo/testbench.v +++ b/demo/testbench.v @@ -76,6 +76,8 @@ module testbench; wire ml_csb; wire ml_clk; + wire cam_scl = 1'b0, cam_sda = 1'b0; + ctrlsoc ctrl ( .clk (ctrl_clk ), @@ -99,7 +101,10 @@ module testbench; .led5 (led5 ), .ml_csb (ml_csb ), - .ml_clk (ml_clk ) + .ml_clk (ml_clk ), + + .cam_scl (cam_scl), + .cam_sda (cam_sda) ); spiflash flash ( From a0c0e2a4858e18c86e423739502d85d5145cb1e4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Sep 2018 16:01:57 +0100 Subject: [PATCH 3/4] Fix camera I2C interface Signed-off-by: David Shah --- demo/camera/cameraif.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/camera/cameraif.v b/demo/camera/cameraif.v index a41478a..65a7134 100644 --- a/demo/camera/cameraif.v +++ b/demo/camera/cameraif.v @@ -121,7 +121,7 @@ module cameraif( .PULLUP(1'b 1) ) scl_buf ( .PACKAGE_PIN(cam_sda), - .OUTPUT_ENABLE(i2c_gpio[0]), + .OUTPUT_ENABLE(!i2c_gpio[0]), .D_OUT_0(1'b0), .D_IN_0(i2c_din[0]) ); @@ -131,7 +131,7 @@ module cameraif( .PULLUP(1'b 1) ) sda_buf ( .PACKAGE_PIN(cam_scl), - .OUTPUT_ENABLE(i2c_gpio[1]), + .OUTPUT_ENABLE(!i2c_gpio[1]), .D_OUT_0(1'b0), .D_IN_0(i2c_din[1]) ); From 81a4569c0bc2890c65ffd88346972bbf75f1210b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Sep 2018 16:17:44 +0100 Subject: [PATCH 4/4] picorv32 image acquisition Signed-off-by: David Shah --- demo/camera/camera.c | 2 +- demo/camera/phy/byte_aligner.v | 2 +- demo/firmware.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/demo/camera/camera.c b/demo/camera/camera.c index 77268b8..3ecb5c7 100644 --- a/demo/camera/camera.c +++ b/demo/camera/camera.c @@ -19,7 +19,7 @@ #define CAMERA_BASE 0x03000000 #define reg_camera_i2c (*(volatile uint32_t*)CAMERA_BASE) -#define reg_camera_fb ((volatile uint32_t*)(CAMERA_BASE + 0x8000)) +#define reg_camera_fb ((volatile uint8_t*)(CAMERA_BASE + 0x8000)) static void i2c_delay() { for (volatile int i = 0; i < 10; i++) diff --git a/demo/camera/phy/byte_aligner.v b/demo/camera/phy/byte_aligner.v index 03259ec..126e421 100644 --- a/demo/camera/phy/byte_aligner.v +++ b/demo/camera/phy/byte_aligner.v @@ -94,7 +94,7 @@ module dphy_rx_byte_align( found_sync = 1'b0; sync_offs = 0; for (i = 0; i < 8; i = i + 1) begin - if ((concat_word[(1+i) +: 8] == sync_word) /*&& (last_byte[i:0] == 0)*/) begin + if ((concat_word[(1+i) +: 8] == sync_word) && (last_byte[i:0] == 0)) begin was_found = 1'b1; offset = i; end diff --git a/demo/firmware.c b/demo/firmware.c index eb568df..864f6c0 100644 --- a/demo/firmware.c +++ b/demo/firmware.c @@ -30,6 +30,8 @@ extern uint32_t sram; #define RUN_LOOP 0 #define SER_TIMEOUT 1500000 #define ML_TIMEOUT 100 +#define NUM_IMAGES 10 +#define IMAGE_NOPS 10000 #define reg_leds (*(volatile uint32_t*)0x02000000) #define reg_uart (*(volatile uint32_t*)0x02000004) @@ -411,11 +413,37 @@ void ml_test() // -------------------------------------------------------- +void print_image() { + uint8_t buf[30*40]; + print("Acquiring image\n"); + acquire_image(buf); + print("----------------------------------------\n"); + + int addr = 0; + for (int y = 0; y < 30; y++) { + for (int x = 0; x < 40; x++) { + print_hex(buf[addr++], 2); + print(" "); + } + print("\n"); + } +} + +// -------------------------------------------------------- + void main() { print("\n\n\n\n\n"); print("Booting..\n"); + camera_init(); + print ("Initialised camera\n"); + for (int ii=0; ii< NUM_IMAGES; ++ii) { + print_image(); + for (volatile int i = 0; i < IMAGE_NOPS; i++) + ; + } + ml_test(); print("\n"); camera_init();