diff --git a/.gitignore b/.gitignore index d87d560..257b03f 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ bit2fp printf_swbits hello_world blinking_led +jtag_counter +j1_blinking # # folders diff --git a/Makefile b/Makefile index 3f7049f..70b5a9a 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ LDFLAGS += -Wl,-rpath,$(CURDIR)/libs OBJS = autotest.o bit2fp.o printf_swbits.o draw_svg_tiles.o fp2bit.o \ hstrrep.o merge_seq.o new_fp.o pair2net.o sort_seq.o hello_world.o \ - blinking_led.o + blinking_led.o jtag_counter.o j1_blinking.o DYNAMIC_LIBS = libs/libfpga-model.so libs/libfpga-bit.so \ libs/libfpga-floorplan.so libs/libfpga-control.so \ @@ -24,7 +24,8 @@ DYNAMIC_LIBS = libs/libfpga-model.so libs/libfpga-bit.so \ .SECONDEXPANSION: all: new_fp fp2bit bit2fp printf_swbits draw_svg_tiles autotest hstrrep \ - sort_seq merge_seq pair2net hello_world blinking_led + sort_seq merge_seq pair2net hello_world blinking_led jtag_counter \ + j1_blinking.o include Makefile.common @@ -81,7 +82,7 @@ libs/%.so: FAKE test_dirs := $(shell mkdir -p test.gold test.out) -DESIGN_TESTS := hello_world blinking_led +DESIGN_TESTS := hello_world blinking_led jtag_counter j1_blinking AUTO_TESTS := logic_cfg routing_sw io_sw iob_cfg lut_encoding COMPARE_TESTS := xc6slx9_tiles xc6slx9_devs xc6slx9_ports xc6slx9_conns xc6slx9_sw xc6slx9_swbits @@ -194,6 +195,10 @@ hello_world: hello_world.o $(DYNAMIC_LIBS) blinking_led: blinking_led.o $(DYNAMIC_LIBS) +jtag_counter: jtag_counter.o $(DYNAMIC_LIBS) + +j1_blinking: j1_blinking.o $(DYNAMIC_LIBS) + fp2bit: fp2bit.o $(DYNAMIC_LIBS) bit2fp: bit2fp.o $(DYNAMIC_LIBS) @@ -225,6 +230,7 @@ clean: rm -f $(OBJS) *.d rm -f draw_svg_tiles new_fp hstrrep sort_seq merge_seq autotest rm -f fp2bit bit2fp printf_swbits pair2net hello_world blinking_led + rm -f jtag_counter j1_blinking rm -f xc6slx9.fp xc6slx9.svg rm -f $(DESIGN_GOLD) $(AUTOTEST_GOLD) $(COMPARE_GOLD) rm -f test.gold/compare_xc6slx9.fp diff --git a/blinking_led.c b/blinking_led.c index 9328c0a..e12796e 100644 --- a/blinking_led.c +++ b/blinking_led.c @@ -14,8 +14,8 @@ module blinking(input clk, output led); - // synthesis attribute LOC clk "P55 | IOSTANDARD = LVCMOS33" - // synthesis attribute LOC led "P48 | SLEW = QUIETIO | DRIVE = 8" + // synthesis attribute LOC clk "T8 | IOSTANDARD = LVCMOS33" + // synthesis attribute LOC led "R5 | SLEW = QUIETIO | DRIVE = 8" // COUNTER_SIZE tested as 14 (32K crystal) and 23 (20M crystal) `define COUNTER_SIZE 23 diff --git a/j1_blinking.c b/j1_blinking.c new file mode 100644 index 0000000..5a4f363 --- /dev/null +++ b/j1_blinking.c @@ -0,0 +1,61 @@ +// +// Author (C version): Wolfgang Spraul +// Author of J1: James Bowman +// License of J1: BSD +// +// This is free and unencumbered software released into the public domain. +// For details see the UNLICENSE file at the root of the source tree. +// + +#include "model.h" +#include "floorplan.h" +#include "control.h" + +// +// J1 references +// +// https://github.com/ros-drivers/wge100_driver +// http://www.ros.org/wiki/wge100_camera_firmware +// http://www.excamera.com/sphinx/fpga-j1.html +// + +/* + This C design corresponds to the following Verilog: +*/ + +int main(int argc, char** argv) +{ + struct fpga_model model; + const char *param_clock_pin, *param_led_pin; + int iob_clk_y, iob_clk_x, iob_clk_type_idx; + int iob_led_y, iob_led_x, iob_led_type_idx; + + if (cmdline_help(argc, argv)) { + printf("\n"); + return 0; + } + if (!(param_clock_pin = cmdline_strvar(argc, argv, "clock_pin"))) + param_clock_pin = "IO_L30N_GCLK0_USERCCLK_2"; + if (!(param_led_pin = cmdline_strvar(argc, argv, "led_pin"))) + param_led_pin = "IO_L48P_D7_2"; + + fpga_build_model(&model, cmdline_part(argc, argv), + cmdline_package(argc, argv)); + + fpga_find_iob(&model, xc6_find_pkg_pin(model.pkg, param_clock_pin), + &iob_clk_y, &iob_clk_x, &iob_clk_type_idx); + fdev_iob_input(&model, iob_clk_y, iob_clk_x, iob_clk_type_idx, + IO_LVCMOS33); + + fpga_find_iob(&model, xc6_find_pkg_pin(model.pkg, param_led_pin), + &iob_led_y, &iob_led_x, &iob_led_type_idx); + fdev_iob_output(&model, iob_led_y, iob_led_x, iob_led_type_idx, + IO_LVCMOS25); + fdev_iob_slew(&model, iob_led_y, iob_led_x, iob_led_type_idx, + SLEW_QUIETIO); + fdev_iob_drive(&model, iob_led_y, iob_led_x, iob_led_type_idx, + 8); + + write_floorplan(stdout, &model, FP_DEFAULT); + return fpga_free_model(&model); +} diff --git a/jtag_counter.c b/jtag_counter.c new file mode 100644 index 0000000..3ff9807 --- /dev/null +++ b/jtag_counter.c @@ -0,0 +1,152 @@ +// +// Author (C version): Wolfgang Spraul +// Author (Verilog version): Xiangfu Liu +// +// This is free and unencumbered software released into the public domain. +// For details see the UNLICENSE file at the root of the source tree. +// + +#include "model.h" +#include "floorplan.h" +#include "control.h" + +/* + This C design corresponds to the following Verilog: + +// There are 5 registers +// 0x0 R Firmware version +// 0x1 RW Counter enable/disable, enable: 1, disable: 0 +// 0x2 RW Counter write enable, enable: 1, disable: 0 +// 0x3 RW Counter write Value +// 0x4 R Counter current value + +// LED1, on: stop counting, off: counting +// LED2, on: counter > 0, off: counter == 0 + +module counter(clk, led1, led2); + input clk; + output led1; + output led2; + + // synthesis attribute LOC clk "T8 | IOSTANDARD = LVCMOS33" + // synthesis attribute LOC led "R5 | SLEW = QUIETIO | DRIVE = 8" + + reg counter_start = 1'b0; + reg counter_we = 1'b0; + reg [31:0] counter = 32'd0; + reg [31:0] counter_set = 32'd0; + always @(posedge clk) + begin + if (counter_start == 1'b1) + counter <= counter + 1; + if (counter_we == 1'b1) + counter <= counter_set; + end + + assign led1 = ~counter_start; + assign led2 = counter; + + wire jt_capture, jt_drck, jt_reset, jt_sel; + wire jt_shift, jt_tck, jt_tdi, jt_update, jt_tdo; + + BSCAN_SPARTAN6 # (.JTAG_CHAIN(1)) jtag_blk ( + .CAPTURE(jt_capture), + .DRCK(jt_drck), + .RESET(jt_reset), + .RUNTEST(), + .SEL(jt_sel), + .SHIFT(jt_shift), + .TCK(jt_tck), + .TDI(jt_tdi), + .TDO(jt_tdo), + .TMS(), + .UPDATE(jt_update) + ); + + reg [37:0] dr; + reg [3:0] addr = 4'hF; + reg checksum; + wire checksum_valid = ~checksum; + wire jtag_we = dr[36]; + wire [3:0] jtag_addr = dr[35:32]; + + assign jt_tdo = dr[0]; + + always @ (posedge jt_tck) + begin + if (jt_reset == 1'b1) + begin + dr <= 38'd0; + end + else if (jt_capture == 1'b1) + begin + checksum <= 1'b1; + dr[37:32] <= 6'd0; + addr <= 4'hF; + case (addr) + 4'h0: dr[31:0] <= 32'h20120911; + 4'h1: dr[0] <= counter_start; + 4'h2: dr[0] <= counter_we; + 4'h3: dr[31:0] <= counter_set; + 4'h4: dr[31:0] <= counter; + + default: dr[31:0] <= 32'habcdef01; + endcase + end + else if (jt_shift == 1'b1) + begin + dr <= {jt_tdi, dr[37:1]}; + checksum <= checksum ^ jt_tdi; + end + else if (jt_update & checksum_valid) + begin + addr <= jtag_addr; + if (jtag_we) + begin + case (jtag_addr) + 4'h1: counter_start <= dr[0]; + 4'h2: counter_we <= dr[0]; + 4'h3: counter_set <= dr[31:0]; + endcase + end + end + end +endmodule +*/ + +int main(int argc, char** argv) +{ + struct fpga_model model; + const char *param_clock_pin, *param_led_pin; + int iob_clk_y, iob_clk_x, iob_clk_type_idx; + int iob_led_y, iob_led_x, iob_led_type_idx; + + if (cmdline_help(argc, argv)) { + printf("\n"); + return 0; + } + if (!(param_clock_pin = cmdline_strvar(argc, argv, "clock_pin"))) + param_clock_pin = "IO_L30N_GCLK0_USERCCLK_2"; + if (!(param_led_pin = cmdline_strvar(argc, argv, "led_pin"))) + param_led_pin = "IO_L48P_D7_2"; + + fpga_build_model(&model, cmdline_part(argc, argv), + cmdline_package(argc, argv)); + + fpga_find_iob(&model, xc6_find_pkg_pin(model.pkg, param_clock_pin), + &iob_clk_y, &iob_clk_x, &iob_clk_type_idx); + fdev_iob_input(&model, iob_clk_y, iob_clk_x, iob_clk_type_idx, + IO_LVCMOS33); + + fpga_find_iob(&model, xc6_find_pkg_pin(model.pkg, param_led_pin), + &iob_led_y, &iob_led_x, &iob_led_type_idx); + fdev_iob_output(&model, iob_led_y, iob_led_x, iob_led_type_idx, + IO_LVCMOS25); + fdev_iob_slew(&model, iob_led_y, iob_led_x, iob_led_type_idx, + SLEW_QUIETIO); + fdev_iob_drive(&model, iob_led_y, iob_led_x, iob_led_type_idx, + 8); + + write_floorplan(stdout, &model, FP_DEFAULT); + return fpga_free_model(&model); +} diff --git a/libs/bit_frames.c b/libs/bit_frames.c index 76aec7b..45f0616 100644 --- a/libs/bit_frames.c +++ b/libs/bit_frames.c @@ -9,6 +9,8 @@ #include "bit.h" #include "control.h" +#undef DBG_EXTRACT_T2 + static uint8_t* get_first_minor(struct fpga_bits* bits, int row, int major) { int i, num_frames; @@ -580,6 +582,10 @@ static int extract_type2(struct extract_state* es) struct switch_to_yx_l2 switch_to_yx_l2; struct switch_to_rel switch_to_rel; +#ifdef DBG_EXTRACT_T2 + fprintf(stderr, "#D %s:%i t2 gclk %i u16 0x%X\n", + __FILE__, __LINE__, gclk_i, u16); +#endif // // find and enable reg-switch for gclk_pin[i] // the writing equivalent is in write_inner_term_sw() @@ -599,6 +605,7 @@ static int extract_type2(struct extract_state* es) switch_to_yx_l2.l1.x = iob_x; switch_to_yx_l2.l1.start_switch = iob_dev->pinw[IOB_OUT_I]; switch_to_yx_l2.l1.from_to = SW_FROM; + switch_to_yx_l2.l1.exclusive_net = NO_NET; fpga_switch_to_yx_l2(&switch_to_yx_l2); RC_CHECK(es->model); if (!switch_to_yx_l2.l1.set.len) @@ -2493,6 +2500,7 @@ static int write_inner_term_sw(struct fpga_bits *bits, switch_to_yx_l2.l1.x = x; switch_to_yx_l2.l1.start_switch = fpga_switch_str_i(model, y, x, i, SW_TO); switch_to_yx_l2.l1.from_to = SW_TO; + switch_to_yx_l2.l1.exclusive_net = NO_NET; fpga_switch_to_yx_l2(&switch_to_yx_l2); RC_ASSERT(model, switch_to_yx_l2.l1.set.len); diff --git a/libs/control.c b/libs/control.c index 01f1146..9c458e5 100644 --- a/libs/control.c +++ b/libs/control.c @@ -2158,7 +2158,11 @@ int fpga_swset_in_other_net(struct fpga_model *model, int y, int x, int i, j; net_p = fnet_get(model, our_net); - if (!net_p) { HERE(); return 0; } + if (!net_p) { + fprintf(stderr ,"#E %s:%i cannot find our_net %i\n", + __FILE__, __LINE__, our_net); + return 0; + } for (i = 0; i < len; i++) { if (!fpga_switch_is_used(model, y, x, sw[i])) continue;