--- /dev/null
+GHDL=ghdl
+tumbl_SRC=mbl_pkg.vhd mem.vhd fetch.vhd exeq.vhd decode.vhd core_ctrl.vhd
+tumbl_DIR=../tumbl
+lx_rocon_tumbl_SRC=lx_rocon_imem.vhd lx_rocon_dmem.vhd lx_rocon_gprf_abd.vhd lx_rocon_tumbl.vhd
+lx_rocon_tumbl_DIR=../lx-rocon_tumbl
+lx_fncapprox_SRC=lx_fncapprox_pkg.vhd lx_fncapprox_dsp48.vhd rom_table.vhd lx_fncapprox.vhd
+lx_fncapprox_DIR=../lx-fncapprox
+lx_util_SRC=util_pkg.vhd lx_rocon_pkg.vhd xilinx_dualport_bram.vhd
+lx_util_DIR=..
+lx_rocon_SRC=dff3.vhd qcounter.vhd \
+ irc_proc_inc.vhd crc.vhd cnt_div.vhd measurement_register.vhd lxmaster_transmitter.vhd \
+ lxmaster_receiver.vhd lx_crosdom_ser_fifo.vhd irc_reader.vhd irc_proc_main.vhd \
+ dff2.vhd bus_tumbl.vhd bus_measurement.vhd bus_lxmaster.vhd bus_irc.vhd lx_rocon_top.vhd
+lx_rocon_DIR=..
+
+MODULES=tumbl lx_util lx_rocon_tumbl
+
+SRC=$(foreach m, $(MODULES), $($(m)_SRC:%=$($(m)_DIR)/%))
+
+$(warning SRC=$(SRC))
+
+#SRC+=lx_rocon_top_tb.vhd
+SRC+=lx_tumbl_tb.vhd
+
+CFLAGS += -Wall
+
+GHDLFLAGS+=
+ANALYZEFLAGS+=--std=93c --ieee=synopsys -fexplicit
+
+#SIM_FLAGS=--stop-time=1000ns #--ieee-asserts=disable
+
+all: test-tumbl
+
+convert_bin2bits : convert_bin2bits.o
+
+imem.bits : imem.bin convert_bin2bits
+ ./convert_bin2bits $< >$@
+
+test-tumbl: analyze-all imem.bits
+ $(GHDL) $(GHDLFLAGS) -m $(ANALYZEFLAGS) lx_tumbl_tb
+ $(GHDL) $(GHDLFLAGS) -r lx_tumbl_tb --stop-time=10000ns --vcd=$@.vcd
+
+test-rocon: analyze-all
+ $(GHDL) $(GHDLFLAGS) -m $(ANALYZEFLAGS) lx_rocon_top_tb
+ $(GHDL) $(GHDLFLAGS) -r lx_rocon_top_tb --stop-time=10000ns --vcd=$@.vcd
+
+analyze-all: $(SRC)
+ $(GHDL) $(GHDLFLAGS) -a $(ANALYZEFLAGS) $(SRC)
+
+
+clean:
+ rm -f convert_bin2bits
+ rm -f *.o
+ $(GHDL) --clean
+ $(RM) work-obj93.cf
--- /dev/null
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+fprintbin(FILE *stream, uint32_t num, unsigned dig)
+{
+ uint32_t mask = 1 << (dig - 1);
+ for(; mask; mask >>= 1) {
+ if (fputc((num & mask)?'1':'0', stream) == EOF)
+ return -1;
+ }
+ return dig;
+}
+
+int main(int argc, char *argv[])
+{
+ char *fin_fname = NULL;
+ FILE *fin;
+ int ret = 0;
+ int vector_bits = 32;
+ size_t vector_bytes = 0;
+ int vector_be = 1;
+ int vector_be_ralign = 0;
+
+ if (argc >= 2)
+ fin_fname = argv[1];
+
+ if (!vector_bytes)
+ vector_bytes = (vector_bits + 7) / 8;
+
+ if (!vector_bits)
+ vector_bits = vector_bytes * 8;
+
+ if (fin_fname != NULL) {
+ fin = fopen(fin_fname, "rb");
+ if (fin == NULL) {
+ fprintf(stderr, "%s: cannot open input file %s\n", argv[0], fin_fname);
+ exit(1);
+ }
+ } else {
+ fin = stdin;
+ }
+
+ {
+ uint8_t buff[vector_bytes];
+ size_t read_res;
+ uint8_t *p;
+ uint8_t b;
+ size_t br;
+ size_t bn;
+
+ do {
+ read_res = fread(buff, 1, vector_bytes, fin);
+ if (read_res == 0)
+ break;
+ if (read_res == -1) {
+ fprintf(stderr, "%s: data read error\n", argv[0]);
+ ret = 1;
+ break;
+ }
+ if (read_res < vector_bytes) {
+ fprintf(stderr, "%s: partial read of last element\n", argv[0]);
+ ret = 1;
+ memset(buff + read_res, 0, vector_bytes - read_res);
+ }
+
+ p = buff + (vector_be? 0: vector_bytes - 1);
+ bn = (vector_be & !vector_be_ralign)? 8: vector_bits % 8;
+
+ for (br = vector_bits; br; br -= bn, bn = 8) {
+ if (bn > br)
+ bn = br;
+ b = *p;
+ if (vector_be) {
+ if (!vector_be_ralign)
+ b >>= (8 - bn);
+ p++;
+ } else {
+ p--;
+ }
+ if (fprintbin(stdout, b, bn) < 0) {
+ fprintf(stderr, "%s: output stream write error\n", argv[0]);
+ ret = 1;
+ break;
+ }
+ }
+
+ if (fputc('\n', stdout) == EOF) {
+ ret = -1;
+ break;
+ }
+ } while(1);
+ }
+
+ if (fin_fname != NULL)
+ fclose(fin);
+
+ return ret;
+}
--- /dev/null
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.all;
+
+LIBRARY std;
+USE std.textio.all;
+
+USE work.mbl_pkg.all;
+USE work.lx_rocon_pkg.all;
+
+
+
+ENTITY lx_tumbl_tb IS
+END lx_tumbl_tb;
+
+ARCHITECTURE behavior OF lx_tumbl_tb IS
+
+ --Clock signals
+ signal clk_cpu : std_logic := '0';
+ signal clk_50m : std_logic := '0';
+ -- Clock period definitions
+ --constant clk_period_cpu : time := 13.8 ns;
+ constant clk_period_50m : time := 20 ns;
+ constant cycle_cnt_limit : natural := 2**20 - 1;
+ signal cycle_cnt : integer range 0 to cycle_cnt_limit;
+
+ signal tumbl_reset_s : std_logic := '1';
+
+ -- Internal memory signals
+ signal imem_en_s : std_logic := '0';
+ signal dmem_en_s : std_logic := '0';
+
+ signal imem_we_s : std_logic_vector(3 downto 0) := "0000";
+ signal dmem_we_s : std_logic_vector(3 downto 0) := "0000";
+
+ signal imem_data_o_s : std_logic_vector(31 downto 0);
+ signal dmem_data_o_s : std_logic_vector(31 downto 0);
+
+ signal imem_data_i_s : std_logic_vector(31 downto 0);
+ signal dmem_data_i_s : std_logic_vector(31 downto 0);
+
+ signal imem_address_s : std_logic_vector(8 downto 0);
+ signal dmem_address_s : std_logic_vector(9 downto 0);
+
+ signal xmemb_sel_s : std_logic;
+ signal xmemb_i_s : DMEMB2CORE_Type;
+ signal xmemb_o_s : CORE2DMEMB_Type;
+
+ signal imem_ready_s : std_logic := '0';
+ signal imem_fill_addr_s : natural range 0 to 2**8-1 := 0;
+
+BEGIN
+ -- Instantiate the Unit Under Test (UUT)
+ uut: lx_rocon_tumbl
+ generic map
+ (
+ IMEM_ABITS_g => 9,
+ DMEM_ABITS_g => 10,
+ --
+ USE_HW_MUL_g => true,
+ USE_BARREL_g => true,
+ COMPATIBILITY_MODE_g => false
+ )
+ port map
+ (
+ clk_i => clk_cpu,
+ rst_i => tumbl_reset_s,
+ halt_i => '0',
+ int_i => '0',
+ trace_i => '0',
+ trace_kick_i => '0',
+
+ pc_o => open,
+ halted_o => open,
+ halt_code_o => open,
+
+ -- Internal memory (instruction)
+ imem_clk_i => clk_cpu,
+ imem_en_i => imem_en_s,
+ imem_we_i => imem_we_s,
+ imem_addr_i => imem_address_s,
+ imem_data_i => imem_data_i_s,
+ imem_data_o => imem_data_o_s,
+
+ -- Internal memory (data)
+ dmem_clk_i => clk_cpu,
+ dmem_en_i => dmem_en_s,
+ dmem_we_i => dmem_we_s,
+ dmem_addr_i => dmem_address_s,
+ dmem_data_i => dmem_data_i_s,
+ dmem_data_o => dmem_data_o_s,
+
+ -- External memory bus
+ xmemb_sel_o => xmemb_sel_s,
+ xmemb_i => xmemb_i_s,
+ xmemb_o => xmemb_o_s
+ );
+
+ clk_cpu <= clk_50m;
+ xmemb_i_s.int <= '0'; -- No interrupt
+
+ setup_process :process
+ begin
+ wait until clk_cpu'event and clk_cpu = '1';
+ if cycle_cnt < cycle_cnt_limit and imem_ready_s = '1' then
+ cycle_cnt <= cycle_cnt + 1;
+ end if;
+
+ if cycle_cnt < 8 then
+ tumbl_reset_s <= '1';
+ else
+ tumbl_reset_s <= '0';
+ end if;
+ end process;
+
+ setup_imem_process : process
+ file imem_file : text open READ_MODE is "imem.bits";
+ variable my_line : LINE;
+ variable bits_line : LINE;
+ variable mem_location : bit_vector(31 downto 0);
+ begin
+ wait until clk_50m'event and clk_50m = '1';
+
+ if endfile(imem_file) then
+ if imem_ready_s = '0' then
+ write(my_line, string'("reading imem complete"));
+ writeline(output, my_line);
+ end if;
+ imem_ready_s <= '1';
+ imem_we_s <= "0000";
+ imem_en_s <= '0';
+ else
+ imem_address_s <= std_logic_vector(to_unsigned(imem_fill_addr_s, 9));
+ readline(imem_file, bits_line);
+ read(bits_line, mem_location);
+ imem_data_i_s <= to_stdLogicVector(mem_location);
+ imem_we_s <= "1111";
+ imem_en_s <= '1';
+ imem_fill_addr_s <= imem_fill_addr_s + 1;
+ end if;
+
+ end process;
+
+ xmemb_process :process
+ variable xmemb_addr_v : std_logic_vector(14 downto 0);
+ variable my_line : LINE;
+ variable delay_access_v : std_logic;
+ begin
+ wait until clk_cpu'event and clk_cpu = '1';
+
+ -- Enable clken only when available for Tumbl
+ if cycle_cnt >= 34 and cycle_cnt <= 34 then
+ delay_access_v := '1';
+ else
+ delay_access_v := '0';
+ end if;
+
+ xmemb_i_s.clken <= not delay_access_v;
+
+ xmemb_i_s.data <= (others => 'X');
+
+ xmemb_addr_v := xmemb_o_s.addr;
+
+ if xmemb_o_s.rd = '1' then
+ if delay_access_v = '1' then
+ xmemb_i_s.data(31 downto 16) <= x"F0F0";
+ else
+ xmemb_i_s.data(31 downto 16) <= x"ACCE";
+ xmemb_i_s.data(15 downto 2) <= xmemb_addr_v(13 downto 0);
+ xmemb_i_s.data(1 downto 0) <= "00";
+ end if;
+
+ write(my_line, string'("@"));
+ write(my_line, cycle_cnt);
+ write(my_line, string'(" tumbl read @("));
+ write(my_line, to_bitvector(xmemb_o_s.addr));
+ write(my_line, string'(")"));
+ writeline(output, my_line);
+ end if;
+
+ if xmemb_o_s.bls /= "0000" then
+ write(my_line, string'("@"));
+ write(my_line, cycle_cnt);
+ write(my_line, string'(" tumbl write "));
+ write(my_line, to_bitvector(xmemb_i_s.data));
+ write(my_line, string'(" -> @("));
+ write(my_line, to_bitvector(xmemb_o_s.addr));
+ write(my_line, string'(")"));
+ writeline(output, my_line);
+ end if;
+ end process;
+
+
+ clk_50m_process :process
+ begin
+ clk_50m <= '1';
+ wait for clk_period_50m/2;
+ clk_50m <= '0';
+ wait for clk_period_50m/2;
+ end process;
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ -- External ModelSim script
+ wait;
+ end process;
+
+END;