--- /dev/null
+# TOP - Name of the top-level module
+# DEVICE - Name of the FPGA device (device-package-speed)
+# PRJ - Name of .prj file with names of all source files. See XST manual.
+# UCF - Name of the user constraints file
+# SEARCH_DIRS - Directories to search when searching for netlists (.ngc, ...).
+# See NGDBUILD manual.
+# INTSTYLE - Style of screen output. (ise | xflow | silent)
+
+# Targets desctiption:
+# - synthesize : Synthesize all VHDL and Verilog source files, libraries, etc.
+# defined in PRJ files and produces NGC file.
+# - translate : Translate all netlist files (.ngc, ...) into the NGD file,
+# where the design is described in terms of deneral logic elements
+# such as (RAM, flip-flop, XOR, ...).
+# - map : Map the general logic from NGD file to the components in the
+# target FPGA and produces NCD_MAP file.
+# - par : PAR stands for Plase & Route. This procedure takes NCD_MAP file,
+# places all components and makes routes between them (depending
+# on the chosen optimization mode) and produces NCD file.
+# - clean : Clean build directory, dependency (*.d) files and call
+# - gen : Transfer placed and routed NCD file into the bin file, which can
+# be then used to configure particular FPGA (this is further packaged
+# for SelectMap interface via the ARM CPU)
+# - firmware : Builds the firmware for Tumbl core
+
+# Dependicies are handled, so in most cases only 'download' target is called.
+
+DEVICE := xc6slx9-2tqg144
+
+TOP := lx_dad_top
+OUT := _build
+OUTB := lx-dad
+REQB := $(OUT)/$(OUTB)
+PRJ := lx_dad_top.prj
+UCF := lx-dad.ucf
+SEARCH_DIRS := ipcore_dir
+INTSTYLE := xflow
+SRC := ..
+
+#===============================================================================
+# Abbreviations of frequently used file names.
+
+NGC := $(OUTB).ngc
+NGD := $(OUTB).ngd
+PCF := $(OUTB).pcf
+NCD_MAP := $(OUTB)_map.ncd
+NCD := $(OUTB).ncd
+BIN := $(OUTB).bin
+PKG := $(OUTB).pkg
+TWR := $(OUTB).twr
+TSI := $(OUTB).tsi
+
+REQ_NGC := $(REQB).ngc
+REQ_NGD := $(REQB).ngd
+REQ_PCF := $(REQB).pcf
+REQ_NCD_MAP := $(REQB)_map.ncd
+REQ_NCD := $(REQB).ncd
+REQ_BIN := $(REQB).bin
+REQ_PKG := $(REQB).pkg
+REQ_SRC := .
+
+#REQ_FIRMWARE := $(OUT)/imem.bin $(OUT)/imem.asm $(OUT)/dmem.bin $(OUT)/firmware.lst
+
+#===============================================================================
+# Sythesis settings (SmartXplorer)
+
+XST_GLOB_OPT := AllClockNets
+XST_OPT_LEVEL := 2
+XST_OPT_MODE := Speed
+XST_IOB_PACKING := False
+XST_POWER := NO
+XST_KEEP_HIEARCHY := No
+XST_NETLIST_HIEARCHY := As_Optimized
+XST_READ_CORES := YES
+XST_WRITE_TIMING_CONSTRAINTS := NO
+XST_CROSS_CLOCK_ANALYSIS := NO
+XST_CASE := Maintain
+XST_REDUCE_CONTROL_SETS := Auto
+XST_REGISTER_DUPLICATION := YES
+XST_REGISTER_BALANCING := Yes
+XST_MOVE_FIRST_STAGE := YES
+XST_MOVE_LAST_STAGE := YES
+XST_OPTIMIZE_PRIMITIVES := NO
+XST_USE_CLOCK_ENABLE := AUTO
+XST_EQUIVALENT_REGISTER_REMOVAL := YES
+XST_IOBUF := YES
+XST_MAX_FANOUT := 100000
+XST_RESOURCE_SHARING := YES
+XST_SLICE_UTILIZATION_RATIO_MARGIN := 5
+XST_SLICE_UTILIZATION_RATIO := 100
+XST_BRAM_UTILIZATION_RATIO := 100
+XST_DSP_UTILIZATION_RATIO := 100
+XST_USE_DSP48 := Auto
+XST_USE_SYNC_SET := Auto
+XST_USE_SYNC_RESET := Auto
+XST_SAFE_IMPLEMENTATION := No
+
+MAP_PLACER_COST_TABLE := 2
+MAP_LOGIC_OPT := on
+MAP_GLOBAL_OPT := off
+MAP_EQUIVALENT_REGISTER_REMOVAL := off
+MAP_LUT_COMBINING := off
+
+#===============================================================================
+# Firmware
+
+MB_CROSS_COMPILE ?= mbtumbl-elf-
+TARGET_CC := $(MB_CROSS_COMPILE)gcc
+TARGET_LD := $(MB_CROSS_COMPILE)ld
+TARGET_OBJCOPY := $(MB_CROSS_COMPILE)objcopy
+TARGET_OBJDUMP := $(MB_CROSS_COMPILE)objdump
+
+C_OBJS := $(OUT)/firmware.o
+A_OBJS :=
+CFLAGS := -mxl-soft-div -msoft-float -Wno-main -Wl,-no-check-sections -ffunction-sections -fno-zero-initialized-in-bss -g -O2 -Wall
+AFLAGS := -D__ASSEMBLY__ $(CFLAGS)
+LDFLAGS := -static -nostdlib -relax -defsym _STACK_SIZE=0x0200 --gc-sections
+
+OBJS := $(OUT)/start.o $(C_OBJS) $(A_OBJS)
+
+FIRMWARE_DIR := ./lx-dad_firmware
+
+#===============================================================================
+
+# Attempt to create a output directory.
+$(shell [ -d ${OUT} ] || mkdir -p ${OUT})
+
+# Verify if it was successful.
+OUTPUT_DIR := $(shell cd $(OUT) && /bin/pwd)
+$(if $(OUTPUT_DIR),,$(error output directory "$(OUT)" does not exist))
+
+#===============================================================================
+
+.PHONY: all
+all: pkg firmware
+
+.PHONY: re-synthesize
+re-synthesize $(REQ_NGC): $(addprefix $(REQ_SRC)/,$(PRJ))
+ cd $(OUT); \
+ echo " \
+ run \
+ $(addprefix -ifn $(SRC)/,$(PRJ)) \
+ -ifmt mixed \
+ -ofn $(NGC) \
+ -ofmt NGC \
+ -top $(TOP) \
+ -p $(DEVICE) \
+ -keep_hierarchy $(XST_KEEP_HIEARCHY) \
+ -glob_opt $(XST_GLOB_OPT) \
+ -opt_mode $(XST_OPT_MODE) \
+ -opt_level $(XST_OPT_LEVEL) \
+ -power $(XST_POWER) \
+ -iob $(XST_IOB_PACKING) \
+ -read_cores $(XST_READ_CORES) \
+ -write_timing_constraints $(XST_WRITE_TIMING_CONSTRAINTS) \
+ -cross_clock_analysis $(XST_CROSS_CLOCK_ANALYSIS) \
+ -case $(XST_CASE) \
+ -reduce_control_sets $(XST_REDUCE_CONTROL_SETS) \
+ -resource_sharing $(XST_RESOURCE_SHARING) \
+ -iobuf $(XST_IOBUF) \
+ -max_fanout $(XST_MAX_FANOUT) \
+ -register_duplication $(XST_REGISTER_DUPLICATION) \
+ -register_balancing $(XST_REGISTER_BALANCING) \
+ -move_first_stage $(XST_MOVE_FIRST_STAGE) \
+ -move_last_stage $(XST_MOVE_LAST_STAGE) \
+ -optimize_primitives $(XST_OPTIMIZE_PRIMITIVES) \
+ -use_clock_enable $(XST_USE_CLOCK_ENABLE) \
+ -equivalent_register_removal $(XST_EQUIVALENT_REGISTER_REMOVAL) \
+ -slice_utilization_ratio_maxmargin $(XST_SLICE_UTILIZATION_RATIO_MARGIN) \
+ -slice_utilization_ratio $(XST_SLICE_UTILIZATION_RATIO) \
+ -bram_utilization_ratio $(XST_BRAM_UTILIZATION_RATIO) \
+ -dsp_utilization_ratio $(XST_DSP_UTILIZATION_RATIO)" | xst | tee xst.log
+
+.PHONY: re-translate
+re-translate $(REQ_NGD): $(REQ_NGC) $(REQ_UCF)
+ cd $(OUT); \
+ ngdbuild -intstyle $(INTSTYLE) -p $(DEVICE) -nt timestamp -uc $(SRC)/$(UCF) \
+ $(addprefix -sd $(SRC)/,$(SEARCH_DIRS)) \
+ $(NGC) \
+ $(NGD)
+
+.PHONY: re-map
+re-map $(REQ_NCD_MAP) $(REQ_PCF): $(REQ_NGD)
+ cd $(OUT); \
+ map -w -intstyle $(INTSTYLE) -p $(DEVICE) -logic_opt $(MAP_LOGIC_OPT) -ol high -t $(MAP_PLACER_COST_TABLE) -xt 0 \
+ -r 4 -global_opt $(MAP_GLOBAL_OPT) -mt off -ir off -pr off -lc $(MAP_LUT_COMBINING) \
+ -power off -equivalent_register_removal $(MAP_EQUIVALENT_REGISTER_REMOVAL) \
+ -o $(NCD_MAP) $(NGD) $(PCF) | tee map.log
+
+.PHONY: re-par
+re-par $(REQ_NCD): $(REQ_NCD_MAP) $(REQ_PCF)
+ cd $(OUT); \
+ par -w -intstyle $(INTSTYLE) -ol high -xe n -mt off $(NCD_MAP) $(NCD) $(PCF) | tee par.log
+ cd $(OUT); \
+ trce -e 20 -tsi $(TSI) -o $(TWR) $(NCD) $(PCF)
+
+.PHONY: re-gen
+re-gen $(REQ_BIN): $(REQ_NCD)
+ cd $(OUT); \
+ bitgen -w -g Binary:yes -g INIT_9K:Yes -g StartUpClk:Cclk $(NCD) $(OUTB) $(PCF) | tee bitgen.log
+
+.PHONY: packager
+packager $(OUT)/packager:
+ gcc packager.c -o $(OUT)/packager
+
+.PHONY: re-pkg
+re-pkg $(REQ_PKG): $(OUT)/packager $(REQ_BIN)
+ cd $(OUT); \
+ ./packager le $(BIN) $(PKG)
+
+$(OUT)/%.o: $(FIRMWARE_DIR)/%.c
+ $(TARGET_CC) $(CFLAGS) -c $< -o $@
+
+$(OUT)/%.o: $(FIRMWARE_DIR)/%.S
+ $(TARGET_CC) $(AFLAGS) -c $< -o $@
+
+$(OUT)/firmware.elf: $(OBJS)
+ $(TARGET_LD) $(LDFLAGS) -T $(FIRMWARE_DIR)/utils/tumbl.ld-script -o $@ $(OBJS)
+
+$(OUT)/bin2mem: $(FIRMWARE_DIR)/utils/bin2mem.c
+ gcc $< -o $@
+
+.PHONY: re-firmware
+re-firmware $(REQ_FIRMWARE): $(REQ_PKG) $(OUT)/bin2mem $(OUT)/firmware.elf
+ $(TARGET_OBJCOPY) -O binary $(OUT)/firmware.elf -j .text -S $(OUT)/imem.bin
+ $(TARGET_OBJCOPY) -O binary $(OUT)/firmware.elf -j .data -S $(OUT)/dmem.bin
+ $(TARGET_OBJDUMP) -DSCz $(OUT)/firmware.elf >$(OUT)/firmware.lst
+ cd $(OUT); \
+ $(TARGET_OBJDUMP) -b binary -mmbtumbl -EB -D imem.bin | sed -e 's/.data/.text/' > imem.asm
+
+# imem
+# watch -d ./usb_sendhex -d 0x1669:0x1023 -t 4 -s 0x80000000 -l 0x200 -f dump -u -
+# dmem
+# watch -d ./usb_sendhex -d 0x1669:0x1023 -t 4 -s 0x80001000 -l 0x200 -f dump -u -
+# PC
+# watch -d ./usb_sendhex -d 0x1669:0x1023 -t 4 -s 0x80003008 -l 0x4 -f dump -u -
+
+#===============================================================================
+
+.PHONY: clean
+clean:
+ rm -rf $(OUT)
+
+.PHONY: synthesize
+synthesize: $(REQ_NGC)
+
+.PHONY: translate
+translate: $(REQ_NGD)
+
+.PHONY: map
+map: $(REQ_NCD_MAP) $(REQ_PCF)
+
+.PHONY: par
+par: $(REQ_NCD)
+
+.PHONY: gen
+gen: $(REQ_BIN)
+
+.PHONY: pkg
+pkg: $(OUT)/packager $(REQ_PKG)
+
+.PHONY: firmware
+firmware: $(REQ_FIRMWARE)
--- /dev/null
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+-- Connects example memory
+
+entity bus_example is
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Global Reset
+ reset_i : in std_logic;
+ -- Master CPU peripheral bus
+ bls_i : in std_logic_vector(3 downto 0);
+ address_i : in std_logic_vector(11 downto 0);
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0)
+
+ -- Non bus signals
+ --
+ -- Add there external component signals
+ );
+end bus_example;
+
+architecture Behavioral of bus_example is
+
+begin
+
+ data_o <= (others => '0');
+
+end Behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+-- Memory bus measurement
+-- Holds the signal for one clock to simulate longest route
+
+entity bus_measurement is
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Address
+ address_i : in std_logic_vector(1 downto 0);
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+end bus_measurement;
+
+architecture Behavioral of bus_measurement is
+
+ -- Wiring
+ signal meas1_out_s : std_logic_vector(31 downto 0);
+ signal meas1_ce_s : std_logic;
+ --
+ signal meas2_out_s : std_logic_vector(31 downto 0);
+ signal meas2_ce_s : std_logic;
+
+begin
+
+ -- First measurement register (0xAAAAAAAA)
+measurement1: measurement_register
+ generic map
+ (
+ id_g => "10101010101010101010101010101010"
+ )
+ port map
+ (
+ clk_i => clk_i,
+ ce_i => meas1_ce_s,
+ switch_i => address_i(0),
+ reset_i => reset_i,
+ bls_i => bls_i,
+ data_i => data_i,
+ data_o => meas1_out_s
+ );
+
+ -- Second measurement register (=0x55555555)
+measurement2: measurement_register
+ generic map
+ (
+ id_g => "01010101010101010101010101010101"
+ )
+ port map
+ (
+ clk_i => clk_i,
+ ce_i => meas2_ce_s,
+ switch_i => address_i(0),
+ reset_i => reset_i,
+ bls_i => bls_i,
+ data_i => data_i,
+ data_o => meas2_out_s
+ );
+
+-- Bus process
+update:
+ process (ce_i, address_i, meas1_out_s, meas2_out_s)
+ begin
+
+ -- Defaults
+ meas1_ce_s <= '0';
+ meas2_ce_s <= '0';
+ data_o <= (others => 'X');
+
+ -- Chip Enable
+ if ce_i = '1' then
+ if address_i(1) = '0' then
+ meas1_ce_s <= '1';
+ data_o <= meas1_out_s;
+ else
+ meas2_ce_s <= '1';
+ data_o <= meas2_out_s;
+ end if;
+ end if;
+
+ end process;
+
+end Behavioral;
+
--- /dev/null
+--
+-- * Counter - divider *
+--
+-- part of LXPWR motion control board (c) PiKRON Ltd
+-- idea by Pavel Pisa PiKRON Ltd <ppisa@pikron.com>
+--
+-- license: BSD
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity cnt_div is
+ generic (
+ cnt_width_g : natural := 8
+ );
+ port
+ (
+ clk_i : in std_logic;
+ en_i : in std_logic;
+ reset_i : in std_logic;
+ ratio_i : in std_logic_vector(cnt_width_g-1 downto 0);
+ q_out_o : out std_logic
+ );
+end cnt_div;
+
+architecture behavioral of cnt_div is
+ signal cnt_val_s : natural range 0 to (2**cnt_width_g - 1);
+ signal cnt_val_r : natural range 0 to (2**cnt_width_g - 1);
+begin
+
+comb: process (reset_i, en_i, ratio_i, cnt_val_r)
+ begin
+ if reset_i = '1' then
+ cnt_val_s <= to_integer(unsigned(ratio_i));
+ q_out_o <= '0';
+ else
+ if en_i = '0' then
+ cnt_val_s <= cnt_val_r;
+ q_out_o <= '0';
+ else
+ if cnt_val_r <= 1 then
+ cnt_val_s <= to_integer(unsigned(ratio_i));
+ q_out_o <= '1';
+ else
+ cnt_val_s <= cnt_val_r - 1;
+ q_out_o <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+seq: process
+ begin
+ wait until clk_i'event and clk_i = '1';
+ cnt_val_r <= cnt_val_s;
+ end process;
+
+end behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+-- D circuit (filtered)
+
+entity dff2 is
+ port
+ (
+ clk_i : in std_logic;
+ d_i : in std_logic;
+ q_o : out std_logic
+ );
+end dff2;
+
+architecture behavioral of dff2 is
+ signal d_2r : std_logic;
+ signal d_r : std_logic;
+ signal data_s : std_logic;
+
+ -- XST attributes
+ attribute REGISTER_DUPLICATION : string;
+ attribute REGISTER_DUPLICATION of d_2r : signal is "NO";
+ attribute REGISTER_DUPLICATION of d_r : signal is "NO";
+
+begin
+ q_o <= data_s;
+
+seq:
+ process
+ begin
+ wait until clk_i'event and clk_i = '1';
+ if d_2r = d_r then
+ data_s <= d_r;
+ end if;
+
+ d_2r <= d_r;
+ d_r <= d_i;
+ end process;
+
+end behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+-- D circuit (filtered)
+
+entity dff3 is
+ port
+ (
+ clk_i : in std_logic;
+ d_i : in std_logic;
+ q_o : out std_logic
+ );
+end dff3;
+
+architecture behavioral of dff3 is
+ signal d_3r : std_logic;
+ signal d_2r : std_logic;
+ signal d_r : std_logic;
+ signal data_s : std_logic;
+
+ -- XST attributes
+ attribute REGISTER_DUPLICATION : string;
+ attribute REGISTER_DUPLICATION of d_3r : signal is "NO";
+ attribute REGISTER_DUPLICATION of d_2r : signal is "NO";
+ attribute REGISTER_DUPLICATION of d_r : signal is "NO";
+
+begin
+ q_o <= data_s;
+
+seq:
+ process
+ begin
+ wait until clk_i'event and clk_i = '1';
+ if d_3r = d_2r and d_2r = d_r then
+ data_s <= d_3r;
+ end if;
+
+ d_3r <= d_2r;
+ d_2r <= d_r;
+ d_r <= d_i;
+ end process;
+
+end behavioral;
--- /dev/null
+# lx-dad with LPC4088 and Spartan6 XC6SLX9-2TQG144
+CONFIG VCCAUX = 3.3;
+
+# ====================================================================
+# INPUTS
+# ====================================================================
+
+# Clock
+#NET CLK_CPU PERIOD = 13.88ns HIGH 50%;
+#NET CLK_CPU LOC = P15 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET CLK_50M PERIOD = 20.00ns HIGH 50%;
+NET CLK_50M LOC = P14 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+
+# Reset (active LOW)
+NET INIT LOC = P39 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+# Memory peripheral
+NET CS0_XC LOC = P64 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+#NET CS1_XC LOC = P1 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+
+NET RD LOC = P60 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET BLS<0> LOC = P70 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET BLS<1> LOC = P67 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET BLS<2> LOC = P66 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET BLS<3> LOC = P55 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+
+NET ADDRESS<0> LOC = P134 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<1> LOC = P133 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<2> LOC = P132 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<3> LOC = P131 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<4> LOC = P127 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<5> LOC = P126 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<6> LOC = P124 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<7> LOC = P123 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<8> LOC = P121 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<9> LOC = P120 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<10> LOC = P119 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<11> LOC = P118 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<12> LOC = P117 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<13> LOC = P116 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<14> LOC = P115 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET ADDRESS<15> LOC = P114 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+NET DATA<0> LOC = P65 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<1> LOC = P62 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<2> LOC = P61 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<3> LOC = P46 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<4> LOC = P45 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<5> LOC = P44 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<6> LOC = P43 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<7> LOC = P48 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<8> LOC = P41 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<9> LOC = P40 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<10> LOC = P59 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<11> LOC = P58 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<12> LOC = P57 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<13> LOC = P56 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<14> LOC = P51 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<15> LOC = P50 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<16> LOC = P38 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<17> LOC = P35 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<18> LOC = P34 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<19> LOC = P33 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<20> LOC = P32 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<21> LOC = P30 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<22> LOC = P29 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<23> LOC = P27 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<24> LOC = P144 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<25> LOC = P143 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<26> LOC = P142 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<27> LOC = P141 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<28> LOC = P140 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<29> LOC = P139 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<30> LOC = P138 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET DATA<31> LOC = P137 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+# Interrupt to master MCU
+NET EVENT_JK_J LOC = P111 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+# IRC
+#NET IRC0_A LOC = P2 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC0_B LOC = P6 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC0_INDEX LOC = P7 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC0_MARK LOC = P5 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC1_A LOC = P8 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC1_B LOC = P10 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC1_INDEX LOC = P11 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC1_MARK LOC = P9 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC2_A LOC = P12 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC2_B LOC = P17 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC2_INDEX LOC = P21 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC2_MARK LOC = P16 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC3_A LOC = P22 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC3_B LOC = P24 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC3_INDEX LOC = P26 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC3_MARK LOC = P23 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC4_A LOC = P93 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC4_B LOC = P104 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC4_INDEX LOC = P105 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC4_MARK LOC = P92 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC5_A LOC = P85 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC5_B LOC = P87 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC5_INDEX LOC = P88 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC5_MARK LOC = P84 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC6_A LOC = P81 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC6_B LOC = P82 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC6_INDEX LOC = P83 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC6_MARK LOC = P80 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+#NET IRC7_A LOC = P75 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC7_B LOC = P78 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC7_INDEX LOC = P79 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET IRC7_MARK LOC = P74 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+
+# ====================================================================
+# S1 Interface
+# ====================================================================
+
+#NET S1_CLK_IN PERIOD = 20.00ns HIGH 50%;
+#NET S1_CLK_IN LOC = P95 | IOSTANDARD = LVCMOS33 | SLEW = FAST | PULLUP;
+#NET S1_MISO LOC = P98 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | PULLUP;
+#NET S1_SYNC_IN LOC = P100 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | PULLUP;
+
+#NET S1_CLK_OUT LOC = P94 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+#NET S1_MOSI LOC = P97 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+#NET S1_SYNC_OUT LOC = P101 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
--- /dev/null
+-- Clock Cross Domain Synchronization Elastic Buffer/FIFO
+--
+-- Copyright (c) 2014, Pavel Pisa <pisa@cmp.felk.cvut.cz>
+-- Designed for PiKRON company robotic controller
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- 1. Redistributions of source code must retain the above copyright notice, this
+-- list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright notice,
+-- this list of conditions and the following disclaimer in the documentation
+-- and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+-- Can be used and distributed under GPLv3 license as well
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.util_pkg.all;
+use work.lx_dad_pkg.all;
+
+entity lx_crosdom_ser_fifo is
+generic
+(
+ fifo_len_g : positive := 8;
+ sync_adj_g : integer := 0
+);
+port
+(
+ -- Asynchronous clock domain interface
+ acd_clock_i : in std_logic;
+ acd_miso_i : in std_logic;
+ acd_sync_i : in std_logic;
+ -- Clock
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ -- Output synchronous with clk_i
+ miso_o : out std_logic;
+ sync_o : out std_logic;
+ data_ready_o : out std_logic
+);
+end lx_crosdom_ser_fifo;
+
+architecture Behavioral of lx_crosdom_ser_fifo is
+ signal fifo_bits_s : std_logic_vector(0 to fifo_len_g - 1);
+ signal fifo_bits_r : std_logic_vector(0 to fifo_len_g - 1);
+
+ signal acd_miso_r : std_logic;
+ signal acd_sync_r : std_logic;
+ signal acd_sync_prev_s : std_logic;
+ signal acd_sync_prev_r : std_logic;
+
+ signal acd_in_loc_s : natural range 0 to fifo_len_g - 1;
+ signal acd_in_loc_r : natural range 0 to fifo_len_g - 1;
+
+ signal out_loc_s : natural range 0 to fifo_len_g - 1;
+ signal out_loc_r : natural range 0 to fifo_len_g - 1;
+
+ signal out_sync_s : std_logic_vector(0 to fifo_len_g / 2 - 1);
+ signal out_sync_r : std_logic_vector(0 to fifo_len_g / 2 - 1);
+
+ signal out_miso_s : std_logic;
+
+ attribute REGISTER_DUPLICATION : string;
+ attribute REGISTER_DUPLICATION of fifo_bits_s : signal is "NO";
+ attribute REGISTER_DUPLICATION of fifo_bits_r : signal is "NO";
+ attribute REGISTER_DUPLICATION of acd_sync_r : signal is "NO";
+ attribute REGISTER_DUPLICATION of out_sync_s : signal is "NO";
+ attribute REGISTER_DUPLICATION of out_sync_r : signal is "NO";
+
+begin
+ sync_o <= out_sync_r(max(-sync_adj_g, 0));
+
+ data_ready_o <= '0';
+
+acd_logic:
+ process (acd_miso_r, acd_sync_r, acd_sync_prev_r, acd_in_loc_r, fifo_bits_r)
+ begin
+ acd_sync_prev_s <= acd_sync_r;
+ fifo_bits_s <= fifo_bits_r;
+ if (acd_sync_r = '1') and (acd_sync_prev_r = '0') then
+ acd_in_loc_s <= 0;
+ fifo_bits_s(0) <= acd_miso_r;
+ else
+ fifo_bits_s(acd_in_loc_r) <= acd_miso_r;
+ if acd_in_loc_r /= fifo_len_g - 1 then
+ acd_in_loc_s <= acd_in_loc_r + 1;
+ else
+ acd_in_loc_s <= 0;
+ end if;
+ end if;
+ end process;
+
+acd_update:
+ process
+ begin
+ wait until acd_clock_i'event and acd_clock_i = '1';
+
+ acd_miso_r <= acd_miso_i;
+ acd_sync_r <= acd_sync_i;
+ acd_sync_prev_r <= acd_sync_prev_s;
+ acd_in_loc_r <= acd_in_loc_s;
+ fifo_bits_r <= fifo_bits_s;
+ end process;
+
+sync_logic:
+ process (fifo_bits_r, out_loc_r, out_sync_r, acd_sync_r)
+ begin
+ out_sync_s <= out_sync_r(1 to out_sync_r'length - 1 ) & acd_sync_r;
+ if out_sync_r(max(sync_adj_g, 0)) = '0' then
+ out_loc_s <= 0;
+ out_miso_s <= '0';
+ else
+ out_miso_s <= fifo_bits_r(out_loc_r);
+ if out_loc_r /= fifo_len_g - 1 then
+ out_loc_s <= out_loc_r + 1;
+ else
+ out_loc_s <= 0;
+ end if;
+ end if;
+ end process;
+
+sync_update:
+ process
+ begin
+ wait until clk_i'event and clk_i = '1';
+
+ out_loc_r <= out_loc_s;
+ miso_o <= out_miso_s;
+ out_sync_r <= out_sync_s;
+ end process;
+
+end Behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.util_pkg.all;
+
+-- Entities within lx_dad
+
+package lx_dad_pkg is
+
+ -- D sampler (filtered, 2 cycles)
+ component dff2
+ port
+ (
+ clk_i : in std_logic;
+ d_i : in std_logic;
+ q_o : out std_logic
+ );
+ end component;
+
+ -- D sampler (filtered, 3 cycles)
+ component dff3
+ port
+ (
+ clk_i : in std_logic;
+ d_i : in std_logic;
+ q_o : out std_logic
+ );
+ end component;
+
+ -- Counter - divider
+ component cnt_div
+ generic (
+ cnt_width_g : natural := 8
+ );
+ port
+ (
+ clk_i : in std_logic;
+ en_i : in std_logic;
+ reset_i : in std_logic;
+ ratio_i : in std_logic_vector(cnt_width_g-1 downto 0);
+ q_out_o : out std_logic
+ );
+ end component;
+
+ -- Clock Cross Domain Synchronization Elastic Buffer/FIFO
+ component lx_crosdom_ser_fifo
+ generic
+ (
+ fifo_len_g : positive := 8;
+ sync_adj_g : integer := 0
+ );
+ port
+ (
+ -- Asynchronous clock domain interface
+ acd_clock_i : in std_logic;
+ acd_miso_i : in std_logic;
+ acd_sync_i : in std_logic;
+ -- Clock
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ -- Output synchronous with clk_i
+ miso_o : out std_logic;
+ sync_o : out std_logic;
+ data_ready_o : out std_logic
+ );
+ end component;
+
+ --------------------------------------------------------------------------------
+ -- MEMORY BUS
+ --------------------------------------------------------------------------------
+
+ -- Measurement register
+ component measurement_register
+ generic
+ (
+ id_g : std_logic_vector(31 downto 0) := (others => '0')
+ );
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Switch
+ switch_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+ end component;
+
+ -- Example component interconnect
+ component bus_example
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ -- Master CPU peripheral bus
+ address_i : in std_logic_vector(11 downto 0);
+ ce_i : in std_logic;
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ --
+ bls_i : in std_logic_vector(3 downto 0)
+
+ -- Non bus signals
+ --
+ -- Add there externaly visible signals
+ );
+ end component;
+
+ -- Measurement interconnect
+ component bus_measurement
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Address
+ address_i : in std_logic_vector(1 downto 0);
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+ end component;
+
+ -- Register on the bus
+ component bus_register is
+ generic
+ (
+ -- Reset value
+ reset_value_g : std_logic_vector(31 downto 0) := (others => '0');
+ -- Width
+ b0_g : natural := 8;
+ b1_g : natural := 8;
+ b2_g : natural := 8;
+ b3_g : natural := 8
+ );
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector((b0_g+b1_g+b2_g+b3_g-1) downto 0);
+ data_o : out std_logic_vector((b0_g+b1_g+b2_g+b3_g-1) downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+ end component;
+
+
+ --------------------------------------------------------------------------------
+ -- BRAM
+ --------------------------------------------------------------------------------
+ type BRAM_type is (READ_FIRST, WRITE_FIRST, NO_CHANGE);
+
+ component xilinx_dualport_bram
+ generic
+ (
+ byte_width : positive := 8;
+ address_width : positive := 8;
+ we_width : positive := 4;
+ port_a_type : BRAM_type := READ_FIRST;
+ port_b_type : BRAM_type := READ_FIRST
+ );
+ port
+ (
+ clka : in std_logic;
+ rsta : in std_logic;
+ ena : in std_logic;
+ wea : in std_logic_vector((we_width-1) downto 0);
+ addra : in std_logic_vector((address_width-1) downto 0);
+ dina : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ douta : out std_logic_vector(((byte_width*we_width)-1) downto 0);
+ clkb : in std_logic;
+ rstb : in std_logic;
+ enb : in std_logic;
+ web : in std_logic_vector((we_width-1) downto 0);
+ addrb : in std_logic_vector((address_width-1) downto 0);
+ dinb : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ doutb : out std_logic_vector(((byte_width*we_width)-1) downto 0)
+ );
+ end component;
+
+end lx_dad_pkg;
+
+package body lx_dad_pkg is
+
+end lx_dad_pkg;
--- /dev/null
+vhdl work "util_pkg.vhd"
+vhdl work "lx_dad_pkg.vhd"
+vhdl work "xilinx_dualport_bram.vhd"
+vhdl work "dff3.vhd"
+vhdl work "dff2.vhd"
+vhdl work "cnt_div.vhd"
+vhdl work "measurement_register.vhd"
+vhdl work "lx_crosdom_ser_fifo.vhd"
+vhdl work "bus_measurement.vhd"
+vhdl work "bus_example.vhd"
+vhdl work "lx_dad_top.vhd"
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+use work.lx_dad_pkg.all;
+
+-- lx_dad_top - wires the modules with the outside world
+
+-- ======================================================
+-- MASTER CPU EXTERNAL MEMORY BUS
+-- ======================================================
+--
+-- Master cpu memory bus has the following wires:
+--
+-- - address[15..0] The address, used to mark chip enable
+-- - data_in[31..0] The data coming to bus
+-- - data_out[31..0] The data coming from bus, multiplexed
+-- - bls[3..0] Write enable for respective bytes
+
+entity lx_dad_top is
+ port
+ (
+ -- External
+ --clk_cpu : in std_logic;
+ clk_50m : in std_logic;
+ --
+ cs0_xc : in std_logic;
+ --
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ address : in std_logic_vector(15 downto 0);
+ data : inout std_logic_vector(31 downto 0);
+ --
+ init : in std_logic;
+ -- signal connected to external JK FF
+ event_jk_j : out std_logic
+ );
+end lx_dad_top;
+
+architecture Behavioral of lx_dad_top is
+
+ -- Reset signal
+ signal reset_s : std_logic;
+ signal init_s : std_logic;
+ -- Peripherals on the memory buses
+ -- Example memory
+ signal example_out_s : std_logic_vector(31 downto 0);
+ signal example_ce_s : std_logic;
+ -- Measurement (Master)
+ signal meas_out_s : std_logic_vector(31 downto 0);
+ signal meas_ce_s : std_logic;
+ -- Signals for external bus transmission
+ signal data_i_s : std_logic_vector(31 downto 0);
+ signal data_o_s : std_logic_vector(31 downto 0);
+ -- Signals for internal transaction
+ signal last_address_s : std_logic_vector(15 downto 0);
+ signal next_last_address_s : std_logic_vector(15 downto 0);
+ signal next_address_hold_s : std_logic;
+ signal address_hold_s : std_logic;
+ signal last_rd_s : std_logic;
+ signal next_last_rd_s : std_logic;
+ signal last_bls_s : std_logic_vector(3 downto 0); -- prev bls_f_s (active 1)
+ signal next_last_bls_s : std_logic_vector(3 downto 0);
+
+ -- Reading logic for Master CPU:
+ -- Broadcast rd only till ta (transaction acknowledge)
+ -- is received, then latch the data till the state of
+ -- rd or address changes
+ --
+ -- Data latching is synchronous - it's purpose is to
+ -- provide stable data for CPU on the bus
+ signal cs0_xc_f_s : std_logic;
+ signal rd_f_s : std_logic; -- Filtered RD
+ signal i_rd_s : std_logic; -- Internal bus RD (active 1)
+ -- signal next_i_rd_s : std_logic;
+ signal last_i_rd_s : std_logic; -- Delayed RD bus, used for latching
+ signal next_last_i_rd_s : std_logic;
+ signal i_rd_cycle2_s : std_logic; -- Some internal subsystems provide
+ signal next_i_rd_cycle2_s : std_logic; -- data only after 2 cycles
+ --
+ signal address_f_s : std_logic_vector(15 downto 0); -- Filtered address
+ --
+ signal data_f_s : std_logic_vector(31 downto 0); -- Filterred input data
+ --
+ signal data_read_s : std_logic_vector(31 downto 0); -- Latched read data
+ signal next_data_read_s : std_logic_vector(31 downto 0);
+
+ -- Writing logic:
+ signal bls_f_s : std_logic_vector(3 downto 0); -- Filtered BLS (active 1)
+ signal i_bls_s : std_logic_vector(3 downto 0); -- Internal BLS (active 1)
+ signal next_i_bls_s : std_logic_vector(3 downto 0);
+ --
+ signal data_write_s : std_logic_vector(31 downto 0); -- Data broadcasted to write
+ signal next_data_write_s : std_logic_vector(31 downto 0);
+
+ -- signal s0 : std_logic;
+ -- signal s1 : std_logic;
+ -- signal s2 : std_logic;
+
+ -- XST attributes
+ attribute REGISTER_DUPLICATION : string;
+ attribute REGISTER_DUPLICATION of rd : signal is "NO";
+ attribute REGISTER_DUPLICATION of rd_f_s : signal is "NO";
+ attribute REGISTER_DUPLICATION of bls : signal is "NO";
+ attribute REGISTER_DUPLICATION of bls_f_s : signal is "NO";
+ attribute REGISTER_DUPLICATION of address : signal is "NO";
+ attribute REGISTER_DUPLICATION of address_f_s : signal is "NO";
+ attribute REGISTER_DUPLICATION of cs0_xc : signal is "NO";
+ attribute REGISTER_DUPLICATION of cs0_xc_f_s : signal is "NO";
+
+begin
+
+-- Example connection
+memory_bus_example: bus_example
+ port map
+ (
+ clk_i => clk_50m,
+ reset_i => reset_s,
+ ce_i => example_ce_s,
+ bls_i => i_bls_s,
+ address_i => address_f_s(11 downto 0),
+ data_i => data_i_s,
+ data_o => example_out_s
+ --
+ --
+ -- additional externally connected signals goes there
+ );
+
+-- Measurement
+memory_bus_measurement: bus_measurement
+ port map
+ (
+ clk_i => clk_50m,
+ reset_i => reset_s,
+ ce_i => meas_ce_s,
+ address_i => address_f_s(1 downto 0),
+ bls_i => i_bls_s,
+ data_i => data_i_s,
+ data_o => meas_out_s
+ );
+
+-- Reset
+dff_reset: dff2
+ port map
+ (
+ clk_i => clk_50m,
+ d_i => init_s,
+ q_o => reset_s
+ );
+
+ -- Reset
+ init_s <= not init;
+
+ -- Signalling
+ data_i_s <= data_write_s;
+
+
+ event_jk_j <= '0';
+
+-- Bus update
+memory_bus_logic:
+ process(cs0_xc_f_s, rd_f_s, last_rd_s, i_rd_cycle2_s, last_i_rd_s,
+ bls_f_s, last_bls_s, data_f_s, data_write_s,
+ data_o_s, data_read_s, last_address_s, address_f_s)
+ begin
+ -- Defaults
+ next_i_rd_cycle2_s <= '0';
+ next_address_hold_s <= '0';
+
+ -- Check if we have chip select
+ if cs0_xc_f_s = '1' then
+
+ -- Reading
+ if rd_f_s = '1' then
+ -- Internal read
+ if last_rd_s = '0' or (last_address_s /= address_f_s) then
+ i_rd_s <= '1';
+ next_i_rd_cycle2_s <= '1';
+ next_last_i_rd_s <= '1';
+ elsif i_rd_cycle2_s = '1' then -- FIXME it seems that some internal
+ i_rd_s <= '1'; -- peripherals demands 2 cycles to read
+ next_last_i_rd_s <= '1';
+ else
+ i_rd_s <= '0';
+ next_last_i_rd_s <= '0';
+ end if;
+
+ if last_i_rd_s = '1' then
+ -- Latch data we just read - they are valid in this cycle
+ next_data_read_s <= data_o_s;
+ else
+ next_data_read_s <= data_read_s;
+ end if;
+ else
+ -- -- Not reading, anything goes
+ -- data_read_s <= (others => 'X');
+ next_data_read_s <= data_read_s;
+ i_rd_s <= '0';
+ next_last_i_rd_s <= '0';
+ end if;
+
+ next_last_rd_s <= rd_f_s;
+
+ -- Data for write are captured only when BLS signals are stable
+ if bls_f_s /= "0000" then
+ next_data_write_s <= data_f_s;
+ next_address_hold_s <= '1';
+ else
+ next_data_write_s <= data_write_s;
+ end if;
+
+ if (bls_f_s /= "0000") or (rd_f_s = '1') then
+ next_last_address_s <= address_f_s;
+ else
+ next_last_address_s <= last_address_s;
+ end if;
+ else
+ next_last_rd_s <= '0';
+ i_rd_s <= '0';
+ next_last_i_rd_s <= '0';
+
+ next_i_bls_s <= "0000";
+ next_data_write_s <= data_write_s;
+ next_data_read_s <= data_read_s;
+ next_last_address_s <= last_address_s;
+ end if;
+
+ -- Data for write are captured at/before BLS signals are negated
+ -- and actual write cycle takes place exacly after BLS negation
+ if ((last_bls_s and not bls_f_s) /= "0000") or
+ ((last_bls_s /= "0000") and (cs0_xc_f_s = '0')) then
+ next_i_bls_s <= last_bls_s;
+ next_last_bls_s <= "0000";
+ next_address_hold_s <= '1';
+ else
+ next_i_bls_s <= "0000";
+ if cs0_xc_f_s = '1' then
+ next_last_bls_s <= bls_f_s;
+ else
+ next_last_bls_s <= "0000" ;
+ end if;
+ end if;
+
+ end process;
+
+-- Bus update
+memory_bus_update:
+ process
+ begin
+
+ wait until clk_50m = '1' and clk_50m'event;
+
+ address_hold_s <= next_address_hold_s;
+
+ -- Synchronized external signals with main clock domain
+ cs0_xc_f_s <= not cs0_xc;
+ bls_f_s <= not bls;
+ rd_f_s <= not rd;
+ data_f_s <= data;
+ if address_hold_s = '0' then
+ address_f_s <= address;
+ else
+ address_f_s <= next_last_address_s;
+ end if;
+
+ -- Synchronoust state andvance to next period
+ last_bls_s <= next_last_bls_s;
+ last_rd_s <= next_last_rd_s;
+ i_bls_s <= next_i_bls_s;
+ -- i_rd_s <= next_i_rd_s;
+ i_rd_cycle2_s <= next_i_rd_cycle2_s;
+ last_i_rd_s <= next_last_i_rd_s;
+ data_write_s <= next_data_write_s;
+ last_address_s <= next_last_address_s;
+ data_read_s <= next_data_read_s;
+
+ end process;
+
+-- Do the actual wiring here
+memory_bus_wiring:
+ process(cs0_xc_f_s, i_bls_s, address_f_s, example_out_s, meas_out_s)
+ begin
+
+ -- Inactive by default
+ example_ce_s <= '0';
+ meas_ce_s <= '0';
+ data_o_s <= (others => '0');
+
+ if cs0_xc_f_s = '1' or i_bls_s /= "0000" then
+
+ -- Memory Map (16-bit address @ 32-bit each)
+
+ -- Each address is seen as 32-bit entry now
+ -- 0x0000 - 0x0FFF: Example memory
+ -- 0x1FFC - 0x1FFF: Measurement
+ -- 0x2000 - 0x8FFF: Free space
+
+ if address_f_s < "0001000000000000" then -- Tumbl
+ example_ce_s <= '1';
+ data_o_s <= example_out_s;
+ elsif address_f_s(15 downto 2) = "00011111111111" then -- Measurement
+ meas_ce_s <= '1';
+ data_o_s <= meas_out_s;
+ end if;
+
+ end if;
+
+ end process;
+
+-- If RD and BLS is not high, we must keep DATA at high impedance
+-- or the FPGA collides with SDRAM (damaging each other)
+memory_bus_out:
+ process(cs0_xc, rd, data_read_s)
+ begin
+
+ -- CS0 / RD / BLS are active LOW
+ if cs0_xc = '0' and rd = '0' then
+ -- Don't risk flipping (between data_o_s and latched data_read_s, it's better to wait)
+ -- Maybe check this later.
+ -- if last_i_rd_s = '1' then
+ -- data <= data_o_s;
+ -- else
+ data <= data_read_s;
+ -- end if;
+ else
+ -- IMPORTANT!!!
+ data <= (others => 'Z');
+ end if;
+
+ end process;
+
+end Behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+-- Transaction measurement register
+
+entity measurement_register is
+ generic
+ (
+ id_g : std_logic_vector(31 downto 0) := (others => '0')
+ );
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Switch
+ switch_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+end measurement_register;
+
+architecture Behavioral of measurement_register is
+ signal value_s : std_logic_vector(31 downto 0);
+begin
+
+ data_o <= value_s when switch_i = '1' else id_g;
+
+-- Write waits for clock
+memory_bus_write:
+ process
+ begin
+
+ wait until clk_i'event and clk_i = '1';
+
+ if reset_i = '1' then
+ value_s <= (others => '0');
+ else
+
+ if ce_i = '1' and bls_i /= "0000" then
+
+ if bls_i(0) = '1' then
+ value_s(7 downto 0) <= data_i(7 downto 0);
+ end if;
+ if bls_i(1) = '1' then
+ value_s(15 downto 8) <= data_i(15 downto 8);
+ end if;
+ if bls_i(2) = '1' then
+ value_s(23 downto 16) <= data_i(23 downto 16);
+ end if;
+ if bls_i(3) = '1' then
+ value_s(31 downto 24) <= data_i(31 downto 24);
+ end if;
+
+ end if;
+ end if;
+
+ end process;
+
+end Behavioral;
+
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <endian.h>
+
+/* This util converts bitstream to more friendly format
+ * for select map interface with x16 line.
+ */
+
+/* Endianness */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+int source_be = 0;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+int source_be = 1;
+#else
+#error Invalid endianness.
+#endif
+
+uint32_t swab32(uint32_t x)
+{
+ return x<<24 | x>>24 |
+ (x & (uint32_t)0x0000ff00UL)<<8 |
+ (x & (uint32_t)0x00ff0000UL)>>8;
+}
+
+uint8_t fpga_swap(uint8_t x)
+{
+ return ((x & (uint8_t)0x01) << 7) | ((x & (uint8_t)0x02) << 5) |
+ ((x & (uint8_t)0x04) << 3) | ((x & (uint8_t)0x08) << 1) |
+ ((x & (uint8_t)0x10) >> 1) | ((x & (uint8_t)0x20) >> 3) |
+ ((x & (uint8_t)0x40) >> 5) | ((x & (uint8_t)0x80) >> 7);
+}
+
+void __attribute__((noreturn)) error_usage(const char* argv0)
+{
+ printf("Usage: %s le|be <bin> <pkg>\n", argv0);
+ exit(1);
+}
+
+void __attribute__((noreturn)) error_reason(const char* argv0, const char* reason)
+{
+ printf("ERROR: %s\n", reason);
+ printf("Usage: %s le|be <bin> <pkg>\n", argv0);
+ exit(1);
+}
+
+int main(int argc, char** argv)
+{
+ int target_be, i;
+ uint32_t sz, szs;
+ uint8_t hb, lb;
+ char magic[4];
+ FILE *fin, *fout;
+
+ if (argc != 4)
+ error_usage(argv[0]);
+
+ if (!strcmp(argv[1], "le"))
+ target_be = 0;
+ else if (!strcmp(argv[1], "be"))
+ target_be = 1;
+ else
+ error_usage(argv[0]);
+
+ fin = fopen(argv[2], "r");
+ if (!fin)
+ error_reason(argv[0], "Failed to open input file.");
+
+ fseek(fin, 0L, SEEK_END);
+ sz = ftell(fin);
+ fseek(fin, 0L, SEEK_SET);
+
+ if (sz & 0x01)
+ error_reason(argv[0], "Invalid size (not aligned).");
+
+ fout = fopen(argv[3], "w+");
+ if (!fout)
+ error_reason(argv[0], "Failed to open output file.");
+
+ /* If we're switching endianness, we need to swap the bytes */
+ if (target_be != source_be)
+ szs = swab32(sz);
+ else
+ szs = sz;
+
+ /* Write magic */
+ magic[0] = 'F';
+ magic[1] = 'P';
+ magic[2] = 'G';
+ magic[3] = 'A';
+ fwrite(&magic, 1, 4, fout);
+
+ /* Write size */
+ fwrite(&szs, 1, sizeof(uint32_t), fout);
+
+ /* Binary must be aligned */
+ for (i = 0; i < sz / 2; i++)
+ {
+ /* Bitstream is big endian */
+ fread(&hb, 1, 1, fin);
+ fread(&lb, 1, 1, fin);
+
+ /* Swap the bites */
+ hb = fpga_swap(hb);
+ lb = fpga_swap(lb);
+
+ /* Write it */
+ if (target_be)
+ {
+ fwrite(&hb, 1, 1, fout);
+ fwrite(&lb, 1, 1, fout);
+ }
+ else
+ {
+ fwrite(&lb, 1, 1, fout);
+ fwrite(&hb, 1, 1, fout);
+ }
+ }
+
+ fclose(fout);
+ return 0;
+}
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package util_pkg is
+ -- ceil(log2(n))
+ function ceil_log2(n: natural) return natural;
+ -- ceil(a/b)
+ function ceil_div(a: integer; b: integer) return integer;
+ --
+ function max(left, right: integer) return integer;
+ function min(left, right: integer) return integer;
+end;
+
+---
+
+package body util_pkg is
+
+ function ceil_log2(n: natural) return natural is
+ begin
+ if n <= 1 then
+ return 0;
+ else
+ if n mod 2 = 0 then
+ return 1 + ceil_log2(n/2);
+ else
+ return 1 + ceil_log2((n+1)/2);
+ end if;
+ end if;
+ end function ceil_log2;
+
+ function ceil_div(a: integer; b: integer) return integer is
+ begin
+ return (a+b-1)/b;
+ end function ceil_div;
+
+ function max(left, right: integer) return integer is
+ begin
+ if left > right then return left;
+ else return right;
+ end if;
+ end;
+
+ function min(left, right: integer) return integer is
+ begin
+ if left < right then return left;
+ else return right;
+ end if;
+ end;
+
+end util_pkg;
--- /dev/null
+-- Xilinx dualport BRAM template, write-first mode, no delay
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.lx_dad_pkg.all;
+
+entity xilinx_dualport_bram is
+ generic
+ (
+ -- Not all combinations are plausible for BRAMs
+ -- byte width: 8, 9, 32, 36
+ -- we_width: 1, 2, 3, 4
+ byte_width : positive := 8;
+ address_width : positive := 8;
+ we_width : positive := 4;
+ port_a_type : BRAM_type := READ_FIRST;
+ port_b_type : BRAM_type := READ_FIRST
+ );
+ port
+ (
+ clka : in std_logic;
+ rsta : in std_logic;
+ ena : in std_logic;
+ wea : in std_logic_vector((we_width-1) downto 0);
+ addra : in std_logic_vector((address_width-1) downto 0);
+ dina : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ douta : out std_logic_vector(((byte_width*we_width)-1) downto 0);
+ clkb : in std_logic;
+ rstb : in std_logic;
+ enb : in std_logic;
+ web : in std_logic_vector((we_width-1) downto 0);
+ addrb : in std_logic_vector((address_width-1) downto 0);
+ dinb : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ doutb : out std_logic_vector(((byte_width*we_width)-1) downto 0)
+ );
+end xilinx_dualport_bram;
+
+architecture Behavioral of xilinx_dualport_bram is
+ type ram is array (0 to ((2**address_width) - 1)) of std_logic_vector(((byte_width*we_width)-1) downto 0);
+ shared variable ram_block : ram := (others => (others => '0'));
+
+begin
+
+-- CLKA process
+ram_process_a:
+ process
+ begin
+
+ wait until clka'event and clka = '1';
+
+ if ena = '1' then
+
+ -- Depends on the port type
+ case port_a_type is
+ when READ_FIRST =>
+ -- Read
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
+ end if;
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+
+ when WRITE_FIRST =>
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+ -- Read
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
+ end if;
+
+ when NO_CHANGE =>
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+ -- Read (if not writing)
+ if to_integer(unsigned(wea)) = 0 then
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
+ end if;
+ end if;
+ end case;
+
+ end if;
+
+ end process;
+
+-- CLKB process
+ram_process_b:
+ process
+ begin
+
+ wait until clkb'event and clkb = '1';
+
+ if enb = '1' then
+
+ -- Depends on the port type
+ case port_b_type is
+ when READ_FIRST =>
+ -- Read
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
+ end if;
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+
+ when WRITE_FIRST =>
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+ -- Read
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
+ end if;
+
+ when NO_CHANGE =>
+ -- Write
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+ -- Read (if not writing)
+ if to_integer(unsigned(web)) = 0 then
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
+ end if;
+ end if;
+ end case;
+
+ end if;
+
+ end process;
+
+end Behavioral;