├── LICENSE
├── Makefile
├── README
├── build.mk
├── build_core.mk
├── cacode
└── cacode.pl
├── doc
└── GNSS_Baseband_UM.pdf
├── gpsif.vhm
├── gpsif_buf.vhm
├── gpsif_config_asic.vhd
├── gpsif_config_fpga.vhd
├── gpsif_config_sim.vhd
├── gpsif_db.vhm
├── gpsif_pkg.vhd
├── gpsif_reg.vhm
├── gpsif_sub_pkg.vhd
├── gpsif_time.vhm
├── gpsif_top.vhd
├── rbus_adp.vhm
├── rbus_pkg.vhd
├── tests
├── gpsif_db_tb.gtkw
├── gpsif_db_tb.vhd
├── gpsif_tb.gtkw
├── gpsif_tb.vhd
├── gpsif_tb_pkg.vhd
├── gpsob
│ ├── Makefile_gpsob
│ ├── README
│ └── gpsif_tb_gpsob.vhd
├── input.txt
├── input2.txt
└── output.golden
└── tools
├── common.mk
├── ghdl.mk
├── tests
├── Makefile
├── runtests.c
└── tap
│ ├── basic.c
│ ├── basic.h
│ ├── libtap.sh
│ ├── macros.h
│ └── test_pkg.vhd
└── v2p
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020, CoreSemi Pte Ltd.
2 | All rights reserved.
3 |
4 | Redistribution and use in source, binary, netlist or hardware instantiated
5 | forms, with or without modification, are permitted provided that the following
6 | conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | VHDLS := VHDS
2 | include build.mk
3 |
4 | VHDS += tests/gpsif_tb.vhd
5 | VHDS += tests/gpsif_tb_pkg.vhd
6 | VHDS += tools/tests/tap/test_pkg.vhd
7 |
8 | VHDL_TESTS := gpsif_tb
9 |
10 | # if gpsif repo is inside the soc_top repo, pull in other vhdl files
11 | # and build gpsif_tb
12 | MK_UTILS := $(wildcard ../../tools/mk_utils.mk)
13 | ifeq ($(MK_UTILS),)
14 | MK_UTILS := $(wildcard ../tools/mk_utils.mk)
15 | include $(MK_UTILS)
16 | VHDS += $(call include_vhdl,../lib/reg_file_struct)
17 | endif
18 | MK_UTILS := $(wildcard ../../tools/mk_utils.mk)
19 | ifneq ($(MK_UTILS),)
20 | include $(MK_UTILS)
21 | VHDS += $(call include_vhdl,../cpu)
22 | VHDS += $(call include_vhdl,../ring_bus)
23 | VHDS += $(call include_vhdl,../../lib/fixed_dsm_pkg)
24 | VHDS += $(call include_vhdl,../../lib/reg_file_struct)
25 | VHDS += $(call include_vhdl,../../lib/memory_tech_lib)
26 | VHDS += $(call include_vhdl,../../lib/hwutils)
27 | endif
28 |
29 | VHDL_TOPS += $(VHDL_TESTS)
30 |
31 | TOOLS_DIR := $(firstword $(wildcard ../../tools) tools)
32 |
33 | all: $(VHDL_TOPS)
34 |
35 | work-obj93.cf: $(VHDS)
36 |
37 | tests/gpsif_tb.ghw: gpsif_tb
38 | ./gpsif_tb --wave=$@ --stop-time=9400us --ieee-asserts=disable
39 |
40 | RUNTESTS := $(TOOLS_DIR)/tests/runtests
41 | $(RUNTESTS):
42 | make -C $(dir $@)
43 |
44 | check: $(RUNTESTS) $(VHDL_TESTS)
45 | $(RUNTESTS) test_bins
46 |
47 | tap: $(RUNTESTS) $(VHDL_TESTS)
48 | $(RUNTESTS) -t test_bins
49 |
50 | include $(TOOLS_DIR)/ghdl.mk
51 |
52 | clean:
53 | rm -f *.cf *.o $(VHDL_TOPS) *_tap tests/*.ghw
54 | rm -f gpsif.vhd gpsif_reg.vhd cacode.vhd gpsif_db.vhd gpsif_buf.vhd rbus_adp.vhd
55 | make -C $(dir $(RUNTESTS)) clean
56 |
57 | .PHONY: all clean check tap
58 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | CoreSemi GNSS Baseband receiver for GPS compatible signals.
2 |
3 | See the manual "1v0 GPS Manual" for details.
4 |
5 |
--------------------------------------------------------------------------------
/build.mk:
--------------------------------------------------------------------------------
1 | include $(dir $(lastword $(MAKEFILE_LIST)))build_core.mk
2 |
3 | $(VHDLS) += gpsif_config_fpga.vhd
4 | $(VHDLS) += gpsif_config_sim.vhd
5 |
--------------------------------------------------------------------------------
/build_core.mk:
--------------------------------------------------------------------------------
1 | $(VHDLS) += rbus_pkg.vhd
2 | $(VHDLS) += rbus_adp.vhd
3 | $(VHDLS) += gpsif_pkg.vhd
4 | $(VHDLS) += gpsif_sub_pkg.vhd
5 | $(VHDLS) += gpsif.vhd
6 | $(VHDLS) += gpsif_reg.vhd
7 | $(VHDLS) += gpsif_db.vhd
8 | $(VHDLS) += gpsif_buf.vhd
9 | $(VHDLS) += gpsif_time.vhd
10 | $(VHDLS) += gpsif_top.vhd
11 |
--------------------------------------------------------------------------------
/cacode/cacode.pl:
--------------------------------------------------------------------------------
1 | #! /usr/bin/perl
2 |
3 | $prn = $ARGV[0];
4 |
5 | $str;
6 |
7 | @g2shift = ( 5, 6, 7, 8, 17, 18, 139, 140, 141, 251, 252, 254, 255, 256, 257, 258, 469, 470, 471, 472, 473, 474, 509, 512, 513, 514, 515, 516, 859, 860, 861, 862, 145, 175, 52, 21, 237, 235, 886, 657, 634, 762, 355, 1012, 176, 603, 130, 359, 595, 68, 386);
8 | @g = (-1,-1,-1,-1,-1,-1,-1,-1,-1,-1);
9 |
10 | for ($i=0; $i<1023; $i++){
11 | if(($i >= 1023- $g2shift[$prn-1] -1) and ($i < 1023- $g2shift[$prn-1] +10-1)){
12 | if($g[9] == 1){
13 | printf "0";
14 | $str = "0".$str;
15 | }else{
16 | printf "1";
17 | $str = "1".$str;
18 | }
19 | }
20 |
21 | $tmp = 0;
22 | for ($j=9;$j>=0;$j--){
23 | $tmp = $tmp*2;
24 | if($g[$j] == -1){
25 | $tmp = $tmp +1;
26 | }
27 | }
28 | printf " %03x %04o\n",$tmp,$tmp;
29 |
30 | #G1
31 | # $tmp = $g[2]*$g[9];
32 | #G2
33 | $tmp = $g[1]*$g[2]*$g[5]*$g[7]*$g[8]*$g[9];
34 |
35 | for ($j=9;$j>0;$j--){
36 | $g[$j] = $g[$j-1];
37 | }
38 | $g[0] = $tmp;
39 | # print " @g\n";
40 | }
41 | print "\n";
42 | #print "$str\n";
43 | $str = "00".$str;
44 | $str = unpack("H3", pack("B*", $str));
45 | printf "$str\n";
46 |
--------------------------------------------------------------------------------
/doc/GNSS_Baseband_UM.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoreSemi/gnss-baseband/42f19080aeeaa6946508fe7b70cd8b1a879ea8cb/doc/GNSS_Baseband_UM.pdf
--------------------------------------------------------------------------------
/gpsif.vhm:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 |
5 | use work.fixed_pkg.all;
6 | use work.rf_pack.all;
7 | use work.memory_pack.all;
8 | use work.bist_pack.all;
9 | use work.ring_bus_pack.all;
10 | use work.rbus_pack.all;
11 | use work.cpu2j0_pack.all;
12 | use work.gpsif_pack.all;
13 | use work.gpsif_sub_pack.all;
14 |
15 | entity gpsif is
16 | generic ( GPSIF_NC : integer := 7;
17 | ANGLE_INI_OLD : boolean := false );
18 | port (
19 | clk : in std_logic;
20 | rst : in std_logic;
21 | bi : in bist_scan_t;
22 | bo : out bist_scan_t;
23 | -- for debug on FPGA (from here)
24 | ring_i : in rbus_9b; -- to monitor ring bus
25 | ring_o : in rbus_9b; -- to monitor ring bus
26 | -- for debug on FPGA (to here)
27 | tgt_o : out cpu_data_i_t;
28 | tgt_i : in gpsif_tgt_i_t;
29 | dev_o : out rbus_dev_o_t;
30 | dev_i : in rbus_dev_i_t;
31 | buf_io : in gpsif_buf_i_t;
32 | time_i : in gpsif_time_t;
33 | ra_io : out gpsif_buf_ct_t;
34 | buf_bus : in gpsif_i_t;
35 | gpsif_o : out gpsif_o_t;
36 | dma : out dma_req_t );
37 | end gpsif;
38 |
39 | architecture beh of gpsif is
40 |
41 | register variable this : gpsif_reg_t reset := GPSIF_REG_RESET;
42 |
43 | signal regfile_i : gpsif_regfile_i_t;
44 | signal regfile_o : gpsif_regfile_o_t;
45 | -- for debug on FPGA (from here)
46 | type dbg_d_t is array (integer range 0 to 2) of std_logic_vector(31 downto 0);
47 | signal dbg_w : std_logic;
48 | signal dbg_a : std_logic_vector( 7 downto 0);
49 | signal dbg_wd,dbg_rd : dbg_d_t;
50 |
51 | begin
52 | dbg0h : ram_1rw
53 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
54 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(0)(31 downto 16),
55 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(0)(31 downto 16));
56 | dbg0l : ram_1rw
57 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
58 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(0)(15 downto 0),
59 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(0)(15 downto 0));
60 | dbg1h : ram_1rw
61 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
62 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(1)(31 downto 16),
63 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(1)(31 downto 16));
64 | dbg1l : ram_1rw
65 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
66 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(1)(15 downto 0),
67 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(1)(15 downto 0));
68 | dbg2h : ram_1rw
69 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
70 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(2)(31 downto 16),
71 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(2)(31 downto 16));
72 | dbg2l : ram_1rw
73 | generic map ( SUBWORD_WIDTH => 8, SUBWORD_NUM => 2, ADDR_WIDTH => 8 )
74 | port map ( clk => clk, en => '1', we => "11", a => dbg_a, dw => dbg_wd(2)(15 downto 0),
75 | rst => rst, wr => dbg_w, margin => "00", dr => dbg_rd(2)(15 downto 0));
76 | -- for debug on FPGA (to here)
77 |
78 | regfile : gpsif_regfile port map ( rst => rst, clk => clk, bi => bi, bo => bo, a => regfile_i, y => regfile_o);
79 |
80 | p0 : process(this, buf_io, buf_bus, tgt_i, dev_i, time_i, regfile_o, ring_i, ring_o)
81 | register this when clk = '1' and clk'event reset sync when rst = '1';
82 | variable active, acm_lst, acm_done, acm_strt, acm_now, acm_nxt, sft_we, stall, mns_inc : boolean;
83 | variable cntl : gpsif_cntl_t;
84 | variable carrmix_i : gpsif_carrmix_i_t;
85 | variable carrmix_o : gpsif_carrmix_o_t;
86 | variable angle, delta : gpsif_angle_t;
87 | variable delta_slv : std_logic_vector(delta'range);
88 | variable next_cnt1ms : ufixed(gpsif_cnt1ms_t'high+1 downto 0);
89 | variable next_ch : gpsif_ch_t;
90 | variable rbus_ch : integer range 0 to GPSIF_NC_MAX;
91 | variable wbus_ch : integer range 0 to GPSIF_NC_MAX;
92 | variable nn_ch : integer range 0 to GPSIF_NC_MAX;
93 | variable n_ch : integer range 0 to GPSIF_NC_MAX;
94 | variable ch : integer range 0 to GPSIF_NC_MAX;
95 | variable ra_range : natural range 64 to GPSIF_RW_MAX+1;
96 | variable nd_range : natural range 4 to GPSIF_ND_MAX+1;
97 | variable wa : integer range 0 to GPSIF_ND_MAX;
98 | variable carrmix : gpsif_sum_t;
99 | variable sum : gpsif_sum_d_t;
100 | variable acm : gpsif_acm_d_t;
101 | variable code, g1sft0, g2sft0 : std_logic;
102 | variable sft_chg : gpsif_sft_chg_t;
103 | variable sft_1ms : gpsif_cnt1ms_t;
104 | variable sft_now : gpsif_sft_t;
105 | variable sft_tmp_h : ufixed(sft_now'high -5 downto 0); -- to absorb carry
106 | variable sft_nxt_h : ufixed(sft_now'high -6 downto 0);
107 | constant sft_dec_h : ufixed(sft_now'high -6 downto 0) := (others => '1');
108 | variable sft_nxt_l : ufixed(6 downto 0); -- to absorb carry
109 | variable sft_inc : integer range 1 to 63;
110 | variable pnco_now : ufixed(delta'high-10 downto 0);
111 | variable pnco_nxt : ufixed(pnco_now'high+1 downto pnco_now'low); -- to absorb carry
112 | variable pnco_inc : natural range 1 to 256;
113 | variable reg_i : gpsif_regfile_i_t;
114 | variable devo : rbus_dev_o_t;
115 | variable tgt_rd : std_logic_vector(31 downto 0);
116 |
117 | -- for debug on FPGA (from here)
118 | variable dbg_b,dbg_r,dbg_v : boolean; -- 1ms boundary, CPU read debug info., dump debug info.
119 | variable dbg_i,dbg_q : gpsif_sum_d_t;
120 | -- for debug on FPGA (to here)
121 |
122 | begin
123 | -- select input source, and set up parameters
124 | case this.src is
125 | when IO_PIN =>
126 | carrmix_i.d := buf_io.d; wa := buf_io.wa; ra_range := 64; nd_range := 4;
127 | when CPU_BUS =>
128 | carrmix_i.d := buf_bus.d; wa := buf_bus.wa; ra_range := GPSIF_RW_MAX+1; nd_range := GPSIF_ND_MAX+1;
129 | when others => -- ((BITL_BUS1 or BITL_BUS2)
130 | carrmix_i.d := time_i.d; wa := time_i.wa; ra_range := 64; nd_range := 4;
131 | end case;
132 | if GPSIF_NC = 7 then
133 | -- channel update with 3b LFSR (only two ENOR gates for next & next-next channel numbers)
134 | -- 000 -> 001 -> 011 -> 110 -> 101 -> 010 -> 100
135 | next_ch := this.ch(1) & this.ch(0) & not (this.ch(2) xor this.ch(1));
136 | nn_ch := vtoui(next_ch(1) & next_ch(0) & not (next_ch(2) xor next_ch(1)));
137 | n_ch := vtoui(next_ch);
138 | else -- use incrementer for arbitary GPSIF_NC (1 to 6)
139 | n_ch :=(vtoui(this.ch)+1) mod GPSIF_NC;
140 | nn_ch := (n_ch +1) mod GPSIF_NC;
141 | next_ch := itov(n_ch, next_ch'length);
142 | end if;
143 | ch := vtoui(this.ch);
144 |
145 | if this.sft.chg = MNS and this.scp_chg then nn_ch := n_ch; end if;
146 | if this.sft.typ = AGN then nn_ch := n_ch; n_ch := ch; end if;
147 | active := this.ready and this.st(n_ch).run and
148 | not(this.scp_chg and this.sft.chg = PLS); -- skip for scope change
149 | acm_lst:= this.st(n_ch).mode(2 downto 1) /= "00" and this.ready and this.bndry;
150 | -- Accumulate for 1ms with C/A code --------------------------------------------
151 | reg_i.acm.a := ch * (GPSIF_REG_PER_CH/2); -- not to add rd for 6,7 to avoid boudary check error
152 | case this.rd is
153 | when 6 => reg_i.sftca.ra := n_ch;
154 | when 7 => reg_i.sftca.ra := nn_ch + (GPSIF_NC_MAX + 1);
155 | when others => reg_i.sftca.ra := ch + (GPSIF_NC_MAX + 1);
156 | reg_i.acm.a := reg_i.acm.a + this.rd/2;
157 | end case;
158 | reg_i.sftca.wa := reg_i.sftca.ra; -- ra & wa are the same for internal operations
159 | if this.rd mod 2 = 0 then
160 | reg_i.acm.bs := '0'; sum := this.sum.i; -- I
161 | else reg_i.acm.bs := '1'; sum := this.sum.q; -- Q
162 | end if;
163 | case this.rd is
164 | when 0 | 1 => code := this.code(2); -- E
165 | when 2 | 3 => code := this.code(1); -- P
166 | when others => code := this.code(0); -- L
167 | end case;
168 | if code = '1' then acm := vtoi(regfile_o.acm) + sum;
169 | else acm := vtoi(regfile_o.acm) - sum;
170 | end if;
171 | if this.acm_lst then
172 | reg_i.acm.wd := (others => '0');
173 | else reg_i.acm.wd := itov(acm,GPSIF_ACMREG_MAX+1); end if;
174 | reg_i.buf.wd := itov(acm,GPSIF_ACMREG_MAX+1);
175 | case this.rd is
176 | when 6 | 7 => acm_nxt := false;
177 | acm_now := false;
178 | when others => acm_nxt := this.ready and this.acm_lst;
179 | acm_now := this.ready and (this.acm_lst or this.acm_en);
180 | end case;
181 | if acm_nxt then reg_i.buf.we := '1'; else reg_i.buf.we := '0'; end if;
182 | if acm_now then reg_i.acm.we := '1'; else reg_i.acm.we := '0'; end if;
183 | -- RING bus --------------------------------------------------------------------
184 | -- Assuming bus is always available,
185 | -- output signals are generated without response from the bus.
186 | -- The first data is used at the 3rd cycle. (cmd and ch are output at 1st and 2nd cycles)
187 | -- keep devo.v true while sending. (BUSY insersion is another way.)
188 | case this.rd is
189 | when 2 | 6 => devo.d := itov(this.sum.i, 9); -- lower 9 bits
190 | when 3 | 7 => devo.d := itov(this.sum.i,18)(17 downto 9); -- higher bits w/ sign ext.
191 | when 4 | 0 => devo.d := itov(this.sum.q, 9);
192 | when 5 | 1 => devo.d := itov(this.sum.q,18)(17 downto 9);
193 | end case;
194 | devo.v := false;
195 | if this.ready and this.st(ch).mode(2 downto 1) = "01" and this.st(ch).run then case this.rd is -- ACQ
196 | when 0 | 1 | 2 | 3 | 4 | 5 => devo.v := true;
197 | when others =>
198 | end case; end if;
199 | devo.bsy := false; -- Currently, fixed to false (currently not used)
200 | devo.ch := RNG_CH_DSP; -- Currently, fixed to DSP
201 | -- Carrier NCO Multply & Accumulate for 8 cycles--------------------------------
202 | delta := to_ufixed(regfile_o.pnco, gpsif_angle_t'high,gpsif_angle_t'low);
203 | angle := to_ufixed(regfile_o.angle,gpsif_angle_t'high,gpsif_angle_t'low);
204 | carrmix_i.angle := angle(GPSIF_ANGLE_BITS-1 downto GPSIF_ANGLE_BITS-GPSIF_ANGLE_INDX);
205 | carrmix_o := gpsif_carrmix(carrmix_i);
206 | if active then case this.rd is
207 | when 0 => this.add.i := carrmix_o.i;
208 | this.add.q := carrmix_o.q;
209 | when 7 => this.sum.i := carrmix_o.i + this.add.i; -- update after use
210 | this.sum.q := carrmix_o.q + this.add.q;
211 | when others => this.add.i := carrmix_o.i + this.add.i;
212 | this.add.q := carrmix_o.q + this.add.q; end case;
213 | reg_i.angle.we := '1';
214 | else reg_i.angle.we := '0';
215 | end if;
216 | reg_i.pnco.a := n_ch;
217 | reg_i.angle.a := n_ch;
218 | reg_i.angle.wd := to_slv(resize(angle + delta, gpsif_angle_t'high, gpsif_angle_t'low));
219 | -- PNCO update data (It is not always used, but must be defined to avoide inferred latch)
220 | reg_i.pnco.wd := regfile_o.pnco; -- to make LS 9 bits unchanged (It is fit to current TB)
221 | --reg_i.pnco.wd := (others => '0'); -- Zero clear is enough to scan.
222 | case this.inc.pnco is
223 | when "000" => pnco_inc := 1; -- 8Hz (7.8048)
224 | when "001" => pnco_inc := 2; -- 16Hz (15.6096)
225 | when "010" => pnco_inc := 4; -- 31Hz (31.2192)
226 | when "011" => pnco_inc := 8; -- 62Hz (62.4384)
227 | when "100" => pnco_inc := 16; -- 125Hz (124.9)
228 | when "101" => pnco_inc := 32; -- 250Hz (249.8)
229 | when "110" => pnco_inc := 64; -- 500Hz (499.5)
230 | when "111" => pnco_inc := 128; -- 1 KHz (999)
231 | when others =>
232 | end case;
233 | if regfile_o.pnco(20 downto 19) & regfile_o.pnco(17) = "011" then -- PNCO is +10kHz
234 | reg_i.pnco.wd(delta'high-1 downto delta'low+17) := X"7fb"; -- rwind to -10kHz
235 | else pnco_now := delta(delta'high-1 downto delta'low+9);
236 | pnco_nxt := pnco_now + pnco_inc;
237 | reg_i.pnco.wd(delta'high-1 downto delta'low+9) := to_slv(pnco_nxt(pnco_now'range));
238 | end if;
239 | -- C/A code upfdate at RD = 6 for next RD period of 8 cycles--------------------
240 | g1sft0 := regfile_o.sftca(19) xor regfile_o.sftca(12);
241 | g2sft0 := regfile_o.sftca( 9) xor regfile_o.sftca( 8) xor regfile_o.sftca(7) xor
242 | regfile_o.sftca( 5) xor regfile_o.sftca( 2) xor regfile_o.sftca(1);
243 | reg_i.sftca.wd := regfile_o.sftca(18 downto 10) & g1sft0 &
244 | regfile_o.sftca( 8 downto 0) & g2sft0;
245 | reg_i.sftca.we := '0';
246 | if this.rd = 6 and active then
247 | this.code(2) := regfile_o.sftca(19) xor regfile_o.sftca(9);
248 | this.code(0) := regfile_o.sftca(18) xor regfile_o.sftca(8);
249 | -- 2 * 1.023 MHz sample CA code ganeration
250 | if this.even then this.code(1) := this.code(2);
251 | else reg_i.sftca.we := '1'; this.code(1) := this.code(0); end if;
252 | end if;
253 |
254 | if((this.cnt1ms(10) = '0') and (this.cnt1ms(9) = '1')) or
255 | ( this.inittm(1) = '1') then
256 | this.inittm := "10"; -- suppress 2nd init command
257 | elsif(std_logic_vector(this.cnt1ms) = "000" & x"20") and
258 | (this.inittm(1) = '0') then
259 | -- synchronize gps_tm
260 | this.inittm := "01";
261 | else this.inittm := "00"; -- keep
262 | end if;
263 |
264 | -- Next states -----------------------------------------------------------------
265 | -- range of cnt1ms is 0 to 2045 (skip 2046,2047)
266 | -- Increment higher bits (other than lower 2 bits) every 4 ND+CH periods, but 2 periods for 2044/4 to skip the 2046,2047.
267 | next_cnt1ms := this.cnt1ms + 4;
268 | -- Channel State transition w/ checking 1 ms period (before 1ms counter update)
269 | -- IDL: Channel is idle.
270 | -- ACQ: Channel is Acquisition. (send carrier mix data to DSP)
271 | -- RDY: Channel is Tracking.
272 | -- VLD: Channel is Tracking, and result is valid.
273 | acm_done := false; -- default
274 | acm_strt := false; -- default
275 | cntl := (vld => '0', ovr => '0', others => false); -- default
276 | case this.rd is
277 | when 5 => acm_done := this.ready and this.acm_lst and this.acm_en;
278 | when 7 => acm_strt := this.ready and this.acm_lst;
279 | when others =>
280 | end case;
281 | this.dma_req(this.dma_req'high) := '0'; -- default
282 | if acm_done and this.st(ch).run and this.st(ch).mode(2) = '1' then -- TRK
283 | this.dma_req := '1' & regfile_o.sftca(19 downto 14);
284 | case this.odd_ms is
285 | when 1 => this.st(ch).mode(1) := '1'; cntl.vld := '1'; cntl.ovr := this.st(ch).mode(0); -- VLD in odd period
286 | when 0 => this.st(ch).mode(0) := '1'; cntl.vld := '1'; cntl.ovr := this.st(ch).mode(1); -- VLD in even period
287 | end case; end if;
288 | if acm_strt and this.st(ch).mode(2 downto 1) /= "00" then this.st(ch).run := true; end if;
289 | -- Count-up speed of nd and cnt1ms are the same, but cnt1ms skips 2046 and 2047 to count 0 to 2045 (not 2047).
290 | reg_i.pnco.we := '0';
291 | stall := false;
292 | sft_now := to_ufixed(regfile_o.sftca(sft_now'range),sft_now'high,sft_now'low);
293 | sft_1ms := sft_now(sft_now'high downto sft_now'high - gpsif_cnt1ms_t'high);
294 | if this.ready then
295 | if this.rd = GPSIF_RD_MAX then
296 | this.acm_en := active; -- Skip is done by controlling state (Clearing acm_en is not enough)
297 | this.acm_lst := acm_lst;
298 | -- Next channel
299 | -- Do extra channel processing if the same scope is to be used for sft -1 correction.
300 | -- register output is not for the extra, it is already for next channel.
301 | if this.sft.typ /= AGN then this.ch := next_ch; end if; -- use current AGN
302 | if this.sft.typ = SKP then this.st(ch).run := false; end if;
303 | this.sft.typ := NOP;
304 | case this.sft.chg is
305 | when INC => if this.scp_chg then this.sft.typ := SKP; end if;
306 | when MNS => if this.scp_chg then this.sft.typ := AGN; end if; reg_i.angle.we := '0'; -- Do next channel twice
307 | when others =>
308 | end case;
309 | if this.sft.typ /= AGN and this.ch = GPSIF_NC_END then -- use next AGN
310 | if this.nd mod 2 = 1 then this.sft.ext := false; end if; -- clear every 2 ND processing
311 | this.nd := (this.nd + 1) mod nd_range; -- update input data scope
312 | if((next_cnt1ms(next_cnt1ms'high) or this.cnt1ms(1)) and this.cnt1ms(0)) = '1' then
313 | this.cnt1ms(this.cnt1ms'high downto 2) :=
314 | next_cnt1ms(this.cnt1ms'high downto 2); end if;
315 | this.cnt1ms(1 downto 0) := ((this.cnt1ms(1) xor this.cnt1ms(0)) and not next_cnt1ms(next_cnt1ms'high)) & not this.cnt1ms(0);
316 | cntl.bndry := (next_cnt1ms(next_cnt1ms'high) and this'register.cnt1ms(0)) = '1';
317 | -- for DEBUG (from here)
318 | if cntl.bndry and this.odd_ms = 1 then this.dbg2ms := (this.dbg2ms + 1) mod (DBG_2MS_MAX+1); end if; -- count 2ms
319 | -- for DEBUG (to here)
320 | if cntl.bndry then this.odd_ms := 1 - this.odd_ms; end if; end if;
321 | -- sft_now is used here for the current input scope.
322 | this.bndry := this.cnt1ms = sft_1ms;
323 | this.even := this.cnt1ms(0) = sft_1ms(0);
324 | this.ra := (this.nd * 8 + to_integer(sft_now(2 downto 0))) mod ra_range; -- use next nd
325 | -- Update sft & check input scope change
326 | -- Note: Logic can be simpler by removing INC 1,4, further by removing minus INC logic
327 | sft_we := false; sft_inc := 1; mns_inc := false; -- default
328 | case this.st(nn_ch).sft is
329 | when INC => if this.bndry then -- for serial acquisition
330 | case this.inc.sft is
331 | when "100" => sft_inc := 4;
332 | when "001" => sft_inc := 8;
333 | when "010" => sft_inc := 16;
334 | when "011" => sft_inc := 24;
335 | when "101" => sft_inc := 64 - 24; mns_inc := true;
336 | when "110" => sft_inc := 64 - 16; mns_inc := true;
337 | when "111" => sft_inc := 64 - 8; mns_inc := true;
338 | when others =>
339 | end case; sft_we := true; end if;
340 | when PLS => sft_we := true;
341 | when MNS => sft_we := true; sft_inc := 64 - 1; mns_inc := true;
342 | when others =>
343 | end case;
344 | sft_nxt_h := sft_now(sft_now'high downto 6);
345 | sft_nxt_l := sft_now(5 downto 0) + sft_inc;
346 | if mns_inc then
347 | sft_tmp_h := sft_nxt_h + sft_dec_h;
348 | if sft_nxt_l(6) = '0' then sft_nxt_h := sft_tmp_h(sft_nxt_h'range); -- change higher part
349 | if sft_tmp_h(sft_tmp_h'high) = '0' then sft_nxt_l := sft_nxt_l(5 downto 0) - 16; end if; end if; -- skip 1023 (2b dec.)
350 | else sft_tmp_h := sft_nxt_h + 1;
351 | if ((sft_tmp_h(sft_tmp_h'high) and sft_nxt_l(5) and sft_nxt_l(4)) or sft_nxt_l(6)) = '1'
352 | then sft_nxt_h := sft_tmp_h(sft_nxt_h'range); -- change higher part
353 | if sft_tmp_h(sft_tmp_h'high) = '1' then sft_nxt_l := sft_nxt_l(5 downto 0) + 16; end if; end if; -- skip 1023 (2b inc.)
354 | end if;
355 | this.scp_chg := sft_nxt_l(5 downto 3) /= sft_now(5 downto 3) and sft_we;
356 | -- Only one extra processing per 7*2 8-cycle is possible. (10 < (125000/1023 - 8*7*2) < 11)
357 | -- Postpone extra processing if another extra processing is already done.
358 | this.sft.chg := NOP; -- defaut
359 | if sft_we then case this.st(nn_ch).sft is
360 | when INC => this.sft.chg := INC;
361 | when PLS => stall := true; this.sft.chg := PLS;
362 | when MNS => if not (this.sft.ext and this.scp_chg) then this.sft.chg := MNS;
363 | this.sft.ext := this.scp_chg or this.sft.ext;
364 | else sft_we := false; end if;
365 | when others =>
366 | end case; end if;
367 | -- Clear sft state if new sft is written.
368 | if sft_we then reg_i.sftca.we := '1'; this.st(nn_ch).sft := NOP; end if;
369 | reg_i.sftca.wd := regfile_o.sftca; -- This is necessary to keep dma info as is.
370 | reg_i.sftca.wd(sft_now'range) := to_slv(sft_nxt_h) & to_slv(sft_nxt_l(5 downto 0));
371 | -- Update PNCO
372 | if this.st(n_ch).pnco and this.acm_lst then
373 | this.st(n_ch).pnco := false;
374 | reg_i.pnco.we := '1';
375 | reg_i.angle.we := '1';
376 | if ANGLE_INI_OLD then reg_i.angle.wd := reg_i.pnco.wd; -- Angle should be pnco here for old expected values.
377 | else reg_i.angle.wd := (others => '0'); end if;
378 | end if;
379 | else this.ra := (this.ra + 1) mod ra_range; end if;
380 | this.rd := (this.rd + 1) mod 8;
381 | elsif this.sft.chg = PLS then reg_i.angle.we := '1'; end if; -- update during inserted stall
382 | -- Is input data ready ? -------------------------------------------------------
383 | this.ready := not stall and (wa /= ((this.nd +1) mod nd_range)); -- use next nd
384 | -- Write pointer wrap round is limited at the last ND states
385 | -- to avoid overwriting of unused data
386 | -- This is only for CPU bus input that can be faster than the gpsif.
387 | -- Direct input never overwrite unused data.
388 | cntl.lst := this.nd = GPSIF_ND_MAX; -- use next nd
389 | -- CPU bus ---------------------------------------------------------------------
390 | dbg_r := false; -- defaut (It becomes true if CPU read the debug info. Then the pointer is updated.)
391 | delta_slv := '0' & not tgt_i.d(delta'high-1)
392 | & tgt_i.d(delta'high-2 downto 0);
393 | reg_i.sftca_obs.ra := vtoui(tgt_i.a(5 downto 2) and ("11" & not to_bit(tgt_i.a(5 downto 4) = "11") & "1")); -- cdef -> cd to avoid out of range
394 | wbus_ch := vtoui(tgt_i.a(4 downto 2));
395 | rbus_ch := vtoui(tgt_i.a(7 downto 5) and ("11" & not to_bit(tgt_i.a(7 downto 6) = "11"))); -- 67 -> 6
396 | reg_i.buf.a := rbus_ch*3 +(vtoui(tgt_i.a(4 downto 3) and ( "1" & not tgt_i.a(4) ))); -- 23 -> 2
397 | reg_i.buf.bs := tgt_i.a(2);
398 |
399 | this.ack := '0'; -- defaut for no bus operation
400 | if tgt_i.en = '1' and this'register.ack = '0' then this.ack := '1'; -- defaut for bus operation
401 | if tgt_i.wr = '1' then -- reg write
402 | case tgt_i.a(8 downto 5) is
403 | when b"00_00" => if tgt_i.d(tgt_i.d'high) = '0' then
404 | if reg_i.sftca.we = '1' then this.ack := '0'; -- delay to avoid port conflict
405 | else reg_i.sftca.we := '1';
406 | reg_i.sftca.wd := tgt_i.d(gpsif_sftca_reg_t'range);
407 | reg_i.sftca.wa := wbus_ch + (GPSIF_NC_MAX + 1); end if;
408 | end if;
409 | sft_chg := gpsif_sft_chg_t'val(vtoui(tgt_i.d(gpsif_sft_fld_t'range)));
410 | if sft_chg /= NOP then this.st(wbus_ch).sft := sft_chg; end if;
411 | if tgt_i.d(gpsif_sft_fld_t'low -1) = '1' then this.st(wbus_ch).pnco := true; end if;
412 | if tgt_i.d(gpsif_sft_inc_t'high+1) = '1' then this.inc.sft := tgt_i.d(gpsif_sft_inc_t'range); end if;
413 | if tgt_i.d(gpsif_pncoinc_t'high+1) = '1' then this.inc.pnco := tgt_i.d(gpsif_pncoinc_t'range); end if;
414 | when b"00_01" => if reg_i.sftca.we = '1' then this.ack := '0'; -- delay to avoid port conflict
415 | else reg_i.sftca.we := '1';
416 | reg_i.sftca.wd := "0111111111" & tgt_i.d(9 downto 0);
417 | reg_i.sftca.wa := wbus_ch;
418 | if tgt_i.d(31) = '1' then this.st(wbus_ch).mode := "010"; -- ACQ
419 | else this.st(wbus_ch).mode := "100"; end if; -- TRK
420 | this.st(wbus_ch).run := false; end if;
421 | when b"00_10" => if reg_i.pnco.we = '1' then this.ack := '0'; -- delay to avoid port conflict
422 | else reg_i.pnco.we := '1';
423 | reg_i.pnco.wd := delta_slv;
424 | reg_i.pnco.a := wbus_ch;
425 | -- The angle can be any value at init., but must be "delta" for the old expected values.
426 | if this'register.st(wbus_ch).mode(2 downto 1) = "00" then -- IDL
427 | reg_i.angle.a := wbus_ch;
428 | reg_i.angle.we := '1';
429 | if ANGLE_INI_OLD then reg_i.angle.wd := delta_slv;
430 | else reg_i.angle.wd := (others => '0'); end if; end if; end if;
431 | when b"00_11" => if tgt_i.d(31) = '0' then this.rst_en := true;
432 | if tgt_i.d(1 downto 0) = "00" then this.src := IO_PIN; -- input from IO pin
433 | elsif tgt_i.d(1 downto 0) = "01" then this.src := CPU_BUS; -- input from CPU bus
434 | elsif tgt_i.d(1 downto 0) = "10" and tgt_i.d(8) = '0' then this.src := BITL_BUS2; -- input from BL(2b/spl) bus
435 | elsif tgt_i.d(1 downto 0) = "10" and tgt_i.d(8) = '1' then this.src := BITL_BUS1; end if; -- input from BL(1b/spl) bus
436 | end if;
437 | this.int_en := tgt_i.d(5 downto 2);
438 | -- for debug on FPGA (from here)
439 | if tgt_i.d(30) = '1' then -- debug enabled
440 | this.dbg_strt := vtoui(tgt_i.d(29 downto 6));
441 | this.dbg_st := DBG_RDY;
442 | end if;
443 | -- for debug on FPGA (to here)
444 | when others =>
445 | end case;
446 | else -- reg read
447 | -- Clear valid flag after read.
448 | if tgt_i.a(8) = '1' and tgt_i.a(4 downto 2) = "101" then
449 | if this.st(rbus_ch).mode(1 downto 0) = "11" then cntl.err := true; end if;
450 | this.st(rbus_ch).mode(1 downto 0) := "00"; end if; -- clear VLD
451 | end if; -- tgt_i.wr
452 | end if;
453 | if tgt_i.a(8) = '1' then
454 | if tgt_i.a(9) = '0' then -- 0x100-1fc
455 | tgt_rd := (others => regfile_o.buf(regfile_o.buf'high)); -- signed
456 | tgt_rd(regfile_o.buf'range) := regfile_o.buf;
457 | else -- --------------- -- 0x300-3fc
458 | tgt_rd := (others => '0'); -- unsigned -- || 0x300
459 | tgt_rd(regfile_o.sftca_obsv'range) := regfile_o.sftca_obsv; -- || 0x300
460 | end if;
461 | -- for debug on FPGA (from here)
462 | else case tgt_i.a(6 downto 5) is -- read dumped signals
463 | when "00" => tgt_rd := dbg_rd(0);
464 | when "01" => tgt_rd := dbg_rd(1);
465 | when "10" => tgt_rd := dbg_rd(2); dbg_r := this.ack = '1';
466 | when others =>
467 | end case;
468 | -- for debug on FPGA (to here)
469 | end if;
470 |
471 | -- Reset -----------------------------------------------------------------------
472 | if this'register.rst_en then this := GPSIF_REG_RESET;
473 | this.int_en := this'register.int_en;
474 | -- for debug on FPGA (from here)
475 | this.dbg_st := this'register.dbg_st;
476 | this.dbg_strt := this'register.dbg_strt;
477 | -- for debug on FPGA (to here)
478 | if this'register.src = CPU_BUS then this.src := CPU_BUS; end if;-- input from CPU bus
479 | if this'register.src = BITL_BUS1 then this.src := BITL_BUS1; end if;-- input from BL(1b)
480 | if this'register.src = BITL_BUS2 then this.src := BITL_BUS2; end if;-- input from BL(2b)
481 | end if;
482 | --------------------------------------------------------------------------------
483 | -- connect output
484 | gpsif_o.cntl <= cntl;
485 | gpsif_o.odd <= this.odd_ms = 1; -- output before latch
486 | gpsif_o.rst <= this'register.rst_en;
487 | gpsif_o.sr <= this'register.st(6).mode(1 downto 0)
488 | & this'register.st(5).mode(1 downto 0)
489 | & this'register.st(4).mode(1 downto 0)
490 | & this'register.st(3).mode(1 downto 0)
491 | & this'register.st(2).mode(1 downto 0)
492 | & this'register.st(1).mode(1 downto 0)
493 | & this'register.st(0).mode(1 downto 0) & '0'
494 | & to_bit(this'register.st(6).run)
495 | & to_bit(this'register.st(5).run)
496 | & to_bit(this'register.st(4).run)
497 | & to_bit(this'register.st(3).run)
498 | & to_bit(this'register.st(2).run)
499 | & to_bit(this'register.st(1).run)
500 | & to_bit(this'register.st(0).run);
501 | gpsif_o.int_en<= this'register.int_en;
502 | gpsif_o.ra <= this'register.ra;
503 | ra_io.ra <= this'register.ra mod 32;
504 | ra_io.inittm <= this'register.inittm(0);
505 | if(this'register.src = BITL_BUS1) then ra_io.blsp1bit <= '1';
506 | else ra_io.blsp1bit <= '0'; end if;
507 | if(this'register.src = BITL_BUS2) then ra_io.blsp2bit <= '1';
508 | else ra_io.blsp2bit <= '0'; end if;
509 | tgt_o.d <= tgt_rd;
510 | tgt_o.ack <= this'register.ack;
511 | dma.req <= this'register.dma_req;
512 | -- for debug on FPGA (from here)
513 | -- Read the same data until actual read request.
514 | if this'register.rd = 7 then dbg_b := this.bndry or this.acm_lst; dbg_i := this.sum.i; dbg_q := this.sum.q;
515 | else dbg_b := false; dbg_i := this.add.i; dbg_q := this.add.q; end if;
516 | dbg_v := (dbg_b or devo.v or reg_i.angle.we = '1' or this'register.rd = 6) and
517 | this'register.dbg_st = DBG_RUN;
518 | if vtoi(itov(this'register.dbg2ms,12) &
519 | itov(this'register.odd_ms, 1) &
520 | to_slv(this'register.cnt1ms)) = this'register.dbg_strt
521 | and this'register.dbg_st = DBG_RDY then this.dbg_st := DBG_RUN; end if;
522 | if dbg_v or dbg_r then if this.dbg_a = 255 then this.dbg_st := DBG_IDL;
523 | this.dbg_a := 0;
524 | else this.dbg_a := this.dbg_a +1; end if; end if;
525 | dbg_a <= itov(this.dbg_a,8);
526 | dbg_w <= to_bit(dbg_v);
527 | dbg_wd(0) <= itov(this'register.ra,8)
528 | & itov(dbg_i,12)
529 | & itov(dbg_q,12);
530 | dbg_wd(1) <= buf_bus.d -- & to_bit(devo.v) & devo.d
531 | & regfile_o.angle(regfile_o.angle'high downto 14)
532 | & to_slv(this'register.cnt1ms)
533 | & itov(this'register.rd,3);
534 | dbg_wd(2) <= reg_i.angle.we & ring_i.stall & ring_o.word.fr & ring_o.word.d
535 | & itov(this'register.dbg2ms,7) & itov(this'register.odd_ms,1)
536 | -- & itov(this.dbg_a,4)
537 | -- & itov(wa,4)
538 | & this'register.st(1).mode(1 downto 0)
539 | & this'register.st(0).mode(1 downto 0)
540 | & to_bit(this'register.st(1).run)
541 | & to_bit(this'register.st(0).run)
542 | & to_bit(dbg_v) & to_bit(dbg_r)
543 | & this'register.ch
544 | & to_bit(wa = 0 and this.nd /= GPSIF_ND_MAX);
545 | -- for debug on FPGA (to here)
546 | regfile_i <= reg_i;
547 | dev_o <= devo;
548 | end process;
549 | end beh;
550 |
--------------------------------------------------------------------------------
/gpsif_buf.vhm:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use work.gpsif_pack.all;
4 |
5 | entity gpsif_buf is port (
6 | clk : in std_logic;
7 | rst : in std_logic;
8 | -- port
9 | gps_clk : in std_logic;
10 | gps_d : in std_logic_vector(1 downto 0);
11 | a : in gpsif_buf_ct_t;
12 | y : out gpsif_buf_i_t;
13 | waf : out gpsif_buf_rw_t );
14 | end gpsif_buf;
15 |
16 | architecture beh of gpsif_buf is
17 | register variable this : gpsif_buf_reg_t reset := gpsif_buf_reg_RESET;
18 | register variable this_sync : gpsif_buf_sync_t reset := gpsif_buf_sync_RESET;
19 |
20 | begin
21 | pi : process(this,gps_d)
22 | variable wa : integer range 0 to 31;
23 | register this when gps_clk = '1' and gps_clk'event reset sync when rst = '1';
24 | begin
25 | case this.wa/8 is -- MS 2 bits: 00=>01=>10=>11
26 | when 2 => wa := 24 + (this.wa mod 8);
27 | when 3 => wa := 16 + (this.wa mod 8);
28 | when others => wa := this.wa;
29 | end case;
30 | this.d(wa) := gps_d;
31 | case this.wa is -- MS 2 bits: 00=>01=>11=>10
32 | when 15 => this.wa := 24;
33 | when 31 => this.wa := 16;
34 | when 23 => this.wa := 0;
35 | when others => this.wa := (this.wa + 1) mod 32;
36 | end case;
37 | end process;
38 |
39 | po : process(this_sync,this)
40 | variable wa : integer range 0 to 3;
41 | register this_sync when clk = '1' and clk'event reset sync when rst = '1';
42 | begin
43 | case this_sync.wa_out is
44 | when 2 => wa := 3;
45 | when 3 => wa := 2;
46 | when others => wa := this_sync.wa_out;
47 | end case;
48 | this_sync.wa_out := this_sync.wa_dly;
49 | this_sync.wa_dly := this'register.wa/8; -- other than lower 3 bits
50 | y.wa <= wa;
51 | end process;
52 | -- connect outputs
53 | y.d <= this'register.d(a.ra); -- data specified by a is stable
54 | waf <= this'register.wa;
55 | end beh;
56 |
--------------------------------------------------------------------------------
/gpsif_config_asic.vhd:
--------------------------------------------------------------------------------
1 | configuration gpsif_asic of gpsif is
2 | for beh
3 | for regfile : gpsif_regfile
4 | use entity work.gpsif_regfile(beh);
5 | for beh
6 | for all : bist_RF1
7 | use configuration work.bist_rf1_asic;
8 | end for;
9 | for all : bist_RF2
10 | use configuration work.bist_rf2_asic;
11 | end for;
12 | end for;
13 | end for;
14 | end for;
15 | end configuration;
16 |
17 | configuration gpsif_top_asic of gpsif_top is
18 | for arch
19 | for g : gpsif
20 | use configuration work.gpsif_asic;
21 | end for;
22 | end for;
23 | end configuration;
24 |
--------------------------------------------------------------------------------
/gpsif_config_fpga.vhd:
--------------------------------------------------------------------------------
1 | configuration gpsif_fpga of gpsif is
2 | for beh
3 | for regfile : gpsif_regfile
4 | use entity work.gpsif_regfile(beh);
5 | for beh
6 | for all : bist_RF1
7 | use configuration work.bist_rf1_inferred;
8 | end for;
9 | for all : bist_RF2
10 | use configuration work.bist_rf2_inferred;
11 | end for;
12 | end for;
13 | end for;
14 | end for;
15 | end configuration;
16 |
17 | configuration gpsif_top_fpga of gpsif_top is
18 | for arch
19 | for g : gpsif
20 | use configuration work.gpsif_fpga;
21 | end for;
22 | end for;
23 | end configuration;
24 |
--------------------------------------------------------------------------------
/gpsif_config_sim.vhd:
--------------------------------------------------------------------------------
1 | configuration gpsif_sim of gpsif is
2 | for beh
3 | for all : ram_1rw
4 | use entity work.ram_1rw(inferred);
5 | end for;
6 | for regfile : gpsif_regfile
7 | use entity work.gpsif_regfile(beh);
8 | for beh
9 | for all : bist_RF1
10 | use configuration work.bist_rf1_inferred;
11 | end for;
12 | end for;
13 | end for;
14 | end for;
15 | end configuration;
16 |
17 | configuration gpsif_top_sim of gpsif_top is
18 | for arch
19 | for g : gpsif
20 | use configuration work.gpsif_sim;
21 | end for;
22 | end for;
23 | end configuration;
24 |
--------------------------------------------------------------------------------
/gpsif_db.vhm:
--------------------------------------------------------------------------------
1 | -- The gpsif_db connects the gpsif to the CPU data bus.
2 | --
3 | library ieee;
4 | use ieee.std_logic_1164.all;
5 | use ieee.numeric_std.all;
6 |
7 | use work.gpsif_pack.all;
8 | use work.cpu2j0_pack.all;
9 | use work.rf_pack.all;
10 | use work.bist_pack.all;
11 |
12 | entity gpsif_db is port (
13 | clk : in std_logic;
14 | rst : in std_logic;
15 | bi : in bist_scan_t;
16 | bo : out bist_scan_t;
17 | db_i : in cpu_data_o_t;
18 | db_o : out cpu_data_i_t;
19 | tgt_o : in cpu_data_i_t;
20 | tgt_i : out gpsif_tgt_i_t;
21 | time_i : in gpsif_time_t;
22 | intrpt : out std_logic;
23 | a : in gpsif_o_t;
24 | y : out gpsif_i_t);
25 | end entity;
26 |
27 | architecture beh of gpsif_db is
28 | type state_t is (
29 | FILL, -- Let CPU write gps data
30 | BUSY -- Wait for gpsif input buffer available
31 | );
32 | constant BUF_ADDR_WIDTH : integer := 4;
33 | subtype buf_ptr_t is integer range 0 to 2**BUF_ADDR_WIDTH-1;
34 |
35 | type gpsif_db_reg_t is record
36 | state : state_t;
37 | ms : std_logic_vector(1 downto 0);
38 | tm : std_logic_vector(1 downto 0);
39 | int : gpsif_int_t; -- interrupt status
40 | intrpt : std_logic; -- interrupt occurs
41 | err : std_logic;
42 | wa : buf_ptr_t;
43 | ack : std_logic;
44 | tgt_i : gpsif_tgt_reg_t;
45 | end record;
46 | constant GPSIF_DB_RESET : gpsif_db_reg_t := ( state => FILL, wa => 0, intrpt => '0', err => '0', ack => '0',
47 | tgt_i => ('0', others => (others => '0')),
48 | others => (others => '0'));
49 | register variable this : gpsif_db_reg_t reset := GPSIF_DB_RESET;
50 |
51 | type mem_loc_t is (GPSIF_REG, INPUT_BUF, GPSTM_REG, NONE );
52 | signal mem_loc : mem_loc_t := NONE;
53 | signal buf_db_o : cpu_data_i_t;
54 | signal gps_db_o : cpu_data_i_t;
55 | signal tim_db_o : cpu_data_i_t;
56 | signal buf_we : std_logic;
57 | signal buf_re : std_logic;
58 | signal tim_re : std_logic;
59 | signal buf_ra : buf_ptr_t;
60 | signal buf_rd : std_logic_vector(31 downto 0);
61 |
62 | -- memory map:
63 | -- 0x000 - 018 shift to ajust C/A code
64 | -- 0x020 - 038 g2 init. of C/A code
65 | -- 0x040 - 058 PNCO
66 | -- 0x060 GPSIF control (write only) reset, INT, debug
67 | -- 0x080 - 088 Dump signals for Debug
68 | -- 0x100 - 1d4 ch0-6,E/P/L,I/Q -- 7*3*2 registers
69 | -- 0x200 - 204 GPSIF status (read only)
70 | -- 0x200 - 204 input sink
71 | -- 0x210 - 214 gps time register
72 |
73 | function decode_addr(a : std_logic_vector( 9 downto 2))
74 | return mem_loc_t is
75 | begin
76 | -- IF_REG = for debug enlarging : {0x000 - 0x1fc, 0x300 - 0x3fc}
77 | ------
78 | if (a(9) = '0') or
79 | (a(8) = '1') then return GPSIF_REG;
80 | else case a(8 downto 3) is
81 | when "000000" => return INPUT_BUF;
82 | when "000010" => return GPSTM_REG;
83 | when others => return NONE;
84 | end case; end if;
85 | end function;
86 |
87 | begin
88 | -------- handle CPU data bus --------
89 | mem_loc <= decode_addr(this'register.tgt_i.a);
90 |
91 | -- select appropriate outgoing data bus
92 | with mem_loc select
93 | db_o <=
94 | gps_db_o when GPSIF_REG,
95 | buf_db_o when INPUT_BUF,
96 | tim_db_o when GPSTM_REG,
97 | ((others => '0'), '0') when others;
98 |
99 | -- connect gpsif bus
100 | tgt_i <= ( this'register.ack and to_bit(mem_loc = GPSIF_REG),
101 | this'register.tgt_i.wr, this'register.tgt_i.a, this'register.tgt_i.d);
102 | gps_db_o <= (tgt_o.d,this'register.ack);
103 |
104 | -------- Input Buffer connected to CPU bus --------
105 | -- STATUS register (Read only)
106 | buf_db_o <= (this'register.ms & a.sr
107 | & this'register.tm
108 | & this'register.int
109 | & this'register.err & to_bit(this'register.state = FILL),
110 | this'register.ack);
111 | buf_we <= this'register.ack and this'register.tgt_i.wr and to_bit(mem_loc = INPUT_BUF and this'register.state = FILL);
112 | buf_re <= this'register.ack and not this'register.tgt_i.wr and to_bit(mem_loc = INPUT_BUF);
113 | tim_re <= this'register.ack and not this'register.tgt_i.wr and to_bit(mem_loc = GPSTM_REG);
114 | buf_ra <= a.ra/16;
115 |
116 | tim_db_o <= (time_i.seq & std_logic_vector(time_i.nsec),
117 | this'register.ack);
118 | intrpt <= this'register.intrpt;
119 |
120 | -- Instantiate register file for input buffer and connect buffer bus to it.
121 | -- Input tbl 256 pairs of sign/mag bits = 16*32
122 | -- Use a 1R/1W register file.
123 | r : bist_RF1
124 | generic map ( WIDTH => 32, DEPTH => 2**BUF_ADDR_WIDTH )
125 | port map
126 | (clk => clk,
127 | rst => rst,
128 | bi => bi,
129 | bo => bo,
130 | D => db_i.d,
131 | WA => this'register.wa,
132 | WE => buf_we,
133 | RA0 => buf_ra,
134 | Q0 => buf_rd);
135 |
136 | p : process(this, a, db_i, tgt_o, buf_we, buf_re, tim_re, time_i)
137 | register this when clk = '1' and clk'event reset sync when rst = '1';
138 | variable int : gpsif_int_t;
139 | begin
140 | this.ack := db_i.en and not this'register.ack;
141 | this.tgt_i := (db_i.wr, db_i.a(9 downto 2), db_i.d);
142 |
143 | if buf_we = '1' then this.wa := (this.wa + 1) mod 16; end if;
144 | if this.wa = 0 and not a.cntl.lst then this.state := BUSY;
145 | else this.state := FILL; end if;
146 | -- Check if read is too late, set err, and clear status
147 | if a.cntl.err then this.err := '1'; end if; -- VLD (accumulate err)
148 | if tim_re = '1' then if this.tm(1 downto 0) = "11" then this.err := '1'; end if; -- Time (accumulate err)
149 | this.tm(1 downto 0):= "00"; end if; -- Clear after time read
150 | if buf_re = '1' then this.err := this.ms(1) and this.ms(0); -- Clear old err after status read, and set new err.
151 | this.ms(1 downto 0):= "00"; -- Clear after status read
152 | this.int := (others => '0'); end if; -- clear after status read
153 | -- Uptate status, check interrupt condition, and assert intrpt
154 | int := a.cntl.ovr & "00" & a.cntl.vld;
155 | if time_i.setnsec = '1' then
156 | if time_i.mscnt = '1' then this.tm(1) := '1'; int(2) := '1'; int(3) := int(3) or this.tm(0); -- 1 pps is in odd region
157 | else this.tm(0) := '1'; int(2) := '1'; int(3) := int(3) or this.tm(1); end if; end if; -- 1 pps is in even region
158 | if a.cntl.bndry then if a.odd then this.ms(1) := '1'; int(1) := '1'; int(3) := int(3) or this.ms(0); -- in odd region now
159 | else this.ms(0) := '1'; int(1) := '1'; int(3) := int(3) or this.ms(1); end if; end if; -- in even region now
160 |
161 | this.int := this.int or int; -- accumulte interrupt condition until read
162 | this.intrpt := to_bit((a.int_en and int) /= X"0");
163 | -- SW reset
164 | if a.rst then this := GPSIF_DB_RESET; end if;
165 | end process;
166 |
167 | -- Returns two neighbouring bits from a vector of 32 bits.
168 | -- The bits are addressed left to right.
169 | -- Address 0 = data(31 downto 30) and address 15 = data(1 downto 0)
170 | y.d <= buf_rd(31 - 2*(a.ra mod 16) downto 30 - 2*(a.ra mod 16));
171 | y.wa <= this'register.wa *2;
172 |
173 | end beh;
174 |
--------------------------------------------------------------------------------
/gpsif_pkg.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.std_logic_unsigned.all;
4 | use ieee.numeric_std.all;
5 |
6 | use work.fixed_pkg.all;
7 | use work.rf_pack.all;
8 | use work.bist_pack.all;
9 | use work.cpu2j0_pack.all;
10 | use work.ring_bus_pack.all;
11 | use work.rbus_pack.all;
12 | use work.gpsif_sub_pack.all;
13 |
14 | -- Code Freq.(Fco): 1.023 MHz, 1023 / 1.023MHz = 1 ms
15 | -- Carrier Freq.(Fc ): 1540*Fco = 1575.42 MHz (used by analog part)
16 | -- 1st Local Freq.(Fl ): 96*16*Fco = 1571.328 MHz (used by analog part)
17 | -- Sampling Freq.(Fs ): 16*Fco = 16.368 MHz, dt = 1/Fs, 16,368 samples/ms
18 | -- Intermediate Freq.(IF ): 4*Fco = 4.092 MHz, Fc - Fl
19 |
20 | -- Doppler Shift: Max +-10kHz/s, +-200Hz/20ms
21 |
22 | package gpsif_pack is
23 |
24 | constant GPSIF_TARGET_BUS_WIDTH : natural := 32;
25 |
26 | constant GPSIF_NC_BITS : natural := 3;
27 | constant GPSIF_NC_MAX : natural := 6;
28 | constant GPSIF_ND_MAX : natural := 31;
29 | constant GPSIF_RD_MAX : natural := 7; -- fixed to 7 now
30 | constant GPSIF_RW_MAX : natural := (GPSIF_ND_MAX+1)*(GPSIF_RD_MAX+1)-1;
31 | constant GPSIF_WA_MAX : natural := (GPSIF_RW_MAX+1)/8-1;
32 | constant GPSIF_CA_BITS : natural := 10;
33 | constant GPSIF_SFT_RNG : natural := 2**(GPSIF_CA_BITS+4);
34 |
35 | function itov(X, N : integer) return std_logic_vector;
36 | function vtoi(X : std_logic_vector) return integer;
37 | function vtoui(X : std_logic_vector) return integer;
38 | function to_bit(b : boolean) return std_logic;
39 |
40 | --- sincos -------------------------------------------------------------------
41 | constant GPSIF_ANGLE_BITS : natural :=30; -- More than 1 rotation can be discarded.
42 | constant GPSIF_ANGLE_INDX : natural := 6; -- scaled by 2**ANGLE_INDX/2PI (PI=>32, range is 0 to 63)
43 | constant GPSIF_SINCOS_MAX : natural := 5; -- scaled by 2**(SINCOSBITS-1) ( 1=>32, range is 0 to 32)
44 | constant GPSIF_CRRMIX_MAX : natural := GPSIF_SINCOS_MAX+ 2; -- (-32*3 to 32*3) to signed here
45 | constant GPSIF_SUMREG_MAX : natural := GPSIF_CRRMIX_MAX+ 3; -- (-32*3*8 to 32*3*8)
46 | constant GPSIF_ACMREG_MAX : natural := GPSIF_SUMREG_MAX+11; -- 1ms*16*1023samples
47 |
48 | subtype gpsif_angle_reg_t is std_logic_vector(GPSIF_ANGLE_BITS-1 downto 0);
49 | subtype gpsif_angle_t is ufixed(GPSIF_ANGLE_BITS-1 downto 0);
50 | subtype gpsif_angle_a_t is integer range 0 to GPSIF_NC_MAX;
51 | subtype gpsif_carrmix_t is integer range -(2**GPSIF_CRRMIX_MAX) to 2**GPSIF_CRRMIX_MAX; -- -96 to 96
52 |
53 | type gpsif_carrmix_o_t is record
54 | i,q : gpsif_carrmix_t; -- -96 to 96 (32*3 = 96, X"A0" to X"60")
55 | end record;
56 |
57 | type gpsif_carrmix_i_t is record
58 | angle : ufixed(GPSIF_ANGLE_INDX-1 downto 0);
59 | d : std_logic_vector( 1 downto 0); -- 00: 1, 01: 3, 10:-1, 11:-3
60 | end record;
61 |
62 | function gpsif_carrmix(a : gpsif_carrmix_i_t) return gpsif_carrmix_o_t;
63 | function gpsif_sin_6b (a : ufixed(3 downto 0)) return ufixed;
64 | function gpsif_mul (a : ufixed(1 downto 0); b : std_logic_vector(1 downto 0);
65 | s,c : ufixed(GPSIF_SINCOS_MAX downto 0)) return gpsif_carrmix_t;
66 |
67 | --- sumreg --------------------------------------------------------------------
68 | subtype gpsif_sum_d_t is integer range -(2**GPSIF_SUMREG_MAX) to 2**GPSIF_SUMREG_MAX; -- -768 to 768 (X"500" to X"300")
69 |
70 | type gpsif_sum_t is record
71 | i,q : gpsif_sum_d_t;
72 | end record;
73 |
74 | --- C/A code -------------------------------------------------------------------
75 | subtype gpsif_sftca_reg_t is std_logic_vector(GPSIF_CA_BITS*2-1 downto 0);
76 | subtype gpsif_sftca_a_t is integer range 0 to GPSIF_NC_MAX * 2 + 1;
77 | subtype gpsif_sft_t is ufixed(GPSIF_CA_BITS+3 downto 0);
78 | subtype gpsif_cnt1ms_t is ufixed(GPSIF_CA_BITS downto 0);
79 |
80 | --- acmreg --------------------------------------------------------------------
81 | constant GPSIF_REG_PER_CH : natural := 6;
82 | constant GPSIF_ACMREG_NUM : natural := (GPSIF_NC_MAX+1)*GPSIF_REG_PER_CH;
83 |
84 | subtype gpsif_acm_a_t is integer range 0 to GPSIF_ACMREG_NUM/2 -1;
85 | subtype gpsif_acm_d_t is integer range -(2**GPSIF_ACMREG_MAX) to 2**GPSIF_ACMREG_MAX-1;
86 | subtype gpsif_acm_reg_t is std_logic_vector (GPSIF_ACMREG_MAX downto 0);
87 |
88 | --- regfile --------------------------------------------------------------------
89 | type gpsif_regin_angle_t is record
90 | wd : gpsif_angle_reg_t;
91 | we : std_logic;
92 | a : gpsif_angle_a_t;
93 | end record;
94 |
95 | type gpsif_regin_sftca_t is record
96 | wd : gpsif_sftca_reg_t;
97 | we : std_logic;
98 | wa : gpsif_sftca_a_t;
99 | ra : gpsif_sftca_a_t;
100 | end record;
101 |
102 | type gpsif_regin_acm_t is record
103 | a : gpsif_acm_a_t;
104 | wd : gpsif_acm_reg_t;
105 | we : std_logic;
106 | bs : std_logic;
107 | end record;
108 |
109 | type gpsif_regfile_i_t is record
110 | pnco : gpsif_regin_angle_t;
111 | angle : gpsif_regin_angle_t;
112 | sftca : gpsif_regin_sftca_t;
113 | sftca_obs : gpsif_regin_sftca_t;
114 | acm : gpsif_regin_acm_t;
115 | buf : gpsif_regin_acm_t;
116 | end record;
117 |
118 | type gpsif_regfile_o_t is record
119 | pnco : gpsif_angle_reg_t;
120 | angle : gpsif_angle_reg_t;
121 | sftca : gpsif_sftca_reg_t;
122 | sftca_obsv : gpsif_sftca_reg_t;
123 | acm : gpsif_acm_reg_t;
124 | buf : gpsif_acm_reg_t;
125 | end record;
126 |
127 | component gpsif_regfile is port (
128 | clk : in std_logic;
129 | rst : in std_logic;
130 | bi : in bist_scan_t;
131 | bo : out bist_scan_t;
132 | a : in gpsif_regfile_i_t;
133 | y : out gpsif_regfile_o_t);
134 | end component;
135 |
136 | --- gpsif --------------------------------------------------------------------
137 | subtype gpsif_rw_t is integer range 0 to GPSIF_RW_MAX;
138 | subtype gpsif_wa_t is integer range 0 to GPSIF_WA_MAX;
139 |
140 | subtype gpsif_buf_rw_t is integer range 0 to 31;
141 | subtype gpsif_buf_wa_t is integer range 0 to 3;
142 | subtype gpsif_int_t is std_logic_vector(3 downto 0);
143 |
144 | type gpsif_cntl_t is record
145 | vld : std_logic;
146 | ovr : std_logic;
147 | bndry : boolean;
148 | err : boolean;
149 | lst : boolean;
150 | end record;
151 | type gpsif_o_t is record
152 | ra : gpsif_rw_t;
153 | sr : std_logic_vector(21 downto 0);
154 | cntl : gpsif_cntl_t;
155 | odd : boolean;
156 | rst : boolean;
157 | int_en : gpsif_int_t;
158 | end record;
159 |
160 | type gpsif_buf_ct_t is record
161 | ra : gpsif_buf_rw_t;
162 | inittm : std_logic;
163 | blsp1bit : std_logic;
164 | blsp2bit : std_logic;
165 | end record;
166 | type gpsif_time_t is record
167 | seq : std_logic_vector(7 downto 0);
168 | nsec : unsigned(23 downto 0);
169 | setnsec : std_logic;
170 | mscnt : std_logic;
171 | d : std_logic_vector(1 downto 0);
172 | wa : gpsif_wa_t;
173 | end record;
174 |
175 | -- sft & pnco update command format
176 | -- 31 : write dma channel & sft value
177 | -- 30-29 : sft value update type ( NOP, INC, PLS, MNS )
178 | -- 28 : pnco value inc. or not
179 | -- 27 : sft inc. code set or not
180 | -- 26-24 : sft inc. code (not a value itself)
181 | -- 23 : pnco inc. code set or not
182 | -- 22-20 : pnco inc. code (not a value itself)
183 | -- 19-14 : dma channel
184 | -- 13- 0 : sft
185 |
186 | subtype gpsif_sft_fld_t is std_logic_vector(30 downto 29);
187 | subtype gpsif_sft_inc_t is std_logic_vector(26 downto 24);
188 | subtype gpsif_pncoinc_t is std_logic_vector(22 downto 20);
189 |
190 | type gpsif_src_t is ( IO_PIN, CPU_BUS, BITL_BUS1, BITL_BUS2 );
191 | type gpsif_sft_typ_t is ( NOP, pad, SKP, AGN );
192 | type gpsif_sft_chg_t is ( NOP, INC, PLS, MNS );
193 | -- Channel mode encoding
194 | -- (2): TRK or not
195 | -- (1): VLD ODD, IDL or ACQ
196 | -- (0): VLD EVN
197 | -- 00-: IDL, 01-: ACQ, 100: TRK & not VLD, 101: TRK & VLD EVN, 110: TRK & VLD ODD, 111: TRK & VLD both (fail to read)
198 | type gpsif_st_t is record
199 | mode : std_logic_vector(2 downto 0);
200 | run : boolean;
201 | pnco : boolean; -- pnco increment by this.inc
202 | sft : gpsif_sft_chg_t;
203 | end record;
204 | type gpsif_sft_st_t is record
205 | chg : gpsif_sft_chg_t;
206 | typ : gpsif_sft_typ_t;
207 | ext : boolean;
208 | end record;
209 | type gpsif_ch_st_t is array (0 to GPSIF_NC_MAX) of gpsif_st_t;
210 | type gpsif_inc_t is record
211 | sft : std_logic_vector(2 downto 0);
212 | pnco : std_logic_vector(2 downto 0);
213 | end record;
214 | subtype gpsif_ch_t is std_logic_vector(GPSIF_NC_BITS-1 downto 0);
215 | constant GPSIF_NC_END : gpsif_ch_t := (others => '0');
216 | constant DBG_2MS_MAX : natural := 2**12 -1;
217 | subtype gpsif_dbg2ms_t is integer range 0 to DBG_2MS_MAX;
218 | type gpsif_dbg_st_t is ( DBG_IDL, DBG_RDY, DBG_RUN );
219 |
220 | type gpsif_reg_t is record
221 | -- config
222 | src : gpsif_src_t;
223 | src_bls : std_logic; -- 0:2bits/spl 1:1bit/spl
224 | inc : gpsif_inc_t;
225 | int_en : gpsif_int_t;
226 | -- state
227 | sft : gpsif_sft_st_t;
228 | st : gpsif_ch_st_t;
229 | -- delayed info.
230 | ready : boolean; -- input data is ready (scope data is stable)
231 | bndry : boolean; -- at 1ms boundary of carier mix channel
232 | even : boolean; -- 1st half of 16 cycles
233 | acm_lst : boolean; -- at 1ms boundary of accumulating channel
234 | acm_en : boolean; -- enable accumulation
235 | scp_chg : boolean; -- ND scope is changed by SHIFT change
236 | rst_en : boolean; -- SW reset enable
237 | -- counters
238 | ch : gpsif_ch_t;
239 | rd : integer range 0 to GPSIF_RD_MAX;
240 | nd : integer range 0 to GPSIF_ND_MAX;
241 | cnt1ms : gpsif_cnt1ms_t;
242 | odd_ms : integer range 0 to 1; -- even/odd ms
243 | -- latched values
244 | sum : gpsif_sum_t;
245 | add : gpsif_sum_t;
246 | code : std_logic_vector(2 downto 0);
247 | -- output
248 | dma_req : std_logic_vector(DMA_CH_NUM_LOG downto 0);
249 | ack : std_logic;
250 | ra : gpsif_rw_t;
251 | inittm : std_logic_vector(1 downto 0);
252 | -- for debug
253 | dbg_st : gpsif_dbg_st_t;
254 | dbg_strt : integer range 0 to 2**24 -1;
255 | dbg_a : integer range 0 to 255;
256 | dbg2ms : gpsif_dbg2ms_t;
257 | end record;
258 |
259 | constant GPSIF_REG_RESET : gpsif_reg_t := (
260 | src => IO_PIN, src_bls => '0',
261 | inc => (others => (others => '0')), int_en => (others => '0'),
262 | st => (others => (mode => (others => '0'), sft => NOP, pnco => false, run => false)),
263 | sft => (chg => NOP, typ => NOP, ext => false),
264 | ready => false, bndry => false, even => false, acm_lst => false, acm_en => false,
265 | scp_chg => false, rst_en => false,
266 | ch => GPSIF_NC_END,
267 | rd => GPSIF_RD_MAX,
268 | nd => GPSIF_ND_MAX,
269 | cnt1ms => (1 => '0', others => '1'), -- 2045 = 7fd
270 | odd_ms => 1, -- start from all 1
271 | sum => (others => 0),
272 | add => (others => 0),
273 | code => (others => '0'),
274 | dma_req => (others => '0'),
275 | ack => '0',
276 | ra => GPSIF_RW_MAX,
277 | inittm => (others => '0'),
278 | dbg_st => DBG_IDL, dbg_strt => 0, dbg_a => 0, dbg2ms => DBG_2MS_MAX );
279 |
280 | type gpsif_i_t is record
281 | d : std_logic_vector(1 downto 0);
282 | wa : gpsif_wa_t;
283 | end record;
284 | type gpsif_tgt_i_t is record
285 | en,wr: std_logic;
286 | a : std_logic_vector( 9 downto 2);
287 | d : std_logic_vector(31 downto 0);
288 | end record;
289 | type gpsif_tgt_reg_t is record -- for slower bus_clk than clk
290 | wr: std_logic;
291 | a : std_logic_vector( 9 downto 2);
292 | d : std_logic_vector(31 downto 0);
293 | end record;
294 | type gpsif_buf_i_t is record
295 | d : std_logic_vector(1 downto 0);
296 | wa : gpsif_buf_wa_t;
297 | end record;
298 |
299 | type gpsif_buf_t is array (0 to 31) of std_logic_vector(1 downto 0);
300 |
301 | type gpsif_time_rt_t is record
302 | nsec : unsigned (23 downto 0);
303 | nsec_cap : unsigned (23 downto 0);
304 | round_s : integer range 0 to 20;
305 | round_l : integer range 0 to 2386;
306 | pps_dly : std_logic_vector (3 downto 0);
307 | inittm : std_logic;
308 | cnt1ms_g : gpsif_cnt1ms_t;
309 | cnt1msup_g : std_logic;
310 | end record;
311 | type gpsif_buf_reg_t is record
312 | d : gpsif_buf_t;
313 | wa : gpsif_buf_rw_t;
314 | end record;
315 | type gpsif_time_reg_t is record
316 | rt : gpsif_time_rt_t;
317 | end record;
318 | type gpsif_buf_sync_t is record
319 | wa_dly : gpsif_buf_wa_t;
320 | wa_out : gpsif_buf_wa_t;
321 | end record;
322 | type gpsif_time_sync_t is record
323 | ppss_dly : std_logic_vector (2 downto 0);
324 | nsec : unsigned (23 downto 0);
325 | cnt1msup_g : std_logic;
326 | setnsec : std_logic;
327 | packetwd : std_logic_vector (15 downto 0);
328 | packetwa : integer range 0 to 31;
329 | packetwe : std_logic;
330 | wa_comm : integer range 0 to 64; -- 2bit sample max 32, 1 bit sample max 64
331 | wa_commwait : integer range 0 to 63;
332 | inittmc1 : std_logic_vector(1 downto 0);
333 | inittmc2 : integer range 0 to 64;
334 | inittmc3 : std_logic;
335 | pon_state : std_logic;
336 | rt : gpsif_time_rt_t;
337 | end record;
338 |
339 | constant gpsif_time_rt_RESET : gpsif_time_rt_t := (nsec => (others => '0'),
340 | nsec_cap => (others => '0'), round_s => 0, round_l => 0, pps_dly => "0000",
341 | inittm => '0', cnt1ms_g => (others => '0'), cnt1msup_g => '0' );
342 | constant gpsif_buf_reg_RESET : gpsif_buf_reg_t := (d => (others => (others => '0')), wa => 0 );
343 | constant gpsif_buf_sync_RESET : gpsif_buf_sync_t := (wa_dly => 0, wa_out => 0);
344 | constant gpsif_time_reg_RESET : gpsif_time_reg_t := (rt => gpsif_time_rt_RESET );
345 | constant gpsif_time_sync_RESET : gpsif_time_sync_t := (ppss_dly => "000",
346 | nsec => (others => '0'), cnt1msup_g => '0', setnsec => '0',
347 | packetwd => x"0000", packetwa => 31, packetwe => '1',
348 | wa_comm => 64, wa_commwait => 0 ,
349 | inittmc1 => "00", inittmc2 => 0, inittmc3 => '0', pon_state => '1',
350 | rt => gpsif_time_rt_RESET );
351 |
352 | component gpsif_buf is port (
353 | clk : in std_logic;
354 | rst : in std_logic;
355 | -- port
356 | gps_clk : in std_logic;
357 | gps_d : in std_logic_vector(1 downto 0);
358 | a : in gpsif_buf_ct_t;
359 | y : out gpsif_buf_i_t;
360 | waf : out gpsif_buf_rw_t );
361 | end component;
362 |
363 | component gpsif_time is port (
364 | clk : in std_logic;
365 | rst : in std_logic;
366 | -- port
367 | gps_clk : in std_logic;
368 | gps_d : in std_logic_vector(1 downto 0);
369 | a : in gpsif_buf_ct_t;
370 | waf : in gpsif_buf_rw_t;
371 | ppsdds : in std_logic;
372 | blgps : in blgps_t;
373 | y : out gpsif_time_t );
374 | end component;
375 |
376 | component gpsif is
377 | generic ( GPSIF_NC : integer := 7;
378 | ANGLE_INI_OLD : boolean := false );
379 | port (
380 | clk : in std_logic;
381 | rst : in std_logic;
382 | bi : in bist_scan_t;
383 | bo : out bist_scan_t;
384 | ring_i : in rbus_9b; -- to monitor ring bus
385 | ring_o : in rbus_9b; -- to monitor ring bus
386 | tgt_o : out cpu_data_i_t;
387 | tgt_i : in gpsif_tgt_i_t;
388 | dev_o : out rbus_dev_o_t;
389 | dev_i : in rbus_dev_i_t;
390 | buf_io : in gpsif_buf_i_t;
391 | time_i : in gpsif_time_t;
392 | ra_io : out gpsif_buf_ct_t;
393 | buf_bus : in gpsif_i_t;
394 | gpsif_o : out gpsif_o_t;
395 | dma : out dma_req_t );
396 | end component;
397 |
398 | component gpsif_db is port (
399 | clk : in std_logic;
400 | rst : in std_logic;
401 | bi : in bist_scan_t;
402 | bo : out bist_scan_t;
403 | db_i : in cpu_data_o_t;
404 | db_o : out cpu_data_i_t;
405 | tgt_o : in cpu_data_i_t;
406 | tgt_i : out gpsif_tgt_i_t;
407 | time_i : in gpsif_time_t;
408 | intrpt : out std_logic;
409 | a : in gpsif_o_t;
410 | y : out gpsif_i_t);
411 | end component;
412 |
413 | end package;
414 |
415 | package body gpsif_pack is
416 |
417 | function itov(X, N : integer) return std_logic_vector is
418 | begin
419 | return std_logic_vector(to_signed(X,N));
420 | end itov;
421 |
422 | function vtoi(X : std_logic_vector) return integer is
423 | variable v : std_logic_vector(X'high - X'low downto 0) := X;
424 | begin
425 | return to_integer(signed(v));
426 | end vtoi;
427 |
428 | function vtoui(X : std_logic_vector) return integer is
429 | variable v : std_logic_vector(X'high - X'low downto 0) := X;
430 | begin
431 | return to_integer(unsigned(v));
432 | end vtoui;
433 | function to_bit(b : boolean) return std_logic is
434 | begin
435 | if b then return '1';
436 | else return '0'; end if;
437 | end to_bit;
438 |
439 | function gpsif_carrmix(a : gpsif_carrmix_i_t) return gpsif_carrmix_o_t is
440 | alias a_q : ufixed(1 downto 0) is a.angle(a.angle'high downto a.angle'high-1);
441 | variable ca_q : ufixed(2 downto 0);
442 | alias a_1 : ufixed(a.angle'high-2 downto 0) is a.angle(a.angle'high-2 downto 0); -- 1st quadrant angle
443 | variable ca_1 : ufixed(a.angle'high downto 0);
444 | variable y : gpsif_carrmix_o_t;
445 | variable s, c : ufixed(GPSIF_SINCOS_MAX downto 0);
446 | begin
447 | ca_q := 1 + a_q;
448 | ca_1 := "00" & a_1;
449 | ca_1 := 2**a_1'length - ca_1(a_1'length downto 0);
450 |
451 | s := gpsif_sin_6b( a_1); -- sin of 1st quadrant
452 | c := gpsif_sin_6b(ca_1(a_1'range)); -- cos(a_1) = sin(scaled(PI/2) - a_1) = sin(ca_1)
453 | if ca_1(ca_1'high-1)='1' then c := "100000"; -- to make cos(0) := 32
454 | end if;
455 | y.i := gpsif_mul( a_q, a.d, s, c); -- c is sin of 2nd quadrant
456 | y.q := gpsif_mul(ca_q(a_q'range), a.d, s, c);
457 | return y;
458 | end gpsif_carrmix;
459 |
460 | function gpsif_sin_6b(a : ufixed(3 downto 0)) return ufixed is
461 |
462 | -- special to 6b output & 4b angle of 1st quadrant
463 | -- angle : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
464 | -- sin : 0 3 6 9 12 15 18 21 23 25 27 29 30 31 32 32
465 | -- cos : 0 32 32 31 30 29 27 25 23 21 18 15 12 9 6 3 : sin(16 - angle), cos(0) must be corrected to 32 after the function.
466 |
467 | variable x1,x2 : ufixed(4 downto 0);
468 | variable y : ufixed(5 downto 0);
469 | begin
470 | if a(3)='0' then x1 := a & '0'; x2 := "0" & a; -- 2x + x = 3x
471 | elsif a(2)='0' then x1 := a & '0'; x2 := "00111"; -- 2x + 7
472 | elsif a(1)='0' then x1 := "10010"; x2 := "0" & a; -- 18 + x
473 | else x1 := "10010"; x2 := "01110"; -- 18 +14 = 32
474 | end if;
475 | y := x1 + x2;
476 | return y;
477 | end gpsif_sin_6b;
478 |
479 |
480 | function gpsif_mul(a : ufixed(1 downto 0); b : std_logic_vector(1 downto 0);
481 | s, c : ufixed(GPSIF_SINCOS_MAX downto 0)) return gpsif_carrmix_t is
482 |
483 | -- quadrant I II III IV
484 | -- sin s c -s -c : s is sin of 1st quadrant
485 | -- cos c -s -c s : c is cos of 1st quadrant
486 |
487 | variable sc,sc4,y : ufixed(GPSIF_CRRMIX_MAX downto 0);
488 | variable ci,dummy : std_logic;
489 | begin
490 | ci := '1'; -- for other than *(+1) case
491 | case a(0) is
492 | when '0' => sc := ("00" & s); sc4 := (s & "00"); -- 1st, 3rd quadrant
493 | when '1' => sc := ("00" & c); sc4 := (c & "00"); -- 2nd, 4th quadrant
494 | when others =>
495 | end case;
496 | case (a(1) xor b(1)) is
497 | when '0' => -- same sign
498 | case b(0) is
499 | when '0' => ci := '0'; sc4 := (others => '0'); -- *(+1)
500 | when '1' => sc := not sc; -- *(+3) ( 3 = 4 - 1)
501 | when others =>
502 | end case;
503 | when '1' => -- different sign
504 | case b(0) is
505 | when '0' => sc := not sc; sc4 := (others => '0'); -- *(-1)
506 | when '1' => sc4 := not sc4; -- *(-3) (-3 = -4 + 1)
507 | when others =>
508 | end case;
509 | when others =>
510 | end case;
511 | add_carry(sc, sc4, ci, y, dummy);
512 | return vtoi(to_slv(y));
513 | end gpsif_mul;
514 |
515 | end gpsif_pack;
516 |
--------------------------------------------------------------------------------
/gpsif_reg.vhm:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use work.rf_pack.all;
4 | use work.bist_pack.all;
5 | use work.gpsif_pack.all;
6 |
7 | entity gpsif_regfile is port (
8 | clk : in std_logic;
9 | rst : in std_logic;
10 | bi : in bist_scan_t;
11 | bo : out bist_scan_t;
12 | a : in gpsif_regfile_i_t;
13 | y : out gpsif_regfile_o_t);
14 | end gpsif_regfile;
15 |
16 | architecture beh of gpsif_regfile is
17 |
18 | signal acm_d0 : gpsif_acm_reg_t;
19 | signal acm_d1 : gpsif_acm_reg_t;
20 | signal we0a : std_logic;
21 | signal we1a : std_logic;
22 | signal bs0 : bist_scan_t;
23 | signal bs1 : bist_scan_t;
24 | signal bs2 : bist_scan_t;
25 | signal bs3 : bist_scan_t;
26 | signal bs4 : bist_scan_t;
27 | signal bs5 : bist_scan_t;
28 | signal bs6 : bist_scan_t;
29 | signal buf_d0 : gpsif_acm_reg_t;
30 | signal buf_d1 : gpsif_acm_reg_t;
31 | signal we0b : std_logic;
32 | signal we1b : std_logic;
33 |
34 | begin
35 | sftca_bank : bist_RF1
36 | generic map ( WIDTH => GPSIF_CA_BITS * 2, DEPTH => (GPSIF_NC_MAX + 1) * 2 )
37 | port map
38 | (clk => clk,
39 | rst => rst,
40 | bi => bi,
41 | bo => bs1,
42 | D => a.sftca.wd,
43 | WA => a.sftca.wa,
44 | WE => a.sftca.we,
45 | RA0 => a.sftca.ra,
46 | Q0 => y.sftca);
47 |
48 | -- observe sftca ----------
49 | sftca_observe : bist_RF1
50 | generic map ( WIDTH => GPSIF_CA_BITS * 2, DEPTH => (GPSIF_NC_MAX + 1) * 2 )
51 | port map
52 | (clk => clk,
53 | rst => rst,
54 | bi => bi,
55 | bo => open,
56 | D => a.sftca.wd,
57 | WA => a.sftca.wa,
58 | WE => a.sftca.we,
59 | RA0 => a.sftca_obs.ra,
60 | Q0 => y.sftca_obsv);
61 |
62 | pnco_bank : bist_RF1
63 | generic map ( WIDTH => GPSIF_ANGLE_BITS, DEPTH => GPSIF_NC_MAX + 1 )
64 | port map
65 | (clk => clk,
66 | rst => rst,
67 | bi => bs1,
68 | bo => bs2,
69 | D => a.pnco.wd,
70 | WA => a.pnco.a,
71 | WE => a.pnco.we,
72 | RA0 => a.angle.a,
73 | Q0 => y.pnco);
74 |
75 | angle_bank : bist_RF1
76 | generic map ( WIDTH => GPSIF_ANGLE_BITS, DEPTH => GPSIF_NC_MAX + 1 )
77 | port map
78 | (clk => clk,
79 | rst => rst,
80 | bi => bs2,
81 | bo => bs3,
82 | D => a.angle.wd,
83 | WA => a.angle.a,
84 | WE => a.angle.we,
85 | RA0 => a.angle.a,
86 | Q0 => y.angle);
87 |
88 | we0a <= a.acm.we when (a.acm.bs = '0') else '0';
89 | we1a <= a.acm.we when (a.acm.bs = '1') else '0';
90 | we0b <= a.buf.we and a.acm.we when (a.acm.bs = '0') else '0';
91 | we1b <= a.buf.we and a.acm.we when (a.acm.bs = '1') else '0';
92 |
93 | acm_bank0 : bist_RF1
94 | generic map ( WIDTH => GPSIF_ACMREG_MAX+1, DEPTH => GPSIF_ACMREG_NUM/2 )
95 | port map
96 | (clk => clk,
97 | rst => rst,
98 | bi => bs3,
99 | bo => bs4,
100 | D => a.acm.wd,
101 | WA => a.acm.a,
102 | WE => we0a,
103 | RA0 => a.acm.a,
104 | Q0 => acm_d0);
105 |
106 | acm_bank1 : bist_RF1
107 | generic map ( WIDTH => GPSIF_ACMREG_MAX+1, DEPTH => GPSIF_ACMREG_NUM/2 )
108 | port map
109 | (clk => clk,
110 | rst => rst,
111 | bi => bs4,
112 | bo => bs5,
113 | D => a.acm.wd,
114 | WA => a.acm.a,
115 | WE => we1a,
116 | RA0 => a.acm.a,
117 | Q0 => acm_d1);
118 |
119 | buf_bank0 : bist_RF1
120 | generic map ( WIDTH => GPSIF_ACMREG_MAX+1, DEPTH => GPSIF_ACMREG_NUM/2 )
121 | port map
122 | (clk => clk,
123 | rst => rst,
124 | bi => bs5,
125 | bo => bs6,
126 | D => a.buf.wd,
127 | WA => a.acm.a,
128 | WE => we0b,
129 | RA0 => a.buf.a,
130 | Q0 => buf_d0);
131 |
132 | buf_bank1 : bist_RF1
133 | generic map ( WIDTH => GPSIF_ACMREG_MAX+1, DEPTH => GPSIF_ACMREG_NUM/2 )
134 | port map
135 | (clk => clk,
136 | rst => rst,
137 | bi => bs6,
138 | bo => bo,
139 | D => a.buf.wd,
140 | WA => a.acm.a,
141 | WE => we1b,
142 | RA0 => a.buf.a,
143 | Q0 => buf_d1);
144 |
145 | -- connect outputs
146 | y.acm <= acm_d0 when (a.acm.bs = '0') else
147 | acm_d1 ;
148 | y.buf <= buf_d0 when (a.buf.bs = '0') else
149 | buf_d1 ;
150 | end beh;
151 |
--------------------------------------------------------------------------------
/gpsif_sub_pkg.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.std_logic_unsigned.all;
4 | use ieee.numeric_std.all;
5 |
6 | use work.fixed_pkg.all;
7 | use work.rf_pack.all;
8 | use work.bist_pack.all;
9 | use work.cpu2j0_pack.all;
10 | use work.ring_bus_pack.all;
11 | use work.rbus_pack.all;
12 |
13 | package gpsif_sub_pack is
14 |
15 | -- Copy from dma_pkg.vhd, and change name to avoid conflict
16 | -- Direct reference by "use work.dma_pack.all;" causes error.
17 | constant DMA_CH_NUM_LOG : natural := 6;
18 | type dma_req_t is record
19 | req : std_logic_vector(DMA_CH_NUM_LOG downto 0);
20 | end record;
21 |
22 | constant NULL_DMA_REQ : dma_req_t := ( req => (others => '0') );
23 |
24 | type blgps_t is record
25 | en : std_logic;
26 | a : std_logic_vector( 5 downto 0);
27 | d : std_logic_vector( 7 downto 0);
28 | tick : std_logic;
29 | end record;
30 |
31 | constant NULL_BLGPS : blgps_t := ( en => '0', a => (others => '0'),
32 | d => x"00", tick => '0' );
33 |
34 | end package;
35 |
36 | package body gpsif_sub_pack is
37 |
38 | end gpsif_sub_pack;
39 |
--------------------------------------------------------------------------------
/gpsif_time.vhm:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use work.fixed_pkg.all;
4 | use ieee.numeric_std.all;
5 | use work.gpsif_pack.all;
6 | use work.gpsif_sub_pack.all;
7 | use work.rf_pack.all;
8 | use work.bist_pack.all;
9 |
10 | entity gpsif_time is port (
11 | clk : in std_logic;
12 | rst : in std_logic;
13 | -- port
14 | gps_clk : in std_logic;
15 | gps_d : in std_logic_vector(1 downto 0);
16 | a : in gpsif_buf_ct_t;
17 | waf : in gpsif_buf_rw_t;
18 | blgps : in blgps_t;
19 | ppsdds : in std_logic;
20 | y : out gpsif_time_t );
21 | end gpsif_time;
22 |
23 | architecture beh of gpsif_time is
24 | register variable this : gpsif_time_reg_t reset := gpsif_time_reg_RESET;
25 | register variable this_sync : gpsif_time_sync_t reset := gpsif_time_sync_RESET;
26 | signal a_ra_mod_8 : integer range 0 to 7 := 0;
27 | signal a_ra_mod_16 : integer range 0 to 15 := 0;
28 | signal regf_rd : std_logic_vector(15 downto 0);
29 | signal regf_ra : integer range 0 to 31 := 0;
30 |
31 | begin
32 | pg : process(this,this_sync,gps_d,a,waf,ppsdds)
33 | variable nsec_upcond_60 : boolean;
34 | variable nsec_upcond_61 : boolean;
35 | variable nsec_upcond_62 : boolean;
36 | variable incr_cnt1ms : ufixed(gpsif_cnt1ms_t'high+1 downto 0);
37 | register this when gps_clk = '1' and gps_clk'event reset sync when rst = '1';
38 | begin
39 | if(this.rt.pps_dly(2) /= this.rt.pps_dly(1)) then
40 | this.rt.nsec_cap := this.rt.nsec;
41 | end if;
42 | this.rt.pps_dly := this.rt.pps_dly(2 downto 0) & ppsdds;
43 |
44 | nsec_upcond_60 := false;
45 | nsec_upcond_61 := false;
46 | nsec_upcond_62 := false;
47 | if (this.rt.round_s = 0) or (this.rt.round_s = 10) then
48 | if(this.rt.round_l = 1) then
49 | nsec_upcond_61 := true;
50 | else nsec_upcond_62 := true; end if;
51 | else
52 | if(this.rt.round_l = 1) then
53 | nsec_upcond_60 := true;
54 | else nsec_upcond_61 := true; end if;
55 | end if;
56 |
57 | -- reset command from clk_sys domain ,
58 | -- reset value = 61.09481 * (34 * 8 + 4) = 16862.217 [ns]
59 | -- clk_sys side 32 x gps_clk, gps_clk side 34 x gps_clk
60 |
61 | if(this.rt.inittm = '1') and ((waf mod 8) = 3) then
62 | this.rt.nsec := to_unsigned(16862, 24);
63 | -- reset gps_is2 sys_clk engine
64 | elsif(waf mod 8 = 7) and
65 | (std_logic_vector(this.rt.cnt1ms_g) = "111" & x"fd") then
66 | this.rt.nsec := (others => '0');
67 | -- 1ms boundary
68 | elsif(nsec_upcond_62) then this.rt.nsec := this.rt.nsec + 62;
69 | elsif(nsec_upcond_61) then this.rt.nsec := this.rt.nsec + 61;
70 | else this.rt.nsec := this.rt.nsec + 60;
71 | end if;
72 |
73 | case this.rt.round_s is
74 | when 20 => this.rt.round_s := 0;
75 | when others => this.rt.round_s := this.rt.round_s + 1;
76 | end case;
77 | case this.rt.round_l is
78 | when 2386 => this.rt.round_l := 0;
79 | when others => this.rt.round_l := this.rt.round_l + 1;
80 | end case;
81 | -- math -- (61 + 2/21 - 1/2387) = (1e6 / 16368)
82 | -- -- hint : 16368 = (16 * 3 * 341)
83 |
84 | -- 1023 counter (nsec count and 1ms count = dual counter) --
85 | if(this.rt.inittm = '1') and ((waf mod 8) = 3) then
86 | this.rt.cnt1ms_g := (5 => '1', 1 => '1', others => '0');
87 | -- | |
88 | -- memo 2^5 + 2^1 = hex 22 (dec 34)
89 | elsif(waf mod 8 = 7) then
90 | if(std_logic_vector(this.rt.cnt1ms_g) = "111" & x"fd") then
91 | this.rt.cnt1ms_g := (others => '0');
92 | this.rt.cnt1msup_g := not this.rt.cnt1msup_g;
93 | else incr_cnt1ms := this.rt.cnt1ms_g + 1;
94 | this.rt.cnt1ms_g := incr_cnt1ms(gpsif_cnt1ms_t'high downto 0);
95 | end if;
96 | end if;
97 | this.rt.inittm := a.inittm;
98 | end process;
99 |
100 | r : bist_RF1
101 | generic map ( WIDTH => 16, DEPTH => 32 )
102 | port map
103 | (clk => clk,
104 | rst => rst,
105 | bi => ( ctrl => '0', d => '0', en => '0', bist => '0', cmd => "00"),
106 | bo => open,
107 | D => this_sync'register.packetwd,
108 | WA => this_sync'register.packetwa,
109 | WE => this_sync'register.packetwe,
110 | RA0 => regf_ra,
111 | Q0 => regf_rd);
112 |
113 | a_ra_mod_8 <= a.ra mod 8;
114 | a_ra_mod_16 <= a.ra mod 16;
115 |
116 | ps : process(this_sync,this, a, blgps)
117 | variable nsec_upcond_60 : boolean;
118 | variable nsec_upcond_61 : boolean;
119 | variable nsec_upcond_62 : boolean;
120 | variable incr_cnt1ms : ufixed(gpsif_cnt1ms_t'high+1 downto 0);
121 | variable wa_comm_cntup : std_logic;
122 | register this_sync when clk = '1' and clk'event reset sync when rst = '1';
123 | begin
124 |
125 | if(a.blsp1bit = '0') and (a.blsp2bit = '0') then -- pin direct case
126 | if(this_sync.ppss_dly(1) /=
127 | this_sync.ppss_dly(2)) then
128 | this_sync.nsec := this'register.rt.nsec_cap;
129 | this_sync.cnt1msup_g := this'register.rt.cnt1msup_g;
130 | this_sync.setnsec := '1';
131 | else
132 | this_sync.setnsec := '0';
133 | end if;
134 | else -- <-> if{(a.blsp1bit = '1') or (a.blsp2bit = '1')}
135 | -- GPS over bitlink case
136 | if(blgps.en = '1') and (blgps.a = "000010") and
137 | (blgps.tick = '1') then
138 | this_sync.nsec := this_sync.rt.nsec;
139 | this_sync.cnt1msup_g := this_sync.rt.cnt1msup_g;
140 | this_sync.setnsec := '1';
141 | else
142 | this_sync.setnsec := '0';
143 | end if;
144 | end if;
145 |
146 | this_sync.ppss_dly :=
147 | this_sync.ppss_dly(1 downto 0) & this'register.rt.pps_dly(3);
148 |
149 | nsec_upcond_60 := false;
150 | nsec_upcond_61 := false;
151 | nsec_upcond_62 := false;
152 | if (this_sync.rt.round_s = 0) or (this_sync.rt.round_s = 10) then
153 | if(this_sync.rt.round_l = 1) then
154 | nsec_upcond_61 := true;
155 | else nsec_upcond_62 := true; end if;
156 | else
157 | if(this_sync.rt.round_l = 1) then
158 | nsec_upcond_60 := true;
159 | else nsec_upcond_61 := true; end if;
160 | end if;
161 |
162 | this_sync.packetwa := to_integer(unsigned(blgps.a(5 downto 1)));
163 |
164 | if(blgps.en = '1') then
165 | if (blgps.a(0) = '0') then
166 | this_sync.packetwd(15 downto 8) := blgps.d;
167 | else this_sync.packetwd( 7 downto 0) := blgps.d; end if;
168 | end if;
169 |
170 | if(blgps.en = '1') and (blgps.a(0) = '1') then
171 | this_sync.packetwe := '1';
172 | else this_sync.packetwe := '0';
173 | end if;
174 |
175 |
176 | -- regfile read address (from a.ra and this_sync.wa_comm)
177 | if ((((a.ra / 8) mod 4) = 1) and (this_sync.wa_comm mod 4 < 1)) or
178 | ((((a.ra / 8) mod 4) = 2) and (this_sync.wa_comm mod 4 < 2)) or
179 | ((((a.ra / 8) mod 4) = 3) and (this_sync.wa_comm mod 4 < 3)) then
180 | if (a.blsp1bit = '0') then
181 | regf_ra <= ((this_sync.wa_comm / 4) * 4 + (a.ra / 8) + 28) mod 32;
182 | else
183 | regf_ra <= ((this_sync.wa_comm / 4) * 2 + (a.ra / 16) + 30) mod 32;
184 | end if;
185 | else
186 | if (a.blsp1bit = '0') then
187 | regf_ra <= ((this_sync.wa_comm / 4) * 4 + (a.ra / 8) ) mod 32;
188 | else
189 | regf_ra <= ((this_sync.wa_comm / 4) * 2 + (a.ra / 16) ) mod 32;
190 | end if;
191 | end if;
192 |
193 | -- wa_comm state machine
194 | wa_comm_cntup := '0';
195 | if(blgps.en = '1') and (blgps.a = "000000") then
196 | this_sync.wa_comm := 0;
197 | this_sync.wa_commwait := 0;
198 | if(this_sync.pon_state = '1') then
199 | this_sync.pon_state := '0';
200 | else
201 | wa_comm_cntup := '1'; end if;
202 | elsif(this_sync.wa_commwait = 42) then
203 | -- gps over bitlink, magic number 5ch * 8cycl + other 2cyc = 42
204 | this_sync.wa_comm := this_sync.wa_comm + 1;
205 | this_sync.wa_commwait := 0;
206 | if((this_sync'register.wa_comm /= 31) and (a.blsp1bit = '0')) or
207 | ((this_sync'register.wa_comm /= 63) and (a.blsp1bit = '1')) then
208 | wa_comm_cntup := '1';
209 | end if;
210 | elsif( this_sync.wa_comm = 64) or
211 | ((this_sync.wa_comm = 32) and (a.blsp1bit = '0')) then
212 | -- no count up
213 | else -- update wait
214 | if(this_sync.wa_commwait = 63) then
215 | this_sync.wa_commwait := 0;
216 | else this_sync.wa_commwait := this_sync.wa_commwait + 1; end if;
217 | end if;
218 |
219 | if(a.inittm = '1') and (this_sync'register.wa_commwait = 39) then
220 | this_sync.inittmc1(0) := '1';
221 | this_sync.inittmc2 := this_sync'register.wa_comm;
222 | elsif(blgps.en = '1') and (blgps.a = "000000") then
223 | this_sync.inittmc1(1 downto 0) :=
224 | this_sync.inittmc1(0) & '0';
225 | end if;
226 |
227 | -- if(blgps.en = '1') and (blgps.a(0) = '0') then
228 | if(wa_comm_cntup = '1') then
229 |
230 | -- reset command from clk_sys domain ,
231 | -- reset value = 61.09481 * (35 * 8 + 0) = 17106.549 [ns]
232 | -- -> nearest 8ns x n -> 17104 [ns ] (2138 * 8)
233 |
234 | if(this_sync.inittmc3 = '1') then
235 | this_sync.rt.nsec := to_unsigned(17104, 24);
236 | -- reset gps_is2 sys_clk engine
237 | elsif(this_sync.rt.nsec > 999295) then
238 | -- dec999296 = 0xfcf80 -- 1ms boundary
239 | this_sync.rt.nsec := (others => '0');
240 | elsif(nsec_upcond_62) then
241 | this_sync.rt.nsec := this_sync.rt.nsec + 62 * 8;
242 | elsif(nsec_upcond_61) then
243 | this_sync.rt.nsec := this_sync.rt.nsec + 61 * 8;
244 | else this_sync.rt.nsec := this_sync.rt.nsec + 60 * 8;
245 | end if;
246 |
247 | -- 1023 counter (nsec count and 1ms count = dual counter) --
248 | if(this_sync.inittmc3 = '1') then
249 | this_sync.rt.cnt1ms_g := (5 => '1', 1 => '1', 0 => '1',
250 | others => '0');
251 | -- | |
252 | -- memo 2^5 + 2^1 + 2^0= hex 23 (dec 35)
253 | else
254 | if(std_logic_vector(this_sync.rt.cnt1ms_g) = "111" & x"fd") then
255 | this_sync.rt.cnt1ms_g := (others => '0');
256 | this_sync.rt.cnt1msup_g := not this_sync.rt.cnt1msup_g;
257 |
258 | else incr_cnt1ms := this_sync.rt.cnt1ms_g + 1;
259 | this_sync.rt.cnt1ms_g := incr_cnt1ms(gpsif_cnt1ms_t'high downto 0);
260 | end if;
261 | end if;
262 |
263 | case this_sync.rt.round_s is
264 | when 20 => this_sync.rt.round_s := 0;
265 | when others => this_sync.rt.round_s := this_sync.rt.round_s + 1;
266 | end case;
267 | case this_sync.rt.round_l is
268 | when 2386 => this_sync.rt.round_l := 0;
269 | when others => this_sync.rt.round_l := this_sync.rt.round_l + 1;
270 | end case;
271 | end if;
272 |
273 | if(this_sync'register.wa_commwait = 39) then
274 | this_sync.inittmc3 := a.inittm;
275 | end if;
276 |
277 | end process;
278 | -- connect outputs
279 | y.nsec <= this_sync'register.nsec;
280 | y.seq <= (others => '0');
281 | y.mscnt <= this_sync'register.cnt1msup_g;
282 | y.setnsec <= this_sync'register.setnsec;
283 | y.d <= regf_rd((15 - 2 * a_ra_mod_8) downto
284 | (14 - 2 * a_ra_mod_8))
285 | when (a.blsp1bit = '0') else
286 | (regf_rd(15 - a_ra_mod_16) & "0"); -- 1b form -> 2b form
287 | y.wa <= this_sync'register.wa_comm mod 4;
288 | end beh;
289 |
--------------------------------------------------------------------------------
/gpsif_top.vhd:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- Brief GPSIF Spec. Written on Aug. 23, 2017 by Fumio Arakawa
3 | --------------------------------------------------------------------------------
4 | --------- Address map (32b address, 4 byte stride for channel address) ---------
5 | -- abcc0000 : Base address on CPU bus
6 | -- abcc0000 + ch : C/A code shift, PNCO inc., DMA channel
7 | -- abcc0020 + ch : G2 shift & Acquisition mode, Channel activation
8 | -- abcc0040 + ch : PNCO
9 | -- abcc0060 : S/W reset
10 | -- abcc0100 +8*ch +N : Output buffer (N: 0-5 for EI,EQ,PI,PQ,LI,LQ)
11 | -- abcc0200 : GPSIF status
12 | -- abcc0204 : Input buffer from CPU bus
13 |
14 | -------------------------------- Bit assignment --------------------------------
15 | -- 1. S/W reset
16 | -- 31 : 0
17 | -- 8 : bitlink case sample bit mode
18 | -- 0: 2 bits/sample. 1: 1 bit sample
19 | -- 1- 0 : input mode (
20 | -- 00: from I/O port, 01: from CPU bus, 10: from bitlink
21 | -- (Currently, other bits are used to dump signals for debug on FPGA)
22 | -- 2. Channel Initialization
23 | -- 1. C/A code shift (direct, inc./plus/minus), PNCO inc., DMA channel
24 | -- 31 : direct write of C/A code shift & DMA channel (0: Enable, 1: Disable)
25 | -- 30-29 : C/A code shift update type ( NOP, INC, PLS, MNS )
26 | -- 28 : PNCO update (0: Disable, 1: Enable)
27 | -- 27 : shift inc. code set (0: Disable, 1: Enable)
28 | -- 26-24 : shift inc. code
29 | -- 000 : + 1 100 : + 4
30 | -- 001 : + 8 101 : -24
31 | -- 010 : +16 110 : -16
32 | -- 011 : +24 111 : - 8
33 | -- 23 : PNCO inc. code set (0: Disable, 1: Enable)
34 | -- 22-20 : PNCO inc. code
35 | -- 000 : 1 100 : 16
36 | -- 001 : 2 101 : 32
37 | -- 010 : 4 110 : 64
38 | -- 011 : 8 111 : 128
39 | -- 19-14 : DMA channel
40 | -- 13- 0 : C/A code shift (for direct write)
41 | -- 2. PNCO direct write
42 | -- 28- 0 : PNCO (28 bit signed number, HW ignores bit 31-30)
43 | -- 3. G2 shift & Acquisition mode
44 | -- 31 : Acquisition mode (0: Disable, 1: Enable)
45 | -- 9- 0 : G2 shift
46 | -- 4. GPSIF status register
47 | -- 29-16 : Channel status (0:IDL, 1:ACQ, 2:RDY, 3:VLD)
48 | -- 23-22 : #3
49 | -- 29-28 : #6 21-20 : #2
50 | -- 27-26 : #5 19-18 : #1
51 | -- 25-24 : #4 17-16 : #0
52 | -- 14- 8 : Channel is running or not (0:ready, 1:run)
53 | -- 11 : #3
54 | -- 14 : #6 10 : #2
55 | -- 13 : #5 9 : #1
56 | -- 12 : #4 8 : #0
57 | -- 0 : Input buffer status (0:BUSY, 1:FILL)
58 |
59 | -------------------------------- control by S/W --------------------------------
60 | -- 1. S/W reset
61 |
62 | -- S/W reset initializes GPSIF.
63 | -- - Input mode is specified by bit 31, and 0 & 1 correspond to from I/O port & CPU bus.
64 | -- - All of channels are set to IDL.
65 | -- - Input buffer is cleared by initializing read scope & write pointers.
66 | -- - Reset 1-ms counter that counts number of data of 1023*16 for 1 ms.
67 | -- (The counter consists of common higher 11-bit one that skips 1023*2 and 1023*2+1,
68 | -- and lower 3-bit one just to count 8 for each 8 data processing.)
69 |
70 | -- 2. Each Channel initialization and updates
71 |
72 | -- For Tracking
73 | -- 1) Direct write of C/A code shift of acquired satellite
74 | -- The value is the 1-ms counter value corresponding to the last data of the 1-ms period of the acquired satellite.
75 | -- 2) Direct write of PNCO of the acquired satellite
76 | -- 3) Write of G2 shift of the acquired satellite w/ disabling acquisition. The write makes the channel RDY.
77 | -- The initialized channel starts running after the higher 11-bits of the C/A code shift and the 1-ms counter match.
78 | -- 4) Write PLS/MNS mode if C/A code shift is to be adjusted with +-1
79 | -- (H/W adjust the shift as early as possible w/ keeping carrier NCO phase.)
80 | -- 5) Write new PNCO if it is to be adjusted.
81 | -- (H/W changes the PNCO as early as possible. The carrier NCO phase is naturally kept.)
82 |
83 | -- For Serial Acquisition (Not use acquisition mode)
84 | -- 1) Direct write of initial C/A code shift of each channel
85 | -- 2) Direct write of initial PNCO
86 | -- 3) Write of G2 shift of a satellite w/ disabling acquisition. The write makes the channel RDY.
87 | -- 4) Increment PNCO to scan Doppler shift range of +-10 kHz
88 | -- (H/W initializes carrier NCO phase to 0 when it increment the PNCO.
89 | -- Then, each evaluation starts w/ the same carrier NCO phase.)
90 | -- 5) Increment C/A code shift to scan all the shift range
91 | -- (H/W increment the PNCO and C/A code shift at the 1-ms boundary of the channel.
92 | -- So, the control must be done during the last 1-ms evaluation of the channel.)
93 | -- 6) Write of G2 shift of another satellite w/ disabling acquisition.
94 |
95 | -- For FFT Acquisition (Use acquisition mode)
96 | -- 1) Direct write of initial PNCO
97 | -- 2) Set acquisition mode enable. The write makes the channel RDY. (G2 shift is not used)
98 | -- 3) The initialized channel starts running when the 1-ms counter becomes 0.
99 | -- (The initial values of C/A code shift and 1-ms counter matches, and the next counter value is 0.)
100 | -- 4) Increment PNCO to scan Doppler shift range of +-10 kHz
101 |
102 | -- 3. Data input
103 |
104 | -- From I/O port
105 | -- 1) Write data w/ setting bit 31 to be 0 to S/W reset address.
106 | -- Default input mode is to use I/O port. Nothing is to be done after H/W reset.
107 | -- From CPU bus
108 | -- 1) Write data w/ setting bit 31 to be 1 to S/W reset address.
109 | -- 2) CPU bus master reads GPSIF status register to check input buffer status BUSY or not, and
110 | -- wait until the status becomes FILL.
111 | -- 3) After it becomes FILL, the CPU bus master writes 16*32 bits of data.
112 | -- Input cycles must be more than 56 (7ch*8cycles) per 16 CPU bus operations for 7 channel case.
113 | -- Is is safe to write data every 4 cycles or less. (4*16 = 64 > 56)
114 |
115 | -- 4. Read evaluation result
116 |
117 | -- By CPU bus master
118 | -- 1) CPU bus master checks each channel status by reading GPSIF status register.
119 | -- 2) If the status is VLD, it reads valid results in output buffers.
120 | -- - The results of each channel are six data of EI,EQ,PI,PQ,LI, and LQ.
121 | -- H/W changes the status to RDY after reading the LQ.
122 | -- So, the LQ should be read last.
123 | -- - GPSIF has output buffers that is separated from accumulating buffers.
124 | -- Then, the results in the output buffers are valid for 1 ms.
125 | -- - H/W set the fail flag of each channel
126 | -- when H/W observes a read access while the status is RDY (read-before-write),
127 | -- or H/W writes a new result while the status is VLD (write-before-read).
128 | -- (Currently, the fail bits are not assigned to GPSIF status register yet.)
129 | -- By DMAC
130 | -- 1) When DMAC get the DMA channel number from GPSIF, it reads the results.
131 | -- - GPSIF output the DMA channel assigned to each channel to DMAC when the results of the channel become valid.
132 | -- So, the DMAC does not have to check the output validity.
133 |
134 | --------------------------------- H/W behavior ---------------------------------
135 | -- 0. H/W reset
136 | -- H/W reset initializes GPSIF. Default input mode is from I/O port. The others are the same as the S/W reset.
137 |
138 | -- 2. Input buffer write
139 | -- From I/O port, GPSIF has a buffer consisting of 4 sets of 8 data. The write uses a special clock synchronized
140 | -- to the I/O port. So, the write pointer and write enable signal are clocked by the special clock. The GPSIF
141 | -- processing is faster than the input write. So, the write is always possible. The higher 2 bits of the write
142 | -- pointer is passed to main body of the GPSIF. For an asynchronous pass, the 2 bits changes with a sequence of
143 | -- 00 => 01 => 11 => 10 => 00. Then, the 2-bit code is always correct even when the signal change timing is
144 | -- slightly different. (Avoiding 01 => 10 or 10 => 01 is important.)
145 |
146 | -- From CPU bus, the GPSIF has a buffer consisting of 32 sets of 8 data assuming a 512 bit packet for the data.
147 | -- GPSIF clear the input buffer status bit of the GPSIF status register to show it is BUSY when the write pointer
148 | -- returns to 0, until read scope pointer points the last scope. CPU bus master must wait until the bit is set
149 | -- for writing new input data. Since the last scope consists of the last and first 8 data and the processing of
150 | -- the scope requires 7*8 = 56 cycles, and 512 bit buffer filling takes 512/32 = 16 CPU bus operations, the bus
151 | -- master must not issue the last input data write within the 56 cycles. Is is safe to write data every 4 cycles
152 | -- or less. Assuming future data input from ring bus, it takes 512/8 = 64 ring bus cycles or more, and no
153 | -- restriction is necessary to keep the input data.
154 |
155 | -- 3. Input buffer read by GPSIF H/W
156 | -- Input buffer is divided into multiple sets of 8 data, and two consecutive sets are specified by the read scope
157 | -- pointer as a current input data scope. Then, a 4-bit read pointer that is lower 4 bits of C/A code shift of each
158 | -- channel can specify any 8 data in the scope. So, all the channels can share the input buffer with different C/A
159 | -- code shift. However, this is not true when the C/A code shift changes. The direct write is for initialization,
160 | -- and it must be done while the channel is IDL. The change by INC/PLS mode requires a scope skip to ignore data
161 | -- between the last and new 1 ms. For negative INC, HW skips data of 1022*16 + (negative)INC. If the new shift can
162 | -- use the same scope, HW does not skip the scope. For MNS mode, HW uses the same scope twice if the scope is
163 | -- changed. If the read scope reaches to the writing entry of the input buffer, GPSIF stall processing of the data.
164 | --------------------------------------------------------------------------------
165 | library ieee;
166 | use ieee.std_logic_1164.all;
167 | use work.gpsif_pack.all;
168 | use work.gpsif_sub_pack.all;
169 | use work.cpu2j0_pack.all;
170 | use work.ring_bus_pack.all;
171 | use work.rbus_pack.all;
172 | use work.bist_pack.all;
173 | use work.util_pack.all;
174 | use work.attr_pack.all;
175 |
176 | entity gpsif_top is
177 | generic ( GPSIF_NC : integer := 7;
178 | ANGLE_INI_OLD : boolean := false );
179 | port (
180 | clk : in std_logic;
181 | rst : in std_logic;
182 | gps_clk : in std_logic;
183 | gps_d : in std_logic_vector(1 downto 0);
184 | ppsdds : in std_logic;
185 | blgps : in blgps_t;
186 | dma : out dma_req_t;
187 | intrpt : out std_logic;
188 | bi : in bist_scan_t;
189 | bo : out bist_scan_t;
190 | ring_i : in rbus_9b;
191 | ring_o : out rbus_9b;
192 | bus_clk : in std_logic;
193 | db_i : in cpu_data_o_t;
194 | db_o : out cpu_data_i_t );
195 | attribute soc_port_irq of intrpt : signal is true;
196 | end entity;
197 |
198 | architecture arch of gpsif_top is
199 | -- gpsif ports
200 | signal tgt_o : cpu_data_i_t;
201 | signal tgt_i : gpsif_tgt_i_t;
202 | signal dev_i : rbus_dev_i_t;
203 | signal dev_o : rbus_dev_o_t;
204 | signal buf_io : gpsif_buf_i_t;
205 | signal ra_io : gpsif_buf_ct_t;
206 | signal buf_bus : gpsif_i_t;
207 | signal buf_waf : gpsif_buf_rw_t;
208 | signal time_i : gpsif_time_t;
209 | signal gpsif_o : gpsif_o_t;
210 | signal bs0 : bist_scan_t;
211 | signal gps_clkbf : std_logic;
212 | signal ring_o_dbg : rbus_9b;
213 |
214 | begin
215 | ring_o <= ring_o_dbg;
216 | g : gpsif
217 | generic map ( GPSIF_NC => GPSIF_NC,
218 | ANGLE_INI_OLD => ANGLE_INI_OLD )
219 | port map (
220 | clk => clk,
221 | rst => rst,
222 | bi => bi,
223 | bo => bs0,
224 | ring_i => ring_i, -- to monitor ring bus
225 | ring_o => ring_o_dbg, -- to monitor ring bus
226 | tgt_o => tgt_o,
227 | tgt_i => tgt_i,
228 | dev_o => dev_o, -- output to ring bus
229 | dev_i => dev_i, -- input from ring bus
230 | buf_io => buf_io, -- wp(write pointer), sgin, magnitude
231 | time_i => time_i,
232 | ra_io => ra_io,
233 | buf_bus => buf_bus,
234 | gpsif_o => gpsif_o, -- rp(read pointer)
235 | dma => dma
236 | );
237 | a : rbus_adp
238 | port map (
239 | clk => clk,
240 | rst => rst,
241 | -- sw_rst => gpsif_o.rst,
242 | ring_i => ring_i,
243 | -- ring_o => ring_o,
244 | ring_o => ring_o_dbg,
245 | dev_o => dev_o,
246 | dev_i => dev_i
247 | );
248 | b : gpsif_buf
249 | port map (
250 | clk => clk,
251 | rst => rst,
252 | gps_clk => gps_clkbf,
253 | gps_d => gps_d,
254 | a => ra_io,
255 | y => buf_io,
256 | waf => buf_waf
257 | );
258 | c : gpsif_db
259 | port map (
260 | clk => bus_clk,
261 | rst => rst,
262 | bi => bs0,
263 | bo => bo,
264 | db_i => db_i,
265 | db_o => db_o,
266 | tgt_o => tgt_o,
267 | tgt_i => tgt_i,
268 | time_i => time_i,
269 | intrpt => intrpt,
270 | a => gpsif_o,
271 | y => buf_bus
272 | );
273 | d : global_buffer
274 | port map (
275 | i => gps_clk,
276 | o => gps_clkbf
277 | );
278 | e : gpsif_time
279 | port map (
280 | clk => clk,
281 | rst => rst,
282 | gps_clk => gps_clkbf,
283 | gps_d => gps_d,
284 | a => ra_io,
285 | waf => buf_waf,
286 | ppsdds => ppsdds,
287 | blgps => blgps,
288 | y => time_i
289 | );
290 |
291 | end architecture;
292 |
--------------------------------------------------------------------------------
/rbus_adp.vhm:
--------------------------------------------------------------------------------
1 |
2 | ---------------------------- GPS digital part (ring bus adaptor) ----------------------------
3 | -- written on 2016/12/14 by F. Arakawa --
4 | ---------------------------------------------------------------------------------------------
5 | library ieee;
6 | use ieee.std_logic_1164.all;
7 | use work.ring_bus_pack.all;
8 | use work.rbus_pack.all;
9 |
10 | entity rbus_adp is
11 | generic (OWN_CH : integer := RNG_CH_GPS); -- default
12 | port (clk : in std_logic;
13 | rst : in std_logic;
14 | -- sw_rst : in boolean;
15 | ring_i : in rbus_9b;
16 | ring_o : out rbus_9b;
17 | dev_o : in rbus_dev_o_t; -- from device
18 | dev_i : out rbus_dev_i_t); -- to device
19 | end rbus_adp;
20 |
21 | architecture beh of rbus_adp is
22 |
23 | type rbus_in_t is -- input word type
24 | (BC, -- input word is BROADCAST cmd
25 | BSY, -- input word is BUSY cmd
26 | FW, -- input word is to be forwarded to successor
27 | WT, -- input word is to be written to device
28 | DTI);-- input word is data
29 | type rbus_wd_t is (CM, CH, DT); -- command, broadcast channel, or data
30 | type rbus_fwd_t is (FWD, SND); -- forward or send
31 | type rbus_typ_t is array (rbus_in_t range BC to DTI) of boolean;
32 | type rbus_reg_t is record
33 | snd,rcv : rbus_wd_t;
34 | fwd : rbus_fwd_t;
35 | dly,ring_o : rbus_word_9b;
36 | dly_v : boolean;
37 | end record;
38 | constant rbus_reg_RESET : rbus_reg_t := (
39 | snd => CM, dly => IDLE_9b, dly_v => false,
40 | rcv => CM, ring_o => IDLE_9b, fwd => FWD
41 | );
42 | register variable this : rbus_reg_t reset := rbus_reg_RESET;
43 |
44 | begin
45 | p0 : process(this,ring_i,dev_o)
46 | register this when clk = '1' and clk'event reset sync when rst = '1';
47 |
48 | variable dev_dt,cmd_nop,stall_wt,stall_fw,dev_i_v,dev_i_ack : boolean;
49 | variable typ : rbus_typ_t;
50 | variable dev_i_wd, dev_o_wd : rbus_word_9b;
51 | variable cmd : rbus_cmd;
52 | variable hop : cmd_hops;
53 | begin
54 | -- device output setup ( add fr bit and packet of cmd,hop and channel)
55 | dev_dt := this.snd = DT and dev_o.v;
56 | if dev_o.v then case this.snd is
57 | when CM => dev_o_wd := cmd_word_9b(BROADCAST,1); this.snd := CH;
58 | when CH => dev_o_wd := data_word_9b(2**dev_o.ch); this.snd := DT;
59 | when DT => dev_o_wd := data_word_9b(dev_o.d); this.snd := DT;
60 | end case; else dev_o_wd := data_word_9b(dev_o.d); this.snd := CM; end if;
61 | -- input select
62 | if this.dly_v then dev_i_wd := this.dly;
63 | else dev_i_wd := ring_i.word; end if;
64 | -- input cmd type & hop count check
65 | if dev_i_wd.fr = '1' then
66 | cmd := to_cmd (dev_i_wd.d);
67 | hop := to_hops(dev_i_wd.d);
68 | typ(BC) := cmd = BROADCAST;
69 | typ(BSY):= cmd = BUSY;
70 | typ(FW) := cmd /= IDLE and hop/2 /= 0; -- hop>1
71 | typ(WT) :=((cmd /= IDLE and hop = 1) or typ(BC)); -- hop=1
72 | -- decrement hop after the check
73 | if hop /= 0 then hop := hop -1; dev_i_wd := cmd_word_9b(cmd,hop); end if;
74 | else typ := (others => false); end if;
75 | typ(DTI) := typ(BSY) or dev_i_wd.fr = '0'; -- data words
76 | -- to device (check cmd and channel, and send data)
77 | dev_i_v := false;
78 | case this.rcv is
79 | when CM => if typ(WT) then if typ(BC) then this.rcv := CH;
80 | else this.rcv := DT; end if; end if;
81 | when CH => if dev_i_wd.d(OWN_CH)= '1' then this.rcv := DT;
82 | else this.rcv := CM; end if;
83 | when DT => if not typ(DTI) then this.rcv := CM; end if;
84 | dev_i_v := dev_i_wd.fr = '0'; -- Input is valid data.
85 | end case;
86 | stall_wt := dev_i_v and dev_o.bsy; -- So stall occurs if device is busy.
87 | -- to successor
88 | -- output cmd type check
89 | if this.ring_o.fr = '1' then
90 | cmd := to_cmd(this.ring_o.d);
91 | cmd_nop := cmd = IDLE or cmd = BUSY;
92 | else cmd_nop := false; end if;
93 | -- Toggle output mode if possible: FWD <=> SND
94 | stall_fw := false;
95 | dev_i_ack := false;
96 | if ring_i.stall = '0' or cmd_nop then case this.fwd is -- ring_o can be updated
97 | when FWD => if typ(DTI) then if stall_wt then this.ring_o := cmd_word_9b(BUSY,0);
98 | else this.ring_o := dev_i_wd; end if; -- continue
99 | elsif dev_o.v then this.fwd := SND; this.ring_o := dev_o_wd; stall_fw := typ(FW); -- mode toggle
100 | elsif typ(FW) then this.ring_o := dev_i_wd; -- new forward
101 | else this.fwd := SND; this.ring_o := IDLE_9b; end if; -- send mode check valid
102 | when SND => if dev_dt then dev_i_ack:=true; this.ring_o := dev_o_wd; stall_fw := typ(FW); -- continue, data is sent
103 | elsif typ(FW) then this.fwd := FWD; this.ring_o := dev_i_wd; -- mode toggle
104 | elsif dev_o.v then this.fwd := SND; this.ring_o := dev_o_wd; stall_fw := typ(FW); -- new send
105 | else this.ring_o := IDLE_9b; end if; end case;
106 | else stall_fw := typ(FW); end if; -- to be forwarded, but cannot
107 | -- keep ring_i if it is not used yet
108 | if not this.dly_v and (stall_wt or stall_fw) then this.dly := ring_i.word; end if;
109 | this.dly_v := stall_wt or stall_fw;
110 | dev_i.d <= dev_i_wd.d;
111 | dev_i.v <= dev_i_v;
112 | dev_i.ack <= dev_i_ack;
113 | -- SW reset
114 | -- if sw_rst then this := rbus_reg_RESET; end if;
115 | end process;
116 | -- stall ring_i if the previous value is kept in this.dly
117 | ring_o.stall <= '1' when this'register.dly_v else '0';
118 | ring_o.word <= this'register.ring_o;
119 | end beh;
120 |
--------------------------------------------------------------------------------
/rbus_pkg.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 | use work.ring_bus_pack.all;
5 |
6 | package rbus_pack is
7 | -- added by FA
8 | constant RNG_CH_DSP : integer := 0;
9 | constant RNG_CH_GPS : integer := 1;
10 | type rbus_dev_o_t is record
11 | d : std_logic_vector(8 downto 0);
12 | v,bsy : boolean;
13 | ch : integer range 0 to 8;
14 | end record;
15 | type rbus_dev_i_t is record
16 | d : std_logic_vector(8 downto 0);
17 | v,ack : boolean;
18 | end record;
19 | component rbus_adp is
20 | generic (OWN_CH : integer := RNG_CH_GPS); -- default
21 | port (clk : in std_logic;
22 | rst : in std_logic;
23 | -- sw_rst : in boolean;
24 | ring_i : in rbus_9b;
25 | ring_o : out rbus_9b;
26 | dev_o : in rbus_dev_o_t; -- from device
27 | dev_i : out rbus_dev_i_t); -- to device
28 | end component;
29 |
30 | end package;
31 |
--------------------------------------------------------------------------------
/tests/gpsif_db_tb.gtkw:
--------------------------------------------------------------------------------
1 | [*]
2 | [*] GTKWave Analyzer v3.3.71 (w)1999-2016 BSI
3 | [*] Fri Oct 28 22:20:49 2016
4 | [*]
5 | [dumpfile] "/Users/fumio/VM/share/current/soc_top/components/gps_if2/tests/gpsif_db_tb.ghw"
6 | [dumpfile_mtime] "Fri Oct 28 13:50:34 2016"
7 | [dumpfile_size] 92689138
8 | [savefile] "/Users/fumio/VM/share/current/soc_top/components/gps_if2/tests/gspif_db_tb.gtkw"
9 | [timestart] 0
10 | [size] 1918 552
11 | [pos] 0 -1
12 | *-37.678806 909000000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
13 | [treeopen] top.
14 | [treeopen] top.gpsif_db_tb.
15 | [treeopen] top.gpsif_db_tb.g.
16 | [treeopen] top.gpsif_db_tb.g.g.
17 | [treeopen] top.gpsif_db_tb.g.g.a.
18 | [treeopen] top.gpsif_db_tb.g.g.acm.
19 | [treeopen] top.gpsif_db_tb.g.g.acm.a.
20 | [treeopen] top.gpsif_db_tb.g.g.acm.y.
21 | [treeopen] top.gpsif_db_tb.g.g.cacode_i.
22 | [treeopen] top.gpsif_db_tb.g.g.cdgen.a.
23 | [treeopen] top.gpsif_db_tb.g.g.cdgen.this_c.
24 | [treeopen] top.gpsif_db_tb.g.g.cdgen.this_r.
25 | [treeopen] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft.
26 | [treeopen] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft.
27 | [treeopen] top.gpsif_db_tb.g.g.regfile_o.
28 | [treeopen] top.gpsif_db_tb.g.g.regfile_o.angle.
29 | [treeopen] top.gpsif_db_tb.g.g.sum.this_r.
30 | [treeopen] top.gpsif_db_tb.g.g.target_i.
31 | [treeopen] top.gpsif_db_tb.g.g.this_c.
32 | [treeopen] top.gpsif_db_tb.g.g.this_r.
33 | [treeopen] top.gpsif_db_tb.g.gpsif_i.
34 | [treeopen] top.gpsif_db_tb.g.gpsif_o.
35 | [treeopen] top.gpsif_db_tb.g.target_i.
36 | [treeopen] top.gpsif_db_tb.g.target_o.
37 | [sst_width] 245
38 | [signals_width] 175
39 | [sst_expanded] 1
40 | [sst_vpaned_height] 303
41 | @28
42 | top.gpsif_db_tb.g.rst
43 | top.gpsif_db_tb.g.clk
44 | top.gpsif_db_tb.g.gpsif_i.wp
45 | top.gpsif_db_tb.g.g.this_r.init
46 | @22
47 | #{top.gpsif_db_tb.g.g.regfile_o.angle.angle[29:0]} top.gpsif_db_tb.g.g.regfile_o.angle.angle[29] top.gpsif_db_tb.g.g.regfile_o.angle.angle[28] top.gpsif_db_tb.g.g.regfile_o.angle.angle[27] top.gpsif_db_tb.g.g.regfile_o.angle.angle[26] top.gpsif_db_tb.g.g.regfile_o.angle.angle[25] top.gpsif_db_tb.g.g.regfile_o.angle.angle[24] top.gpsif_db_tb.g.g.regfile_o.angle.angle[23] top.gpsif_db_tb.g.g.regfile_o.angle.angle[22] top.gpsif_db_tb.g.g.regfile_o.angle.angle[21] top.gpsif_db_tb.g.g.regfile_o.angle.angle[20] top.gpsif_db_tb.g.g.regfile_o.angle.angle[19] top.gpsif_db_tb.g.g.regfile_o.angle.angle[18] top.gpsif_db_tb.g.g.regfile_o.angle.angle[17] top.gpsif_db_tb.g.g.regfile_o.angle.angle[16] top.gpsif_db_tb.g.g.regfile_o.angle.angle[15] top.gpsif_db_tb.g.g.regfile_o.angle.angle[14] top.gpsif_db_tb.g.g.regfile_o.angle.angle[13] top.gpsif_db_tb.g.g.regfile_o.angle.angle[12] top.gpsif_db_tb.g.g.regfile_o.angle.angle[11] top.gpsif_db_tb.g.g.regfile_o.angle.angle[10] top.gpsif_db_tb.g.g.regfile_o.angle.angle[9] top.gpsif_db_tb.g.g.regfile_o.angle.angle[8] top.gpsif_db_tb.g.g.regfile_o.angle.angle[7] top.gpsif_db_tb.g.g.regfile_o.angle.angle[6] top.gpsif_db_tb.g.g.regfile_o.angle.angle[5] top.gpsif_db_tb.g.g.regfile_o.angle.angle[4] top.gpsif_db_tb.g.g.regfile_o.angle.angle[3] top.gpsif_db_tb.g.g.regfile_o.angle.angle[2] top.gpsif_db_tb.g.g.regfile_o.angle.angle[1] top.gpsif_db_tb.g.g.regfile_o.angle.angle[0]
48 | #{top.gpsif_db_tb.g.g.regfile_o.angle.pnco[29:0]} top.gpsif_db_tb.g.g.regfile_o.angle.pnco[29] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[28] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[27] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[26] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[25] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[24] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[23] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[22] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[21] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[20] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[19] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[18] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[17] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[16] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[15] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[14] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[13] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[12] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[11] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[10] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[9] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[8] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[7] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[6] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[5] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[4] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[3] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[2] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[1] top.gpsif_db_tb.g.g.regfile_o.angle.pnco[0]
49 | @28
50 | top.gpsif_db_tb.g.gpsif_o.a
51 | top.gpsif_db_tb.g.g.this_r.st
52 | top.gpsif_db_tb.g.g.this_r.ready
53 | top.gpsif_db_tb.g.g.this_r.rd
54 | top.gpsif_db_tb.g.g.this_r.nc
55 | top.gpsif_db_tb.g.g.this_r.nd
56 | top.gpsif_db_tb.g.g.this_r.cnt1ms
57 | #{top.gpsif_db_tb.g.g.a.d[1:0]} top.gpsif_db_tb.g.g.a.d[1] top.gpsif_db_tb.g.g.a.d[0]
58 | top.gpsif_db_tb.g.g.sum_i.q
59 | top.gpsif_db_tb.g.g.acm_i.q
60 | top.gpsif_db_tb.g.g.sum_i.i
61 | top.gpsif_db_tb.g.g.acm_i.i
62 | top.gpsif_db_tb.g.g.acm.this_r.ch
63 | top.gpsif_db_tb.g.g.cdgen.a.ch
64 | @800022
65 | #{top.gpsif_db_tb.g.g.this_r.ch_st[0:6]} top.gpsif_db_tb.g.g.this_r.ch_st[0] top.gpsif_db_tb.g.g.this_r.ch_st[1] top.gpsif_db_tb.g.g.this_r.ch_st[2] top.gpsif_db_tb.g.g.this_r.ch_st[3] top.gpsif_db_tb.g.g.this_r.ch_st[4] top.gpsif_db_tb.g.g.this_r.ch_st[5] top.gpsif_db_tb.g.g.this_r.ch_st[6]
66 | @28
67 | top.gpsif_db_tb.g.g.this_r.ch_st[0]
68 | top.gpsif_db_tb.g.g.this_r.ch_st[1]
69 | top.gpsif_db_tb.g.g.this_r.ch_st[2]
70 | top.gpsif_db_tb.g.g.this_r.ch_st[3]
71 | top.gpsif_db_tb.g.g.this_r.ch_st[4]
72 | top.gpsif_db_tb.g.g.this_r.ch_st[5]
73 | top.gpsif_db_tb.g.g.this_r.ch_st[6]
74 | @1001200
75 | -group_end
76 | @28
77 | top.gpsif_db_tb.g.g.cdgen.a.even
78 | top.gpsif_db_tb.g.g.cdgen.a.set
79 | @22
80 | #{top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][9:0]} top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][9] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][8] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][7] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][6] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][5] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][4] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][3] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][2] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][1] top.gpsif_db_tb.g.g.cdgen.this_r.g1sft[0][0]
81 | #{top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][9:0]} top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][9] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][8] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][7] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][6] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][5] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][4] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][3] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][2] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][1] top.gpsif_db_tb.g.g.cdgen.this_r.g2sft[0][0]
82 | @28
83 | #{top.gpsif_db_tb.g.g.cdgen.this_c.code[2:0]} top.gpsif_db_tb.g.g.cdgen.this_c.code[2] top.gpsif_db_tb.g.g.cdgen.this_c.code[1] top.gpsif_db_tb.g.g.cdgen.this_c.code[0]
84 | #{top.gpsif_db_tb.g.g.cdgen.this_r.code[2:0]} top.gpsif_db_tb.g.g.cdgen.this_r.code[2] top.gpsif_db_tb.g.g.cdgen.this_r.code[1] top.gpsif_db_tb.g.g.cdgen.this_r.code[0]
85 | @22
86 | #{top.gpsif_db_tb.g.g.acm_o.wd[27:0]} top.gpsif_db_tb.g.g.acm_o.wd[27] top.gpsif_db_tb.g.g.acm_o.wd[26] top.gpsif_db_tb.g.g.acm_o.wd[25] top.gpsif_db_tb.g.g.acm_o.wd[24] top.gpsif_db_tb.g.g.acm_o.wd[23] top.gpsif_db_tb.g.g.acm_o.wd[22] top.gpsif_db_tb.g.g.acm_o.wd[21] top.gpsif_db_tb.g.g.acm_o.wd[20] top.gpsif_db_tb.g.g.acm_o.wd[19] top.gpsif_db_tb.g.g.acm_o.wd[18] top.gpsif_db_tb.g.g.acm_o.wd[17] top.gpsif_db_tb.g.g.acm_o.wd[16] top.gpsif_db_tb.g.g.acm_o.wd[15] top.gpsif_db_tb.g.g.acm_o.wd[14] top.gpsif_db_tb.g.g.acm_o.wd[13] top.gpsif_db_tb.g.g.acm_o.wd[12] top.gpsif_db_tb.g.g.acm_o.wd[11] top.gpsif_db_tb.g.g.acm_o.wd[10] top.gpsif_db_tb.g.g.acm_o.wd[9] top.gpsif_db_tb.g.g.acm_o.wd[8] top.gpsif_db_tb.g.g.acm_o.wd[7] top.gpsif_db_tb.g.g.acm_o.wd[6] top.gpsif_db_tb.g.g.acm_o.wd[5] top.gpsif_db_tb.g.g.acm_o.wd[4] top.gpsif_db_tb.g.g.acm_o.wd[3] top.gpsif_db_tb.g.g.acm_o.wd[2] top.gpsif_db_tb.g.g.acm_o.wd[1] top.gpsif_db_tb.g.g.acm_o.wd[0]
87 | #{top.gpsif_db_tb.g.g.target_i.d[31:0]} top.gpsif_db_tb.g.g.target_i.d[31] top.gpsif_db_tb.g.g.target_i.d[30] top.gpsif_db_tb.g.g.target_i.d[29] top.gpsif_db_tb.g.g.target_i.d[28] top.gpsif_db_tb.g.g.target_i.d[27] top.gpsif_db_tb.g.g.target_i.d[26] top.gpsif_db_tb.g.g.target_i.d[25] top.gpsif_db_tb.g.g.target_i.d[24] top.gpsif_db_tb.g.g.target_i.d[23] top.gpsif_db_tb.g.g.target_i.d[22] top.gpsif_db_tb.g.g.target_i.d[21] top.gpsif_db_tb.g.g.target_i.d[20] top.gpsif_db_tb.g.g.target_i.d[19] top.gpsif_db_tb.g.g.target_i.d[18] top.gpsif_db_tb.g.g.target_i.d[17] top.gpsif_db_tb.g.g.target_i.d[16] top.gpsif_db_tb.g.g.target_i.d[15] top.gpsif_db_tb.g.g.target_i.d[14] top.gpsif_db_tb.g.g.target_i.d[13] top.gpsif_db_tb.g.g.target_i.d[12] top.gpsif_db_tb.g.g.target_i.d[11] top.gpsif_db_tb.g.g.target_i.d[10] top.gpsif_db_tb.g.g.target_i.d[9] top.gpsif_db_tb.g.g.target_i.d[8] top.gpsif_db_tb.g.g.target_i.d[7] top.gpsif_db_tb.g.g.target_i.d[6] top.gpsif_db_tb.g.g.target_i.d[5] top.gpsif_db_tb.g.g.target_i.d[4] top.gpsif_db_tb.g.g.target_i.d[3] top.gpsif_db_tb.g.g.target_i.d[2] top.gpsif_db_tb.g.g.target_i.d[1] top.gpsif_db_tb.g.g.target_i.d[0]
88 | #{top.gpsif_db_tb.g.g.cacode_i.wen[0:6]} top.gpsif_db_tb.g.g.cacode_i.wen[0] top.gpsif_db_tb.g.g.cacode_i.wen[1] top.gpsif_db_tb.g.g.cacode_i.wen[2] top.gpsif_db_tb.g.g.cacode_i.wen[3] top.gpsif_db_tb.g.g.cacode_i.wen[4] top.gpsif_db_tb.g.g.cacode_i.wen[5] top.gpsif_db_tb.g.g.cacode_i.wen[6]
89 | #{top.gpsif_db_tb.g.g.cacode_i.indata[9:0]} top.gpsif_db_tb.g.g.cacode_i.indata[9] top.gpsif_db_tb.g.g.cacode_i.indata[8] top.gpsif_db_tb.g.g.cacode_i.indata[7] top.gpsif_db_tb.g.g.cacode_i.indata[6] top.gpsif_db_tb.g.g.cacode_i.indata[5] top.gpsif_db_tb.g.g.cacode_i.indata[4] top.gpsif_db_tb.g.g.cacode_i.indata[3] top.gpsif_db_tb.g.g.cacode_i.indata[2] top.gpsif_db_tb.g.g.cacode_i.indata[1] top.gpsif_db_tb.g.g.cacode_i.indata[0]
90 | #{top.gpsif_db_tb.g.g.target_i.a[6:0]} top.gpsif_db_tb.g.g.target_i.a[6] top.gpsif_db_tb.g.g.target_i.a[5] top.gpsif_db_tb.g.g.target_i.a[4] top.gpsif_db_tb.g.g.target_i.a[3] top.gpsif_db_tb.g.g.target_i.a[2] top.gpsif_db_tb.g.g.target_i.a[1] top.gpsif_db_tb.g.g.target_i.a[0]
91 | @800022
92 | #{top.gpsif_db_tb.g.g.this_r.sft[0:6]} top.gpsif_db_tb.g.g.this_r.sft[0] top.gpsif_db_tb.g.g.this_r.sft[1] top.gpsif_db_tb.g.g.this_r.sft[2] top.gpsif_db_tb.g.g.this_r.sft[3] top.gpsif_db_tb.g.g.this_r.sft[4] top.gpsif_db_tb.g.g.this_r.sft[5] top.gpsif_db_tb.g.g.this_r.sft[6]
93 | @28
94 | top.gpsif_db_tb.g.g.this_r.sft[0]
95 | top.gpsif_db_tb.g.g.this_r.sft[1]
96 | top.gpsif_db_tb.g.g.this_r.sft[2]
97 | top.gpsif_db_tb.g.g.this_r.sft[3]
98 | top.gpsif_db_tb.g.g.this_r.sft[4]
99 | top.gpsif_db_tb.g.g.this_r.sft[5]
100 | top.gpsif_db_tb.g.g.this_r.sft[6]
101 | #{top.gpsif_db_tb.g.g.cacode_o[2:0]} top.gpsif_db_tb.g.g.cacode_o[2] top.gpsif_db_tb.g.g.cacode_o[1] top.gpsif_db_tb.g.g.cacode_o[0]
102 | @23
103 | #{top.gpsif_db_tb.g.target_o.d[31:0]} top.gpsif_db_tb.g.target_o.d[31] top.gpsif_db_tb.g.target_o.d[30] top.gpsif_db_tb.g.target_o.d[29] top.gpsif_db_tb.g.target_o.d[28] top.gpsif_db_tb.g.target_o.d[27] top.gpsif_db_tb.g.target_o.d[26] top.gpsif_db_tb.g.target_o.d[25] top.gpsif_db_tb.g.target_o.d[24] top.gpsif_db_tb.g.target_o.d[23] top.gpsif_db_tb.g.target_o.d[22] top.gpsif_db_tb.g.target_o.d[21] top.gpsif_db_tb.g.target_o.d[20] top.gpsif_db_tb.g.target_o.d[19] top.gpsif_db_tb.g.target_o.d[18] top.gpsif_db_tb.g.target_o.d[17] top.gpsif_db_tb.g.target_o.d[16] top.gpsif_db_tb.g.target_o.d[15] top.gpsif_db_tb.g.target_o.d[14] top.gpsif_db_tb.g.target_o.d[13] top.gpsif_db_tb.g.target_o.d[12] top.gpsif_db_tb.g.target_o.d[11] top.gpsif_db_tb.g.target_o.d[10] top.gpsif_db_tb.g.target_o.d[9] top.gpsif_db_tb.g.target_o.d[8] top.gpsif_db_tb.g.target_o.d[7] top.gpsif_db_tb.g.target_o.d[6] top.gpsif_db_tb.g.target_o.d[5] top.gpsif_db_tb.g.target_o.d[4] top.gpsif_db_tb.g.target_o.d[3] top.gpsif_db_tb.g.target_o.d[2] top.gpsif_db_tb.g.target_o.d[1] top.gpsif_db_tb.g.target_o.d[0]
104 | @28
105 | top.gpsif_db_tb.g.target_o.ack
106 | @1001200
107 | -group_end
108 | [pattern_trace] 1
109 | [pattern_trace] 0
110 |
--------------------------------------------------------------------------------
/tests/gpsif_db_tb.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.std_logic_textio.all;
4 | use ieee.numeric_std.all;
5 | use std.textio.all;
6 |
7 | use work.cpu2j0_pack.all;
8 | use work.test_pkg.all;
9 | use work.bist_pack.all;
10 | use work.gpsif_pack.all;
11 |
12 | entity gpsif_db_tb is
13 | end entity;
14 |
15 | architecture tb of gpsif_db_tb is
16 | signal clk : std_logic := '0';
17 | signal rst : std_logic := '1';
18 | shared variable ENDSIM : boolean := false;
19 |
20 | signal dma : dma_req_t;
21 | signal db_i : cpu_data_o_t := NULL_DATA_O;
22 | signal db_o : cpu_data_i_t;
23 |
24 | function read(addr : std_logic_vector(7 downto 0))
25 | return cpu_data_o_t is
26 | variable r : cpu_data_o_t := NULL_DATA_O;
27 | begin
28 | r.en := '1';
29 | r.rd := '1';
30 | r.a := x"00000" & "00" & addr & "00";
31 | return r;
32 | end;
33 |
34 | function write(addr : std_logic_vector(7 downto 0);
35 | data : std_logic_vector(31 downto 0);
36 | we : std_logic_vector(3 downto 0) := "1111")
37 | return cpu_data_o_t is
38 | variable w : cpu_data_o_t := NULL_DATA_O;
39 | begin
40 | w.en := '1';
41 | w.wr := '1';
42 | w.a := x"00000" & "00" & addr & "00";
43 | w.d := data;
44 | w.we := we;
45 | return w;
46 | end;
47 |
48 | function sign_extend28(x : std_logic_vector(31 downto 0))
49 | return std_logic_vector is
50 | begin
51 | return x(27) & x(27) & x(27) & x(27) & x(27 downto 0);
52 | end function;
53 |
54 | procedure check_channel(
55 | signal clk : in std_logic;
56 | signal db_i : out cpu_data_o_t;
57 | signal db_o : in cpu_data_i_t;
58 | constant ch : integer;
59 | constant ei : integer;
60 | constant eq : integer;
61 | constant pi : integer;
62 | constant pq : integer;
63 | constant li : integer;
64 | constant lq : integer) is
65 | begin
66 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8 , 8)));
67 | wait until clk = '1' and clk'event and db_o.ack = '1';
68 | test_equal(to_integer(signed(sign_extend28(db_o.d))), ei, "E_I(" & integer'image(ch) & ")");
69 | db_i <= NULL_DATA_O;
70 | wait until clk = '1' and clk'event;
71 |
72 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8+1, 8)));
73 | wait until clk = '1' and clk'event and db_o.ack = '1';
74 | test_equal(to_integer(signed(sign_extend28(db_o.d))), eq, "E_Q(" & integer'image(ch) & ")");
75 | db_i <= NULL_DATA_O;
76 | wait until clk = '1' and clk'event;
77 |
78 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8+2, 8)));
79 | wait until clk = '1' and clk'event and db_o.ack = '1';
80 | test_equal(to_integer(signed(sign_extend28(db_o.d))), pi, "P_I(" & integer'image(ch) & ")");
81 | db_i <= NULL_DATA_O;
82 | wait until clk = '1' and clk'event;
83 |
84 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8+3, 8)));
85 | wait until clk = '1' and clk'event and db_o.ack = '1';
86 | test_equal(to_integer(signed(sign_extend28(db_o.d))), pq, "P_Q(" & integer'image(ch) & ")");
87 | db_i <= NULL_DATA_O;
88 | wait until clk = '1' and clk'event;
89 |
90 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8+4, 8)));
91 | wait until clk = '1' and clk'event and db_o.ack = '1';
92 | test_equal(to_integer(signed(sign_extend28(db_o.d))), li, "L_I(" & integer'image(ch) & ")");
93 | db_i <= NULL_DATA_O;
94 | wait until clk = '1' and clk'event;
95 |
96 | db_i <= read(std_logic_vector(to_unsigned(16#40#, 8) + to_unsigned(ch*8+5, 8)));
97 | wait until clk = '1' and clk'event and db_o.ack = '1';
98 | test_equal(to_integer(signed(sign_extend28(db_o.d))), lq, "L_Q(" & integer'image(ch) & ")");
99 | db_i <= NULL_DATA_O;
100 | wait until clk = '1' and clk'event;
101 | end procedure;
102 |
103 | begin
104 | clk_gen : process
105 | begin
106 | if ENDSIM = false then
107 | clk <= '0';
108 | wait for 5 ns;
109 | clk <= '1';
110 | wait for 5 ns;
111 | else
112 | wait;
113 | end if;
114 | end process;
115 |
116 | dma_if_chk : process
117 | variable LI : line;
118 | begin
119 | if ENDSIM = false then
120 | wait until clk = '1' and clk'event;
121 | if dma.req(6) = '1' then
122 | write(LI, "DMA req. of ch #" & integer'image(to_integer(unsigned(dma.req(5 downto 0)))));
123 | writeline(output, LI);
124 | end if;
125 | else
126 | wait;
127 | end if;
128 | end process;
129 |
130 | g : configuration work.gpsif_top_sim
131 | port map (
132 | clk => clk,
133 | rst => rst,
134 | bi => BIST_SCAN_NOP,
135 | bo => open,
136 | db_i => db_i,
137 | db_o => db_o);
138 |
139 | process
140 | variable write_more : boolean := false;
141 | file FI : TEXT open read_mode is "tests/input.txt";
142 | variable LI : line;
143 | variable input : std_logic_vector(31 downto 0);
144 | variable data : std_logic_vector(31 downto 0);
145 | variable input_count : integer := 0;
146 | begin
147 | test_plan(36, "gpsif_db_tb");
148 | wait until clk = '1' and clk'event;
149 | wait until clk = '0' and clk'event;
150 | wait until clk = '1' and clk'event;
151 | wait until clk = '0' and clk'event;
152 | rst <= '0';
153 |
154 | wait until clk = '1' and clk'event;
155 | wait until clk = '1' and clk'event;
156 |
157 | -- write SFT
158 | db_i <= write(x"00", x"00002ba4");
159 | wait until clk = '1' and clk'event and db_o.ack = '1';
160 | db_i <= write(x"01", x"00003182");
161 | wait until clk = '1' and clk'event and db_o.ack = '1';
162 | db_i <= write(x"02", x"00002e54");
163 | wait until clk = '1' and clk'event and db_o.ack = '1';
164 | db_i <= write(x"03", x"00001640");
165 | wait until clk = '1' and clk'event and db_o.ack = '1';
166 | db_i <= write(x"04", x"00002a51");
167 | wait until clk = '1' and clk'event and db_o.ack = '1';
168 | db_i <= write(x"05", x"00003097");
169 | wait until clk = '1' and clk'event and db_o.ack = '1';
170 | db_i <= NULL_DATA_O;
171 |
172 | -- write g2sft
173 | db_i <= write(x"08", x"00000006");
174 | wait until clk = '1' and clk'event and db_o.ack = '1';
175 | db_i <= write(x"09", x"0000041c");
176 | wait until clk = '1' and clk'event and db_o.ack = '1';
177 | db_i <= write(x"0a", x"0000080b");
178 | wait until clk = '1' and clk'event and db_o.ack = '1';
179 | db_i <= write(x"0b", x"00000c64");
180 | wait until clk = '1' and clk'event and db_o.ack = '1';
181 | db_i <= write(x"0c", x"00001200");
182 | wait until clk = '1' and clk'event and db_o.ack = '1';
183 | db_i <= write(x"0d", x"000014d2");
184 | wait until clk = '1' and clk'event and db_o.ack = '1';
185 | db_i <= NULL_DATA_O;
186 |
187 | -- write PNCO
188 | db_i <= write(x"10", x"00016058");
189 | wait until clk = '1' and clk'event and db_o.ack = '1';
190 | db_i <= write(x"11", x"fffe1f88");
191 | wait until clk = '1' and clk'event and db_o.ack = '1';
192 | db_i <= write(x"12", x"0000e038");
193 | wait until clk = '1' and clk'event and db_o.ack = '1';
194 | db_i <= write(x"13", x"ffff5fd8");
195 | wait until clk = '1' and clk'event and db_o.ack = '1';
196 | db_i <= write(x"14", x"fffbbef0");
197 | wait until clk = '1' and clk'event and db_o.ack = '1';
198 | db_i <= write(x"15", x"ffffdff8");
199 | wait until clk = '1' and clk'event and db_o.ack = '1';
200 |
201 | input_loop: while true loop
202 | -- loop until status register allows input write
203 | write_ready: while true loop
204 | db_i <= read(x"80");
205 | wait until clk = '1' and clk'event and db_o.ack = '1';
206 | db_i <= NULL_DATA_O;
207 | data := db_o.d;
208 | if data(0) = '1' then
209 | exit write_ready;
210 | end if;
211 | end loop;
212 |
213 | input := x"00000000";
214 | for j in 0 to 15 loop -- Read 32b data from 16 lines of 2b data
215 | if endfile(FI) then
216 | exit input_loop;
217 | end if;
218 | readline(FI, LI);
219 | read(LI, input(31 - 2*j downto 30 - 2*j));
220 | end loop;
221 |
222 | -- Wait for 20 cycles between writing input data to test delays in input
223 | -- arrival
224 | if input_count > 22 then
225 | for i in 1 to 50 loop
226 | wait until clk = '1' and clk'event;
227 | end loop;
228 | else
229 | input_count := input_count + 1;
230 | end if;
231 |
232 | db_i <= write(x"81", input);
233 | wait until clk = '1' and clk'event and db_o.ack = '1';
234 | db_i <= NULL_DATA_O;
235 | wait until clk = '1' and clk'event;
236 | end loop;
237 | wait until clk = '1' and clk'event;
238 |
239 | -- Check that same values seen in the waveform at the end of the gpsif_tb
240 | check_channel(clk, db_i, db_o, 0, 13270, 7002, 19082, 42342, 21452, 25808);
241 | check_channel(clk, db_i, db_o, 1, 19610, -33416, 28814, -42980, 17464, -26782);
242 | check_channel(clk, db_i, db_o, 2, 31701, -1218, 39655, 2086, 13683, 578);
243 | check_channel(clk, db_i, db_o, 3, 18756, 3118, 33526, 1452, 8116, -17806);
244 | check_channel(clk, db_i, db_o, 4, 41, 16785, -12169, 10099, -9071, 593);
245 | check_channel(clk, db_i, db_o, 5, -2038, -1740, 8074, 23868, -6866, 22632);
246 | -- check_channel(clk, db_i, db_o, 6, -27648, -18944, -18304, -15872, -5120, -7168);
247 |
248 | wait until clk = '1' and clk'event;
249 | wait until clk = '1' and clk'event;
250 | wait until clk = '1' and clk'event;
251 | test_finished("done");
252 | ENDSIM := true;
253 | wait;
254 | end process;
255 | end architecture;
256 |
--------------------------------------------------------------------------------
/tests/gpsif_tb.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.std_logic_textio.all;
4 | use ieee.numeric_std.all;
5 | use std.textio.all;
6 |
7 | use work.cpu2j0_pack.all;
8 | use work.ring_bus_pack.all;
9 | use work.test_pkg.all;
10 | use work.bist_pack.all;
11 | use work.gpsif_pack.all;
12 | use work.gpsif_sub_pack.all;
13 | use work.gpsif_tb_pack.all;
14 |
15 | entity gpsif_tb is
16 | end entity;
17 |
18 | architecture tb of gpsif_tb is
19 | constant clk_tgl : time := 4.0 ns; -- for 125 MHz
20 | -- constant clk_tgl : time := 5.3333 ns; -- for 93.75 MHz
21 | -- constant clk_tgl : time := 5.454 ns; -- for 5.5x gps clk MHz
22 | -- constant clk_tgl : time := 5.714 ns; -- for 87.5 MHz
23 | -- constant clk_tgl : time := 8 ns; -- for 62.5 MHz
24 | -- constant bus_tgl : time := 8.0 ns; -- for 62.5 MHz
25 | constant bus_tgl : time := 4.0 ns; -- for 125 MHz
26 | constant gps_tgl : time := 30.547 ns; -- for 16.368 MHz
27 | constant ppsdds_tgl : time := 30000.0 ns; -- actual 1Hz, accelating test
28 | constant INTERVAL : natural := 4; -- 32b/4cycles = 1Byte/cycle is the maximum input speed for gpsif
29 | constant exe_cycles : natural := 32736; -- running 2ms @16.368Ms/s
30 | constant ANGLE_INI_OLD : boolean := false;
31 | constant GPSIF_NC : natural := 7;
32 | constant ACQ_TEST : boolean := false;
33 | constant SKIP_TEST : boolean := false;
34 |
35 | signal gps_clk : std_logic := '0';
36 | signal gps_d : std_logic_vector(1 downto 0) := "00";
37 | signal clk : std_logic := '0';
38 | signal rst : std_logic := '1';
39 | signal ppsdds : std_logic := '0';
40 | signal blgps : blgps_t := NULL_BLGPS;
41 | signal intrpt : std_logic := '0';
42 | signal bus_clk : std_logic := '0';
43 | shared variable ENDSIM : boolean := false;
44 |
45 | signal dma : dma_req_t;
46 | signal db_i : cpu_data_o_t := NULL_DATA_O;
47 | signal db_o : cpu_data_i_t;
48 |
49 | begin
50 | clk_gen : process
51 | begin
52 | if ENDSIM = false then
53 | clk <= '1'; wait for clk_tgl;
54 | clk <= '0'; wait for clk_tgl;
55 | else wait;
56 | end if;
57 | end process;
58 |
59 | bus_clk_gen : process
60 | begin
61 | if ENDSIM = false then
62 | bus_clk <= '1'; wait for bus_tgl;
63 | bus_clk <= '0'; wait for bus_tgl;
64 | else wait;
65 | end if;
66 | end process;
67 |
68 | gps_clk_gen : process
69 | begin
70 | if ENDSIM = false then
71 | gps_clk <= '0'; wait for gps_tgl;
72 | gps_clk <= '1'; wait for gps_tgl;
73 | else wait;
74 | end if;
75 | end process;
76 |
77 | ppsdds_gen : process
78 | begin
79 | if ENDSIM = false then
80 | ppsdds <= '0'; wait for ppsdds_tgl;
81 | ppsdds <= '1'; wait for ppsdds_tgl;
82 | else wait;
83 | end if;
84 | end process;
85 |
86 | g : configuration work.gpsif_top_sim
87 | generic map ( GPSIF_NC => GPSIF_NC,
88 | ANGLE_INI_OLD => ANGLE_INI_OLD )
89 | port map (
90 | clk => clk,
91 | rst => rst,
92 | gps_clk => gps_clk,
93 | gps_d => gps_d,
94 | ppsdds => ppsdds,
95 | blgps => blgps,
96 | dma => dma,
97 | intrpt => intrpt,
98 | bi => BIST_SCAN_NOP,
99 | bo => open,
100 | ring_i => RBUS_IDLE_9B,
101 | ring_o => open,
102 | bus_clk => bus_clk,
103 | db_i => db_i,
104 | db_o => db_o);
105 |
106 | data_input : process
107 | file FI : TEXT open read_mode is "tests/input.txt";
108 | variable LI : line;
109 | variable input : std_logic_vector(1 downto 0);
110 | begin
111 | -- gps signal input
112 | input_loop: while true loop
113 | if endfile(FI) then
114 | exit input_loop;
115 | end if;
116 | readline(FI, LI);
117 | read(LI, input(1 downto 0));
118 | gps_d <= input;
119 | wait until gps_clk = '1' and gps_clk'event;
120 | end loop;
121 | wait;
122 | end process;
123 |
124 | process
125 | file FI : TEXT open read_mode is "tests/input2.txt";
126 | variable LI : line;
127 | variable input : std_logic_vector(31 downto 0);
128 | variable last : std_logic_vector(31 downto 0) := (others => '0');
129 | variable sft_chg : integer range 0 to 1023 := 256;
130 | variable sft_ini : integer range 0 to 1023 := 256;
131 | variable set_inc : std_logic_vector(6 downto 0) := (others => '1');
132 | begin
133 | wait until bus_clk = '1' and bus_clk'event;
134 | wait until bus_clk = '1' and bus_clk'event;
135 | rst <= '0';
136 | wait until clk = '1' and clk'event;
137 | wait until clk = '1' and clk'event;
138 |
139 | test_plan((GPSIF_NC+6)*6, "gpsif_tb");
140 | -- write PNCO
141 | -- Values after increment will be for expected values.
142 | db_i <= ('1',x"ABCC0040",'0','1',x"F",x"00006058"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
143 | db_i <= ('1',x"ABCC0044",'0','1',x"F",x"fffd1f88"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
144 | db_i <= ('1',x"ABCC0048",'0','1',x"F",x"ffffe038"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
145 | db_i <= ('1',x"ABCC004c",'0','1',x"F",x"fffe5fd8"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus - minus*4 - inc
146 | db_i <= ('1',x"ABCC0050",'0','1',x"F",x"fffabef0"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
147 | db_i <= ('1',x"ABCC0054",'0','1',x"F",x"fffedff8"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
148 | db_i <= ('1',x"ABCC0058",'0','1',x"F",x"fffedff8"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
149 | db_i <= NULL_DATA_O;
150 | -- write SFT
151 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"00002b98"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
152 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"00007176"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
153 | db_i <= ('1',x"ABCC0008",'0','1',x"F",x"0000ae48"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
154 | db_i <= ('1',x"ABCC000c",'0','1',x"F",x"0000d637"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus - minus*4 - inc
155 | db_i <= ('1',x"ABCC0010",'0','1',x"F",x"00012a45"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
156 | db_i <= ('1',x"ABCC0014",'0','1',x"F",x"00017090"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
157 | db_i <= ('1',x"ABCC0018",'0','1',x"F",x"0001b090"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
158 | db_i <= NULL_DATA_O;
159 | -- write g2sft
160 | db_i <= ('1',x"ABCC0020",'0','1',x"F",x"00000006"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
161 | db_i <= ('1',x"ABCC0024",'0','1',x"F",x"0000001c"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
162 | db_i <= ('1',x"ABCC0028",'0','1',x"F",x"0000000b"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
163 | db_i <= ('1',x"ABCC002c",'0','1',x"F",x"00000064"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
164 | db_i <= ('1',x"ABCC0030",'0','1',x"F",x"00000200"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
165 | db_i <= ('1',x"ABCC0034",'0','1',x"F",x"000000d2"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
166 | db_i <= ('1',x"ABCC0038",'0','1',x"F",x"000000d2"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
167 | db_i <= NULL_DATA_O;
168 | -- correct SFT, increment PNCO
169 | db_i <= ('1',x"ABCC000c",'0','1',x"F",x"c0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus - minus*4 - inc
170 | db_i <= ('1',x"ABCC0014",'0','1',x"F",x"f0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
171 | db_i <= ('1',x"ABCC0018",'0','1',x"F",x"f0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
172 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"bcf00000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc 4, 1kHz
173 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"b0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
174 | db_i <= ('1',x"ABCC0008",'0','1',x"F",x"b0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
175 | db_i <= ('1',x"ABCC0010",'0','1',x"F",x"b0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc
176 |
177 | for j in 1 to 4 loop
178 | for i in 1 to 17 loop db_i <= NULL_DATA_O; wait until gps_clk = '1' and gps_clk'event; end loop;
179 | wait until bus_clk = '1' and bus_clk'event; -- adjust timing to bus_clk
180 | db_i <= ('1',x"ABCC000c",'0','1',x"F",x"e0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; end loop; -- plus - minus*4 - inc
181 | for i in 1 to 19 loop db_i <= NULL_DATA_O; wait until gps_clk = '1' and gps_clk'event; end loop;
182 | wait until bus_clk = '1' and bus_clk'event; -- adjust timing to bus_clk
183 | db_i <= ('1',x"ABCC000c",'0','1',x"F",x"b0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
184 | db_i <= NULL_DATA_O;
185 | -- Wait for end of execution
186 | for i in 1 to exe_cycles loop wait until gps_clk = '1' and gps_clk'event; chk_dma_req(dma); end loop;
187 | wait until bus_clk = '1' and bus_clk'event; -- adjust timing to bus_clk
188 | -- Check that same values seen in the waveform at the end of the gpsif_tb
189 | if ANGLE_INI_OLD then check_channel(bus_clk, db_o, db_i, 0, 13270, 7002, 19082, 42342, 21452, 25808);
190 | if(GPSIF_NC > 1) then check_channel(bus_clk, db_o, db_i, 1, 19610, -33416, 28814,-42980, 17464,-26782); end if;
191 | if(GPSIF_NC > 2) then check_channel(bus_clk, db_o, db_i, 2, 31701, -1218, 39655, 2086, 13683, 578); end if;
192 | if(GPSIF_NC > 3) then check_channel(bus_clk, db_o, db_i, 3, 18756, 3118, 33526, 1452, 8116,-17806); end if;
193 | if(GPSIF_NC > 4) then check_channel(bus_clk, db_o, db_i, 4, 41, 16785,-12169, 10099, -9071, 593); end if;
194 | if(GPSIF_NC > 5) then check_channel(bus_clk, db_o, db_i, 5, -2038, -1740, 8074, 23868, -6866, 22632); end if;
195 | if(GPSIF_NC > 6) then check_channel(bus_clk, db_o, db_i, 6, -2038, -1740, 8074, 23868, -6866, 22632); end if;
196 | else check_channel(bus_clk, db_o, db_i, 0, -7067, 13225,-42327, 19061,-25709, 21447);
197 | if(GPSIF_NC > 1) then check_channel(bus_clk, db_o, db_i, 1, 33477, 19603, 43079, 28829, 26827, 17517); end if;
198 | if(GPSIF_NC > 2) then check_channel(bus_clk, db_o, db_i, 2, 1206, 31727, -2054, 39687, -562, 13701); end if;
199 | if(GPSIF_NC > 3) then check_channel(bus_clk, db_o, db_i, 3, -3137, 18763, -1443, 33571, 17805, 8119); end if;
200 | if(GPSIF_NC > 4) then check_channel(bus_clk, db_o, db_i, 4,-16875, 59,-10147,-12217, -477, -9121); end if;
201 | if(GPSIF_NC > 5) then check_channel(bus_clk, db_o, db_i, 5, 1743, -2041,-23865, 8079,-22653, -6869); end if;
202 | if(GPSIF_NC > 6) then check_channel(bus_clk, db_o, db_i, 6, 1743, -2041,-23865, 8079,-22653, -6869); end if; end if;
203 | wait until bus_clk = '1' and bus_clk'event;
204 | wait until bus_clk = '1' and bus_clk'event;
205 |
206 | -- Reset to test the mode of CPU bus input
207 | db_i <= ('1',x"ABCC0060",'0','1',x"F",x"00000001"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
208 | -- write PNCO
209 | db_i <= ('1',x"ABCC0040",'0','1',x"F",x"00006058"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus
210 | db_i <= ('1',x"ABCC0044",'0','1',x"F",x"fffd1f88"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
211 | db_i <= ('1',x"ABCC0048",'0','1',x"F",x"0000e038"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
212 | db_i <= ('1',x"ABCC004c",'0','1',x"F",x"ffff5fd8"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
213 | db_i <= ('1',x"ABCC0050",'0','1',x"F",x"fffbbef0"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
214 | db_i <= ('1',x"ABCC0054",'0','1',x"F",x"ffffdff8"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
215 | db_i <= NULL_DATA_O;
216 | -- write SFT
217 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"00000007"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus
218 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"00000011"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
219 | db_i <= ('1',x"ABCC0008",'0','1',x"F",x"0000ae4c"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
220 | db_i <= ('1',x"ABCC000c",'0','1',x"F",x"0000d638"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
221 | db_i <= ('1',x"ABCC0010",'0','1',x"F",x"00012a49"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
222 | db_i <= ('1',x"ABCC0014",'0','1',x"F",x"0001708f"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
223 | db_i <= NULL_DATA_O;
224 | -- write g2sft
225 | db_i <= ('1',x"ABCC0020",'0','1',x"F",x"00000006"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus - minus
226 | db_i <= ('1',x"ABCC0024",'0','1',x"F",x"0000001c"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus - plus
227 | db_i <= ('1',x"ABCC0028",'0','1',x"F",x"0000000b"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
228 | db_i <= ('1',x"ABCC002c",'0','1',x"F",x"00000064"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
229 | db_i <= ('1',x"ABCC0030",'0','1',x"F",x"00000200"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
230 | db_i <= ('1',x"ABCC0034",'0','1',x"F",x"000000d2"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
231 | db_i <= NULL_DATA_O;
232 | input_loop: while true loop
233 | input := x"00000000";
234 | for j in 0 to 15 loop -- Read 32b data from 16 lines of 2b data
235 | if endfile(FI) then
236 | exit input_loop;
237 | end if;
238 | readline(FI, LI);
239 | read(LI, input(31 - 2*j downto 30 - 2*j));
240 | end loop;
241 | db_i <= ('1',x"ABCC0204",'0','1',x"F",input); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; chk_dma_req(dma);
242 | -- loop until status register allows input write
243 | write_ready: while true loop
244 | db_i <= ('1',x"ABCC0200",'1','0',x"F",x"00000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; chk_dma_req(dma);
245 | db_i <= NULL_DATA_O;
246 | if db_o.d(0) = '1' then
247 | exit write_ready;
248 | elsif sft_chg > 0 then
249 | sft_chg := sft_chg -1;
250 | if sft_chg = 128 then
251 | -- SFT +- 1
252 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"c0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus
253 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"e0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
254 | db_i <= NULL_DATA_O;
255 | elsif sft_chg = 0 then
256 | -- SFT -+ 1
257 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"e0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- minus
258 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"c0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- plus
259 | db_i <= NULL_DATA_O;
260 | end if;
261 | elsif sft_ini > 0 then
262 | sft_ini := sft_ini -1;
263 | if sft_ini = 0 then
264 | -- write SFT
265 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"00002b8c"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
266 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"0000716a"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
267 | db_i <= ('1',x"ABCC0000",'0','1',x"F",x"baf00000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc 16, inc 1kHz
268 | db_i <= ('1',x"ABCC0004",'0','1',x"F",x"b0000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- inc 16, inc 1kHz
269 | db_i <= ('1',x"ABCC0020",'0','1',x"F",x"00000006"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- reset C/A code
270 | db_i <= ('1',x"ABCC0024",'0','1',x"F",x"0000001c"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1'; -- reset C/A code
271 | db_i <= NULL_DATA_O;
272 | end if;
273 | end if;
274 | end loop;
275 | for j in 1 to INTERVAL-2 loop
276 | wait until bus_clk = '1' and bus_clk'event; chk_dma_req(dma);
277 | end loop;
278 | end loop;
279 | -- Check that same values seen in the waveform at the end of the gpsif_tb
280 | if ANGLE_INI_OLD then check_channel(bus_clk, db_o, db_i, 0, 13270, 7002, 19082, 42342, 21452, 25808);
281 | if(GPSIF_NC > 1) then check_channel(bus_clk, db_o, db_i, 1, 19610, -33416, 28814,-42980, 17464,-26782); end if;
282 | if(GPSIF_NC > 2) then check_channel(bus_clk, db_o, db_i, 2, 31701, -1218, 39655, 2086, 13683, 578); end if;
283 | if(GPSIF_NC > 3) then check_channel(bus_clk, db_o, db_i, 3, 18756, 3118, 33526, 1452, 8116,-17806); end if;
284 | if(GPSIF_NC > 4) then check_channel(bus_clk, db_o, db_i, 4, 41, 16785,-12169, 10099, -9071, 593); end if;
285 | if(GPSIF_NC > 5) then check_channel(bus_clk, db_o, db_i, 5, -2038, -1740, 8074, 23868, -6866, 22632); end if;
286 | else check_channel(bus_clk, db_o, db_i, 0, -7067, 13225,-42327, 19061,-25709, 21447);
287 | if(GPSIF_NC > 1) then check_channel(bus_clk, db_o, db_i, 1, 33477, 19603, 43079, 28829, 26827, 17517); end if;
288 | if(GPSIF_NC > 2) then check_channel(bus_clk, db_o, db_i, 2, 1206, 31727, -2054, 39687, -562, 13701); end if;
289 | if(GPSIF_NC > 3) then check_channel(bus_clk, db_o, db_i, 3, -3137, 18763, -1443, 33571, 17805, 8119); end if;
290 | if(GPSIF_NC > 4) then check_channel(bus_clk, db_o, db_i, 4,-16875, 59,-10147,-12217, -477, -9121); end if;
291 | if(GPSIF_NC > 5) then check_channel(bus_clk, db_o, db_i, 5, 1743, -2041,-23865, 8079,-22653, -6869); end if; end if;
292 |
293 | -- dump signals
294 | for i in 1 to 256 loop
295 | db_i <= ('1',x"ABCC0080",'1','0',x"F",x"00000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
296 | db_i <= ('1',x"ABCC00a0",'1','0',x"F",x"00000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
297 | db_i <= ('1',x"ABCC00c0",'1','0',x"F",x"00000000"); wait until bus_clk = '1' and bus_clk'event and db_o.ack = '1';
298 | end loop;
299 | db_i <= NULL_DATA_O;
300 |
301 | test_finished("done");
302 | ENDSIM := true;
303 | wait;
304 | end process;
305 |
306 | end architecture;
307 |
--------------------------------------------------------------------------------
/tests/gpsif_tb_pkg.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.std_logic_textio.all;
4 | use ieee.std_logic_unsigned.all;
5 | use ieee.numeric_std.all;
6 | use std.textio.all;
7 |
8 | use work.cpu2j0_pack.all;
9 | use work.gpsif_pack.all;
10 | use work.gpsif_sub_pack.all;
11 | use work.test_pkg.all;
12 |
13 | package gpsif_tb_pack is
14 | procedure chk_dma_req(dma : dma_req_t);
15 | procedure check_equal(
16 | signal clk : in std_logic;
17 | signal db_o : in cpu_data_i_t;
18 | signal db_i : out cpu_data_o_t;
19 | constant val,ch,ofs : integer;
20 | constant typ : string);
21 | procedure check_channel(
22 | signal clk : in std_logic;
23 | signal db_o : in cpu_data_i_t;
24 | signal db_i : out cpu_data_o_t;
25 | constant ch,ei,eq,pi,pq,li,lq : integer);
26 | end package;
27 |
28 | package body gpsif_tb_pack is
29 |
30 | procedure chk_dma_req(dma : dma_req_t) is
31 | variable LI : line;
32 | begin
33 | if dma.req(6) = '1' then
34 | write(LI, "DMA req. of ch #" & integer'image(to_integer(unsigned(dma.req(5 downto 0)))));
35 | writeline(output, LI);
36 | end if;
37 | end procedure;
38 |
39 | procedure check_equal(
40 | signal clk : in std_logic;
41 | signal db_o : in cpu_data_i_t;
42 | signal db_i : out cpu_data_o_t;
43 | constant val,ch,ofs : integer;
44 | constant typ : string) is
45 | begin
46 | db_i <= ('1',(std_logic_vector(to_unsigned(ch*8 + ofs,30)) & "00") or x"ABCC0100",'1','0',x"F",x"00000000");
47 | wait until clk = '1' and clk'event and db_o.ack = '1';
48 | test_equal(to_integer(signed(db_o.d)),val, typ & "(" & integer'image(ch) & ")");
49 | end procedure;
50 |
51 | procedure check_channel(
52 | signal clk : in std_logic;
53 | signal db_o : in cpu_data_i_t;
54 | signal db_i : out cpu_data_o_t;
55 | constant ch,ei,eq,pi,pq,li,lq : integer) is
56 | begin
57 | check_equal(clk,db_o,db_i,ei,ch,0,"E_I");
58 | check_equal(clk,db_o,db_i,eq,ch,1,"E_Q");
59 | check_equal(clk,db_o,db_i,pi,ch,2,"P_I");
60 | check_equal(clk,db_o,db_i,pq,ch,3,"P_Q");
61 | check_equal(clk,db_o,db_i,li,ch,4,"L_I");
62 | check_equal(clk,db_o,db_i,lq,ch,5,"L_Q");
63 | db_i <= NULL_DATA_O; wait until clk = '1' and clk'event;
64 | end procedure;
65 |
66 | end gpsif_tb_pack;
67 |
--------------------------------------------------------------------------------
/tests/gpsob/Makefile_gpsob:
--------------------------------------------------------------------------------
1 | VHDLS := VHDS
2 | include build.mk
3 |
4 | VHDS += tests/gpsob/gpsif_tb_gpsob.vhd
5 | VHDS += tests/gpsif_tb_pkg.vhd
6 | VHDS += tools/tests/tap/test_pkg.vhd
7 |
8 | VHDL_TESTS := gpsif_tb_gpsob
9 |
10 | # if gpsif repo is inside the soc_top repo, pull in other vhdl files
11 | # and build gpsif_tb
12 | MK_UTILS := $(wildcard ../../tools/mk_utils.mk)
13 | ifeq ($(MK_UTILS),)
14 | MK_UTILS := $(wildcard ../tools/mk_utils.mk)
15 | include $(MK_UTILS)
16 | VHDS += $(call include_vhdl,../lib/reg_file_struct)
17 | endif
18 | MK_UTILS := $(wildcard ../../tools/mk_utils.mk)
19 | ifneq ($(MK_UTILS),)
20 | include $(MK_UTILS)
21 | VHDS += $(call include_vhdl,../cpu)
22 | VHDS += $(call include_vhdl,../ring_bus)
23 | VHDS += $(call include_vhdl,../../lib/fixed_dsm_pkg)
24 | VHDS += $(call include_vhdl,../../lib/reg_file_struct)
25 | VHDS += $(call include_vhdl,../../lib/memory_tech_lib)
26 | VHDS += $(call include_vhdl,../../lib/hwutils)
27 | endif
28 |
29 | VHDL_TOPS += $(VHDL_TESTS)
30 |
31 | TOOLS_DIR := $(firstword $(wildcard ../../tools) tools)
32 |
33 | all: $(VHDL_TOPS)
34 |
35 | work-obj93.cf: $(VHDS)
36 |
37 | tests/gpsif_tb_gpsob.ghw: gpsif_tb_gpsob
38 | ./gpsif_tb_gpsob --wave=$@ --stop-time=2500us --ieee-asserts=disable
39 |
40 | RUNTESTS := $(TOOLS_DIR)/tests/runtests
41 | $(RUNTESTS):
42 | make -C $(dir $@)
43 |
44 | check: $(RUNTESTS) $(VHDL_TESTS)
45 | $(RUNTESTS) test_bins
46 |
47 | tap: $(RUNTESTS) $(VHDL_TESTS)
48 | $(RUNTESTS) -t test_bins
49 |
50 | include $(TOOLS_DIR)/ghdl.mk
51 |
52 | clean:
53 | rm -f *.cf *.o $(VHDL_TOPS) *_tap tests/*.ghw
54 | rm -f gpsif.vhd gpsif_reg.vhd cacode.vhd gpsif_db.vhd gpsif_buf.vhd rbus_adp.vhd
55 | make -C $(dir $(RUNTESTS)) clean
56 |
57 | .PHONY: all clean check tap
58 |
--------------------------------------------------------------------------------
/tests/gpsob/README:
--------------------------------------------------------------------------------
1 | READMEs
2 | for gps over bitlilnk RTL simulation
3 |
4 | # -- vector data creation
5 | cat input.txt input.txt > input3.txt
6 |
7 | # -- run simulation
8 | make -f tests/gpsob/Makefile_gpsob tests/gpsif_tb_gpsob.ghw
9 | (Makefile_gpsob specifies, 2500us)
10 |
11 | # -- pass judgement method (automatic compare is not coded)
12 | diff acm_bank set value of gpsif_tb.vhd (1ms - 2ms, set once)
13 | and
14 | acm_bank set value of gpsif_tb_gpsob.vhd (1ms - 2ms, set once)
15 | (2 bit sample)
16 |
17 | # -- pass judgement method (automatic compare is not coded)
18 | diff acm_bank set value of gpsif_tb.vhd (1ms - 2ms, set once)
19 | (here, modifiy input.txt to simulate 1 bit sample)
20 | and
21 | acm_bank set value of gpsif_tb_gpsob.vhd (1ms - 2ms, set once)
22 | (1 bit sample)
23 |
24 |
--------------------------------------------------------------------------------
/tests/output.golden:
--------------------------------------------------------------------------------
1 | RTL scilab(スケール)
2 | ch 0 E I 13270 13823.2636
3 | ch 0 E Q 7002 6369.74055
4 | ch 0 P I 19082 21596.543
5 | ch 0 P Q 42342 41015.6471
6 | ch 0 L I 21452 22581.9309
7 | ch 0 L Q 25808 24266.027
8 |
9 | ch 1 E I 19610 17864.0066
10 | ch 1 E Q -33416 -33986.9417
11 | ch 1 P I 28814 25953.9501
12 | ch 1 P Q -42980 -43525.8691
13 | ch 1 L I 17464 15713.9891
14 | ch 1 L Q -26782 -27500.4761
15 |
16 | ch 2 E I 31701 31199.4215
17 | ch 2 E Q -1218 -2660.5226
18 | ch 2 P I 39655 39390.571
19 | ch 2 P Q 2086 61.201696
20 | ch 2 L I 13683 13859.681
21 | ch 2 L Q 578 -404.860315
22 |
23 | ch 3 E I 18756 18320.9667
24 | ch 3 E Q 3118 2153.91711
25 | ch 3 P I 33526 33077.2592
26 | ch 3 P Q 1452 -313.385172
27 | ch 3 L I 8116 6667.05973
28 | ch 3 L Q -17806 -17659.9623
29 |
30 | ch 4 E I 41 1130.54181
31 | ch 4 E Q 16785 16447.2867
32 | ch 4 P I -12169 -11400.356
33 | ch 4 P Q 10099 10471.0422
34 | ch 4 L I -9071 -8735.83329
35 | ch 4 L Q 593 902.019975
36 |
37 | ch 5 E I -2038 -2132.58843
38 | ch 5 E Q -1740 -2110.0271
39 | ch 5 P I 8074 8891.66381
40 | ch 5 P Q 23868 23018.9347
41 | ch 5 L I -6866 -5457.77001
42 | ch 5 L Q 22632 22822.634
43 |
--------------------------------------------------------------------------------
/tools/common.mk:
--------------------------------------------------------------------------------
1 | # find v2p in directory this file is in
2 | V2P := $(dir $(lastword $(MAKEFILE_LIST)))v2p
3 |
4 | # depend on force to always convert files but convert to *.temp and
5 | # then use cmp || mv to avoid needlessly updating the timestamp and
6 | # causing unwanted rebuilds
7 |
8 | # override LD_LIBRARY_PATH when running v2p to avoid Xilinx's libraries
9 | # causing errors like this:
10 | # /usr/lib/gcc/i586-suse-linux/4.5/cc1: /opt/Xilinx/13.1/ISE_DS/common/lib/lin/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by /usr/lib/libppl_c.so.2)
11 |
12 | %.vhd: %.vhm force
13 | $(info Convert $< -> $@)
14 | @LD_LIBRARY_PATH='' perl $(V2P) < $< > $@.temp
15 | @cmp -s $@.temp $@ || mv $@.temp $@
16 | @rm -f $@.temp
17 |
18 | # vhmh lets us run a file through the preprocessor before v2p
19 | %.vhm: %.vhmh force
20 | $(info Convert $< -> $@)
21 | @LD_LIBRARY_PATH='' gcc -x c-header -E -P -w -nostdinc -I. -Iconfig $< -o $@.temp
22 | @cmp -s $@.temp $@ || mv $@.temp $@
23 | @rm -f $@.temp
24 |
25 | %.vhh: %.vhd force
26 | $(info Convert $< -> $@)
27 | @LD_LIBRARY_PATH='' gcc -x c-header -E -P -w -nostdinc -I. -Iconfig $< -o $@.temp
28 | @cmp -s $@.temp $@ || mv $@.temp $@
29 | @rm -f $@.temp
30 |
31 | .PHONY: force
32 |
--------------------------------------------------------------------------------
/tools/ghdl.mk:
--------------------------------------------------------------------------------
1 | # This is a makefile snippet useful for simulating with ghdl on both
2 | # Linux and OSX. On both platforms it will create a create an
3 | # executable file that can be used to run the simulation.
4 |
5 | # To use this, set VHDL_TOPS and optionally VHDL_LIBS (described
6 | # below), define the dependicies between the vhdl library file and vhd
7 | # files it will contain, and include this file.
8 |
9 | # For example:
10 | #
11 | # VHDL_TOPS := foo
12 | # work-obj93.cf: foo.vhd foo_pkg.vhd
13 | # include tools/ghdl.mk
14 | #
15 | # Variables that can be set to modify this files behaviour:
16 | # VHDL_TOPS = names of top entities that will be simulated
17 | # VHDL_LIBS = names of VHDL libraries. Defaults to "work"
18 |
19 | ifeq ($(VHDL_TOPS),)
20 | $(error Need to set VHDL_TOPS)
21 | endif
22 |
23 | include $(dir $(lastword $(MAKEFILE_LIST)))common.mk
24 |
25 | VHDL_LIBS ?= work
26 | VHDL_LIBS := $(addsuffix -obj93.cf,$(VHDL_LIBS))
27 |
28 | GHDL ?= ghdl
29 | GHDL_EXISTS := $(shell sh -c 'which $(GHDL) >/dev/null && echo true')
30 |
31 | ifeq ($(GHDL_EXISTS),true)
32 | %-obj93.cf:
33 | $(GHDL) -i --work=$* $(filter %.vhh %.vhd %.vhdl,$^)
34 |
35 | # look at ghdl --version output to determine backend generator type
36 | define check_backend
37 | (ghdl --version 2> /dev/null | grep -i "$(1).*generator" -q) && echo y
38 | endef
39 |
40 | GHDL_BACKEND_GCC := $(shell $(call check_backend,gcc))
41 | GHDL_BACKEND_LLVM := $(shell $(call check_backend,llvm))
42 | GHDL_BACKEND_MCODE := $(shell $(call check_backend,mcode))
43 |
44 | ifeq ($(GHDL_BACKEND_GCC)$(GHDL_BACKEND_LLVM),y)
45 | # for compiler backends, use -m to compile binaries for each top
46 | $(VHDL_TOPS): $(VHDL_LIBS)
47 | $(GHDL) -m -fexplicit --ieee=synopsys $@
48 | else
49 | ifeq ($(GHDL_BACKEND_MCODE),y)
50 | # With an mcode backend, create wrapper scripts that compile and run
51 | # the test benches
52 | $(VHDL_TOPS): $(VHDL_LIBS)
53 | echo "#!/bin/sh" > $@
54 | echo 'ghdl -c -fexplicit --ieee=synopsys -r $@ $$@' >> $@
55 | chmod +x $@
56 | else
57 | $(error Unrecognized GHDL backend)
58 | endif
59 | endif
60 |
61 | endif
62 |
63 | #clean::
64 | # -$(GHDL) --remove
65 | # rm -f *.lst
66 |
--------------------------------------------------------------------------------
/tools/tests/Makefile:
--------------------------------------------------------------------------------
1 |
2 | CFLAGS += -Wall
3 |
4 | runtests: runtests.o
5 |
6 | clean:
7 | rm -f runtests *.o
8 |
--------------------------------------------------------------------------------
/tools/tests/tap/basic.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Some utility routines for writing tests.
3 | *
4 | * Here are a variety of utility routines for writing tests compatible with
5 | * the TAP protocol. All routines of the form ok() or is*() take a test
6 | * number and some number of appropriate arguments, check to be sure the
7 | * results match the expected output using the arguments, and print out
8 | * something appropriate for that test number. Other utility routines help in
9 | * constructing more complex tests, skipping tests, reporting errors, setting
10 | * up the TAP output format, or finding things in the test environment.
11 | *
12 | * This file is part of C TAP Harness. The current version plus supporting
13 | * documentation is at .
14 | *
15 | * Copyright 2009, 2010, 2011, 2012 Russ Allbery
16 | * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
17 | * The Board of Trustees of the Leland Stanford Junior University
18 | *
19 | * Permission is hereby granted, free of charge, to any person obtaining a
20 | * copy of this software and associated documentation files (the "Software"),
21 | * to deal in the Software without restriction, including without limitation
22 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
23 | * and/or sell copies of the Software, and to permit persons to whom the
24 | * Software is furnished to do so, subject to the following conditions:
25 | *
26 | * The above copyright notice and this permission notice shall be included in
27 | * all copies or substantial portions of the Software.
28 | *
29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
32 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35 | * DEALINGS IN THE SOFTWARE.
36 | */
37 |
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #ifdef _WIN32
44 | # include
45 | #else
46 | # include
47 | #endif
48 | #include
49 | #include
50 | #include
51 |
52 | #include
53 |
54 | /* Windows provides mkdir and rmdir under different names. */
55 | #ifdef _WIN32
56 | # define mkdir(p, m) _mkdir(p)
57 | # define rmdir(p) _rmdir(p)
58 | #endif
59 |
60 | /*
61 | * The test count. Always contains the number that will be used for the next
62 | * test status.
63 | */
64 | unsigned long testnum = 1;
65 |
66 | /*
67 | * Status information stored so that we can give a test summary at the end of
68 | * the test case. We store the planned final test and the count of failures.
69 | * We can get the highest test count from testnum.
70 | *
71 | * We also store the PID of the process that called plan() and only summarize
72 | * results when that process exits, so as to not misreport results in forked
73 | * processes.
74 | *
75 | * If _lazy is true, we're doing lazy planning and will print out the plan
76 | * based on the last test number at the end of testing.
77 | */
78 | static unsigned long _planned = 0;
79 | static unsigned long _failed = 0;
80 | static pid_t _process = 0;
81 | static int _lazy = 0;
82 |
83 | static FILE *output;;
84 |
85 | /*
86 | * Our exit handler. Called on completion of the test to report a summary of
87 | * results provided we're still in the original process. This also handles
88 | * printing out the plan if we used plan_lazy(), although that's suppressed if
89 | * we never ran a test (due to an early bail, for example).
90 | */
91 | static void
92 | finish(void)
93 | {
94 | unsigned long highest = testnum - 1;
95 |
96 | if (_planned == 0 && !_lazy)
97 | return;
98 | fflush(stderr);
99 | if (_process != 0 && getpid() == _process) {
100 | if (_lazy && highest > 0) {
101 | fprintf(output, "1..%lu\n", highest);
102 | _planned = highest;
103 | }
104 | if (_planned > highest)
105 | fprintf(output, "# Looks like you planned %lu test%s but only ran %lu\n",
106 | _planned, (_planned > 1 ? "s" : ""), highest);
107 | else if (_planned < highest)
108 | fprintf(output, "# Looks like you planned %lu test%s but ran %lu extra\n",
109 | _planned, (_planned > 1 ? "s" : ""), highest - _planned);
110 | else if (_failed > 0)
111 | fprintf(output, "# Looks like you failed %lu test%s of %lu\n", _failed,
112 | (_failed > 1 ? "s" : ""), _planned);
113 | else if (_planned > 1)
114 | fprintf(output, "# All %lu tests successful or skipped\n", _planned);
115 | else
116 | fprintf(output, "# %lu test successful or skipped\n", _planned);
117 | }
118 | }
119 |
120 | static void init_tap_file(void) {
121 | output = stdout;
122 | char *tap_path = getenv("TAP_FILE");
123 | if (tap_path) {
124 | output = fopen(tap_path, "w");
125 | if (output == 0) {
126 | fprintf(stderr, "# cannot open TAP file \"%s\" for writting: %s\n",
127 | tap_path, strerror(errno));
128 | exit(1);
129 | }
130 | }
131 | }
132 |
133 | /*
134 | * Initialize things. Turns on line buffering on stdout and then prints out
135 | * the number of tests in the test suite.
136 | */
137 | void
138 | plan(unsigned long count)
139 | {
140 | init_tap_file();
141 | if (setvbuf(output, NULL, _IOLBF, BUFSIZ) != 0)
142 | fprintf(stderr, "# cannot set output to line buffered: %s\n",
143 | strerror(errno));
144 | fflush(stderr);
145 | fprintf(output, "1..%lu\n", count);
146 | testnum = 1;
147 | _planned = count;
148 | _process = getpid();
149 | atexit(finish);
150 | }
151 |
152 |
153 | /*
154 | * Initialize things for lazy planning, where we'll automatically print out a
155 | * plan at the end of the program. Turns on line buffering on stdout as well.
156 | */
157 | void
158 | plan_lazy(void)
159 | {
160 | init_tap_file();
161 | if (setvbuf(output, NULL, _IOLBF, BUFSIZ) != 0)
162 | fprintf(stderr, "# cannot set output to line buffered: %s\n",
163 | strerror(errno));
164 | testnum = 1;
165 | _process = getpid();
166 | _lazy = 1;
167 | atexit(finish);
168 | }
169 |
170 |
171 | /*
172 | * Skip the entire test suite and exits. Should be called instead of plan(),
173 | * not after it, since it prints out a special plan line.
174 | */
175 | void
176 | skip_all(const char *format, ...)
177 | {
178 | fflush(stderr);
179 | fprintf(output, "1..0 # skip");
180 | if (format != NULL) {
181 | va_list args;
182 |
183 | putchar(' ');
184 | va_start(args, format);
185 | vfprintf(output, format, args);
186 | va_end(args);
187 | }
188 | putchar('\n');
189 | exit(0);
190 | }
191 |
192 |
193 | /*
194 | * Print the test description.
195 | */
196 | static void
197 | print_desc(const char *format, va_list args)
198 | {
199 | fprintf(output, " - ");
200 | vfprintf(output, format, args);
201 | }
202 |
203 |
204 | /*
205 | * Takes a boolean success value and assumes the test passes if that value
206 | * is true and fails if that value is false.
207 | */
208 | void
209 | ok(int success, const char *format, ...)
210 | {
211 | fflush(stderr);
212 | fprintf(output, "%sok %lu", success ? "" : "not ", testnum++);
213 | if (!success)
214 | _failed++;
215 | if (format != NULL) {
216 | va_list args;
217 |
218 | va_start(args, format);
219 | print_desc(format, args);
220 | va_end(args);
221 | }
222 | putchar('\n');
223 | }
224 |
225 |
226 | /*
227 | * Same as ok(), but takes the format arguments as a va_list.
228 | */
229 | void
230 | okv(int success, const char *format, va_list args)
231 | {
232 | fflush(stderr);
233 | fprintf(output, "%sok %lu", success ? "" : "not ", testnum++);
234 | if (!success)
235 | _failed++;
236 | if (format != NULL)
237 | print_desc(format, args);
238 | putchar('\n');
239 | }
240 |
241 |
242 | /*
243 | * Skip a test.
244 | */
245 | void
246 | skip(const char *reason, ...)
247 | {
248 | fflush(stderr);
249 | fprintf(output, "ok %lu # skip", testnum++);
250 | if (reason != NULL) {
251 | va_list args;
252 |
253 | va_start(args, reason);
254 | putchar(' ');
255 | vfprintf(output, reason, args);
256 | va_end(args);
257 | }
258 | putchar('\n');
259 | }
260 |
261 |
262 | /*
263 | * Report the same status on the next count tests.
264 | */
265 | void
266 | ok_block(unsigned long count, int status, const char *format, ...)
267 | {
268 | unsigned long i;
269 |
270 | fflush(stderr);
271 | for (i = 0; i < count; i++) {
272 | fprintf(output, "%sok %lu", status ? "" : "not ", testnum++);
273 | if (!status)
274 | _failed++;
275 | if (format != NULL) {
276 | va_list args;
277 |
278 | va_start(args, format);
279 | print_desc(format, args);
280 | va_end(args);
281 | }
282 | putchar('\n');
283 | }
284 | }
285 |
286 |
287 | /*
288 | * Skip the next count tests.
289 | */
290 | void
291 | skip_block(unsigned long count, const char *reason, ...)
292 | {
293 | unsigned long i;
294 |
295 | fflush(stderr);
296 | for (i = 0; i < count; i++) {
297 | fprintf(output, "ok %lu # skip", testnum++);
298 | if (reason != NULL) {
299 | va_list args;
300 |
301 | va_start(args, reason);
302 | putchar(' ');
303 | vfprintf(output, reason, args);
304 | va_end(args);
305 | }
306 | putchar('\n');
307 | }
308 | }
309 |
310 |
311 | /*
312 | * Takes an expected integer and a seen integer and assumes the test passes
313 | * if those two numbers match.
314 | */
315 | void
316 | is_int(long wanted, long seen, const char *format, ...)
317 | {
318 | fflush(stderr);
319 | if (wanted == seen)
320 | fprintf(output, "ok %lu", testnum++);
321 | else {
322 | fprintf(output, "# wanted: %ld\n# seen: %ld\n", wanted, seen);
323 | fprintf(output, "not ok %lu", testnum++);
324 | _failed++;
325 | }
326 | if (format != NULL) {
327 | va_list args;
328 |
329 | va_start(args, format);
330 | print_desc(format, args);
331 | va_end(args);
332 | }
333 | putchar('\n');
334 | }
335 |
336 |
337 | /*
338 | * Takes a string and what the string should be, and assumes the test passes
339 | * if those strings match (using strcmp).
340 | */
341 | void
342 | is_string(const char *wanted, const char *seen, const char *format, ...)
343 | {
344 | if (wanted == NULL)
345 | wanted = "(null)";
346 | if (seen == NULL)
347 | seen = "(null)";
348 | fflush(stderr);
349 | if (strcmp(wanted, seen) == 0)
350 | fprintf(output, "ok %lu", testnum++);
351 | else {
352 | fprintf(output, "# wanted: %s\n# seen: %s\n", wanted, seen);
353 | fprintf(output, "not ok %lu", testnum++);
354 | _failed++;
355 | }
356 | if (format != NULL) {
357 | va_list args;
358 |
359 | va_start(args, format);
360 | print_desc(format, args);
361 | va_end(args);
362 | }
363 | putchar('\n');
364 | }
365 |
366 |
367 | /*
368 | * Takes an expected unsigned long and a seen unsigned long and assumes the
369 | * test passes if the two numbers match. Otherwise, reports them in hex.
370 | */
371 | void
372 | is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
373 | {
374 | fflush(stderr);
375 | if (wanted == seen)
376 | fprintf(output, "ok %lu", testnum++);
377 | else {
378 | fprintf(output, "# wanted: %lx\n# seen: %lx\n", (unsigned long) wanted,
379 | (unsigned long) seen);
380 | fprintf(output, "not ok %lu", testnum++);
381 | _failed++;
382 | }
383 | if (format != NULL) {
384 | va_list args;
385 |
386 | va_start(args, format);
387 | print_desc(format, args);
388 | va_end(args);
389 | }
390 | putchar('\n');
391 | }
392 |
393 |
394 | /*
395 | * Bail out with an error.
396 | */
397 | void
398 | bail(const char *format, ...)
399 | {
400 | va_list args;
401 |
402 | fflush(stderr);
403 | fflush(output);
404 | fprintf(output, "Bail out! ");
405 | va_start(args, format);
406 | vfprintf(output, format, args);
407 | va_end(args);
408 | fprintf(output, "\n");
409 | exit(1);
410 | }
411 |
412 |
413 | /*
414 | * Bail out with an error, appending strerror(errno).
415 | */
416 | void
417 | sysbail(const char *format, ...)
418 | {
419 | va_list args;
420 | int oerrno = errno;
421 |
422 | fflush(stderr);
423 | fflush(output);
424 | fprintf(output, "Bail out! ");
425 | va_start(args, format);
426 | vfprintf(output, format, args);
427 | va_end(args);
428 | fprintf(output, ": %s\n", strerror(oerrno));
429 | exit(1);
430 | }
431 |
432 |
433 | /*
434 | * Report a diagnostic to stderr.
435 | */
436 | void
437 | diag(const char *format, ...)
438 | {
439 | va_list args;
440 |
441 | fflush(stderr);
442 | fflush(output);
443 | fprintf(output, "# ");
444 | va_start(args, format);
445 | vfprintf(output, format, args);
446 | va_end(args);
447 | fprintf(output, "\n");
448 | }
449 |
450 |
451 | /*
452 | * Report a diagnostic to stderr, appending strerror(errno).
453 | */
454 | void
455 | sysdiag(const char *format, ...)
456 | {
457 | va_list args;
458 | int oerrno = errno;
459 |
460 | fflush(stderr);
461 | fflush(output);
462 | fprintf(output, "# ");
463 | va_start(args, format);
464 | vfprintf(output, format, args);
465 | va_end(args);
466 | fprintf(output, ": %s\n", strerror(oerrno));
467 | }
468 |
469 |
470 | /*
471 | * Allocate cleared memory, reporting a fatal error with bail on failure.
472 | */
473 | void *
474 | bcalloc(size_t n, size_t size)
475 | {
476 | void *p;
477 |
478 | p = calloc(n, size);
479 | if (p == NULL)
480 | sysbail("failed to calloc %lu", (unsigned long)(n * size));
481 | return p;
482 | }
483 |
484 |
485 | /*
486 | * Allocate memory, reporting a fatal error with bail on failure.
487 | */
488 | void *
489 | bmalloc(size_t size)
490 | {
491 | void *p;
492 |
493 | p = malloc(size);
494 | if (p == NULL)
495 | sysbail("failed to malloc %lu", (unsigned long) size);
496 | return p;
497 | }
498 |
499 |
500 | /*
501 | * Reallocate memory, reporting a fatal error with bail on failure.
502 | */
503 | void *
504 | brealloc(void *p, size_t size)
505 | {
506 | p = realloc(p, size);
507 | if (p == NULL)
508 | sysbail("failed to realloc %lu bytes", (unsigned long) size);
509 | return p;
510 | }
511 |
512 |
513 | /*
514 | * Copy a string, reporting a fatal error with bail on failure.
515 | */
516 | char *
517 | bstrdup(const char *s)
518 | {
519 | char *p;
520 | size_t len;
521 |
522 | len = strlen(s) + 1;
523 | p = malloc(len);
524 | if (p == NULL)
525 | sysbail("failed to strdup %lu bytes", (unsigned long) len);
526 | memcpy(p, s, len);
527 | return p;
528 | }
529 |
530 |
531 | /*
532 | * Copy up to n characters of a string, reporting a fatal error with bail on
533 | * failure. Don't use the system strndup function, since it may not exist and
534 | * the TAP library doesn't assume any portability support.
535 | */
536 | char *
537 | bstrndup(const char *s, size_t n)
538 | {
539 | const char *p;
540 | char *copy;
541 | size_t length;
542 |
543 | /* Don't assume that the source string is nul-terminated. */
544 | for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
545 | ;
546 | length = p - s;
547 | copy = malloc(length + 1);
548 | if (p == NULL)
549 | sysbail("failed to strndup %lu bytes", (unsigned long) length);
550 | memcpy(copy, s, length);
551 | copy[length] = '\0';
552 | return copy;
553 | }
554 |
555 |
556 | /*
557 | * Locate a test file. Given the partial path to a file, look under BUILD and
558 | * then SOURCE for the file and return the full path to the file. Returns
559 | * NULL if the file doesn't exist. A non-NULL return should be freed with
560 | * test_file_path_free().
561 | *
562 | * This function uses sprintf because it attempts to be independent of all
563 | * other portability layers. The use immediately after a memory allocation
564 | * should be safe without using snprintf or strlcpy/strlcat.
565 | */
566 | char *
567 | test_file_path(const char *file)
568 | {
569 | char *base;
570 | char *path = NULL;
571 | size_t length;
572 | const char *envs[] = { "BUILD", "SOURCE", NULL };
573 | int i;
574 |
575 | for (i = 0; envs[i] != NULL; i++) {
576 | base = getenv(envs[i]);
577 | if (base == NULL)
578 | continue;
579 | length = strlen(base) + 1 + strlen(file) + 1;
580 | path = bmalloc(length);
581 | sprintf(path, "%s/%s", base, file);
582 | if (access(path, R_OK) == 0)
583 | break;
584 | free(path);
585 | path = NULL;
586 | }
587 | return path;
588 | }
589 |
590 |
591 | /*
592 | * Free a path returned from test_file_path(). This function exists primarily
593 | * for Windows, where memory must be freed from the same library domain that
594 | * it was allocated from.
595 | */
596 | void
597 | test_file_path_free(char *path)
598 | {
599 | if (path != NULL)
600 | free(path);
601 | }
602 |
603 |
604 | /*
605 | * Create a temporary directory, tmp, under BUILD if set and the current
606 | * directory if it does not. Returns the path to the temporary directory in
607 | * newly allocated memory, and calls bail on any failure. The return value
608 | * should be freed with test_tmpdir_free.
609 | *
610 | * This function uses sprintf because it attempts to be independent of all
611 | * other portability layers. The use immediately after a memory allocation
612 | * should be safe without using snprintf or strlcpy/strlcat.
613 | */
614 | char *
615 | test_tmpdir(void)
616 | {
617 | const char *build;
618 | char *path = NULL;
619 | size_t length;
620 |
621 | build = getenv("BUILD");
622 | if (build == NULL)
623 | build = ".";
624 | length = strlen(build) + strlen("/tmp") + 1;
625 | path = bmalloc(length);
626 | sprintf(path, "%s/tmp", build);
627 | if (access(path, X_OK) < 0)
628 | if (mkdir(path, 0777) < 0)
629 | sysbail("error creating temporary directory %s", path);
630 | return path;
631 | }
632 |
633 |
634 | /*
635 | * Free a path returned from test_tmpdir() and attempt to remove the
636 | * directory. If we can't delete the directory, don't worry; something else
637 | * that hasn't yet cleaned up may still be using it.
638 | */
639 | void
640 | test_tmpdir_free(char *path)
641 | {
642 | rmdir(path);
643 | if (path != NULL)
644 | free(path);
645 | }
646 |
--------------------------------------------------------------------------------
/tools/tests/tap/basic.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Basic utility routines for the TAP protocol.
3 | *
4 | * This file is part of C TAP Harness. The current version plus supporting
5 | * documentation is at .
6 | *
7 | * Copyright 2009, 2010, 2011, 2012 Russ Allbery
8 | * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
9 | * The Board of Trustees of the Leland Stanford Junior University
10 | *
11 | * Permission is hereby granted, free of charge, to any person obtaining a
12 | * copy of this software and associated documentation files (the "Software"),
13 | * to deal in the Software without restriction, including without limitation
14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 | * and/or sell copies of the Software, and to permit persons to whom the
16 | * Software is furnished to do so, subject to the following conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be included in
19 | * all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 | * DEALINGS IN THE SOFTWARE.
28 | */
29 |
30 | #ifndef TAP_BASIC_H
31 | #define TAP_BASIC_H 1
32 |
33 | #include
34 | #include /* va_list */
35 | #include /* size_t */
36 |
37 | /*
38 | * Used for iterating through arrays. ARRAY_SIZE returns the number of
39 | * elements in the array (useful for a < upper bound in a for loop) and
40 | * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
41 | * legal to refer to such a pointer as long as it's never dereferenced).
42 | */
43 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
44 | #define ARRAY_END(array) (&(array)[ARRAY_SIZE(array)])
45 |
46 | BEGIN_DECLS
47 |
48 | /*
49 | * The test count. Always contains the number that will be used for the next
50 | * test status.
51 | */
52 | extern unsigned long testnum;
53 |
54 | /* Print out the number of tests and set standard output to line buffered. */
55 | void plan(unsigned long count);
56 |
57 | /*
58 | * Prepare for lazy planning, in which the plan will be printed automatically
59 | * at the end of the test program.
60 | */
61 | void plan_lazy(void);
62 |
63 | /* Skip the entire test suite. Call instead of plan. */
64 | void skip_all(const char *format, ...)
65 | __attribute__((__noreturn__, __format__(printf, 1, 2)));
66 |
67 | /*
68 | * Basic reporting functions. The okv() function is the same as ok() but
69 | * takes the test description as a va_list to make it easier to reuse the
70 | * reporting infrastructure when writing new tests.
71 | */
72 | void ok(int success, const char *format, ...)
73 | __attribute__((__format__(printf, 2, 3)));
74 | void okv(int success, const char *format, va_list args);
75 | void skip(const char *reason, ...)
76 | __attribute__((__format__(printf, 1, 2)));
77 |
78 | /* Report the same status on, or skip, the next count tests. */
79 | void ok_block(unsigned long count, int success, const char *format, ...)
80 | __attribute__((__format__(printf, 3, 4)));
81 | void skip_block(unsigned long count, const char *reason, ...)
82 | __attribute__((__format__(printf, 2, 3)));
83 |
84 | /* Check an expected value against a seen value. */
85 | void is_int(long wanted, long seen, const char *format, ...)
86 | __attribute__((__format__(printf, 3, 4)));
87 | void is_string(const char *wanted, const char *seen, const char *format, ...)
88 | __attribute__((__format__(printf, 3, 4)));
89 | void is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
90 | __attribute__((__format__(printf, 3, 4)));
91 |
92 | /* Bail out with an error. sysbail appends strerror(errno). */
93 | void bail(const char *format, ...)
94 | __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
95 | void sysbail(const char *format, ...)
96 | __attribute__((__noreturn__, __nonnull__, __format__(printf, 1, 2)));
97 |
98 | /* Report a diagnostic to stderr prefixed with #. */
99 | void diag(const char *format, ...)
100 | __attribute__((__nonnull__, __format__(printf, 1, 2)));
101 | void sysdiag(const char *format, ...)
102 | __attribute__((__nonnull__, __format__(printf, 1, 2)));
103 |
104 | /* Allocate memory, reporting a fatal error with bail on failure. */
105 | void *bcalloc(size_t, size_t)
106 | __attribute__((__alloc_size__(1, 2), __malloc__));
107 | void *bmalloc(size_t)
108 | __attribute__((__alloc_size__(1), __malloc__));
109 | void *brealloc(void *, size_t)
110 | __attribute__((__alloc_size__(2), __malloc__));
111 | char *bstrdup(const char *)
112 | __attribute__((__malloc__, __nonnull__));
113 | char *bstrndup(const char *, size_t)
114 | __attribute__((__malloc__, __nonnull__));
115 |
116 | /*
117 | * Find a test file under BUILD or SOURCE, returning the full path. The
118 | * returned path should be freed with test_file_path_free().
119 | */
120 | char *test_file_path(const char *file)
121 | __attribute__((__malloc__, __nonnull__));
122 | void test_file_path_free(char *path);
123 |
124 | /*
125 | * Create a temporary directory relative to BUILD and return the path. The
126 | * returned path should be freed with test_tmpdir_free.
127 | */
128 | char *test_tmpdir(void)
129 | __attribute__((__malloc__));
130 | void test_tmpdir_free(char *path);
131 |
132 | END_DECLS
133 |
134 | #endif /* TAP_BASIC_H */
135 |
--------------------------------------------------------------------------------
/tools/tests/tap/libtap.sh:
--------------------------------------------------------------------------------
1 | # Shell function library for test cases.
2 | #
3 | # Note that while many of the functions in this library could benefit from
4 | # using "local" to avoid possibly hammering global variables, Solaris /bin/sh
5 | # doesn't support local and this library aspires to be portable to Solaris
6 | # Bourne shell. Instead, all private variables are prefixed with "tap_".
7 | #
8 | # This file provides a TAP-compatible shell function library useful for
9 | # writing test cases. It is part of C TAP Harness, which can be found at
10 | # .
11 | #
12 | # Written by Russ Allbery
13 | # Copyright 2009, 2010, 2011, 2012 Russ Allbery
14 | # Copyright 2006, 2007, 2008
15 | # The Board of Trustees of the Leland Stanford Junior University
16 | #
17 | # Permission is hereby granted, free of charge, to any person obtaining a copy
18 | # of this software and associated documentation files (the "Software"), to
19 | # deal in the Software without restriction, including without limitation the
20 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
21 | # sell copies of the Software, and to permit persons to whom the Software is
22 | # furnished to do so, subject to the following conditions:
23 | #
24 | # The above copyright notice and this permission notice shall be included in
25 | # all copies or substantial portions of the Software.
26 | #
27 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 | # IN THE SOFTWARE.
34 |
35 | # Print out the number of test cases we expect to run.
36 | plan () {
37 | count=1
38 | planned="$1"
39 | failed=0
40 | echo "1..$1"
41 | trap finish 0
42 | }
43 |
44 | # Prepare for lazy planning.
45 | plan_lazy () {
46 | count=1
47 | planned=0
48 | failed=0
49 | trap finish 0
50 | }
51 |
52 | # Report the test status on exit.
53 | finish () {
54 | tap_highest=`expr "$count" - 1`
55 | if [ "$planned" = 0 ] ; then
56 | echo "1..$tap_highest"
57 | planned="$tap_highest"
58 | fi
59 | tap_looks='# Looks like you'
60 | if [ "$planned" -gt 0 ] ; then
61 | if [ "$planned" -gt "$tap_highest" ] ; then
62 | if [ "$planned" -gt 1 ] ; then
63 | echo "$tap_looks planned $planned tests but only ran" \
64 | "$tap_highest"
65 | else
66 | echo "$tap_looks planned $planned test but only ran" \
67 | "$tap_highest"
68 | fi
69 | elif [ "$planned" -lt "$tap_highest" ] ; then
70 | tap_extra=`expr "$tap_highest" - "$planned"`
71 | if [ "$planned" -gt 1 ] ; then
72 | echo "$tap_looks planned $planned tests but ran" \
73 | "$tap_extra extra"
74 | else
75 | echo "$tap_looks planned $planned test but ran" \
76 | "$tap_extra extra"
77 | fi
78 | elif [ "$failed" -gt 0 ] ; then
79 | if [ "$failed" -gt 1 ] ; then
80 | echo "$tap_looks failed $failed tests of $planned"
81 | else
82 | echo "$tap_looks failed $failed test of $planned"
83 | fi
84 | elif [ "$planned" -gt 1 ] ; then
85 | echo "# All $planned tests successful or skipped"
86 | else
87 | echo "# $planned test successful or skipped"
88 | fi
89 | fi
90 | }
91 |
92 | # Skip the entire test suite. Should be run instead of plan.
93 | skip_all () {
94 | tap_desc="$1"
95 | if [ -n "$tap_desc" ] ; then
96 | echo "1..0 # skip $tap_desc"
97 | else
98 | echo "1..0 # skip"
99 | fi
100 | exit 0
101 | }
102 |
103 | # ok takes a test description and a command to run and prints success if that
104 | # command is successful, false otherwise. The count starts at 1 and is
105 | # updated each time ok is printed.
106 | ok () {
107 | tap_desc="$1"
108 | if [ -n "$tap_desc" ] ; then
109 | tap_desc=" - $tap_desc"
110 | fi
111 | shift
112 | if "$@" ; then
113 | echo ok "$count$tap_desc"
114 | else
115 | echo not ok "$count$tap_desc"
116 | failed=`expr $failed + 1`
117 | fi
118 | count=`expr $count + 1`
119 | }
120 |
121 | # Skip the next test. Takes the reason why the test is skipped.
122 | skip () {
123 | echo "ok $count # skip $*"
124 | count=`expr $count + 1`
125 | }
126 |
127 | # Report the same status on a whole set of tests. Takes the count of tests,
128 | # the description, and then the command to run to determine the status.
129 | ok_block () {
130 | tap_i=$count
131 | tap_end=`expr $count + $1`
132 | shift
133 | while [ "$tap_i" -lt "$tap_end" ] ; do
134 | ok "$@"
135 | tap_i=`expr $tap_i + 1`
136 | done
137 | }
138 |
139 | # Skip a whole set of tests. Takes the count and then the reason for skipping
140 | # the test.
141 | skip_block () {
142 | tap_i=$count
143 | tap_end=`expr $count + $1`
144 | shift
145 | while [ "$tap_i" -lt "$tap_end" ] ; do
146 | skip "$@"
147 | tap_i=`expr $tap_i + 1`
148 | done
149 | }
150 |
151 | # Portable variant of printf '%s\n' "$*". In the majority of cases, this
152 | # function is slower than printf, because the latter is often implemented
153 | # as a builtin command. The value of the variable IFS is ignored.
154 | #
155 | # This macro must not be called via backticks inside double quotes, since this
156 | # will result in bizarre escaping behavior and lots of extra backslashes on
157 | # Solaris.
158 | puts () {
159 | cat << EOH
160 | $@
161 | EOH
162 | }
163 |
164 | # Run a program expected to succeed, and print ok if it does and produces the
165 | # correct output. Takes the description, expected exit status, the expected
166 | # output, the command to run, and then any arguments for that command.
167 | # Standard output and standard error are combined when analyzing the output of
168 | # the command.
169 | #
170 | # If the command may contain system-specific error messages in its output,
171 | # add strip_colon_error before the command to post-process its output.
172 | ok_program () {
173 | tap_desc="$1"
174 | shift
175 | tap_w_status="$1"
176 | shift
177 | tap_w_output="$1"
178 | shift
179 | tap_output=`"$@" 2>&1`
180 | tap_status=$?
181 | if [ $tap_status = $tap_w_status ] \
182 | && [ x"$tap_output" = x"$tap_w_output" ] ; then
183 | ok "$tap_desc" true
184 | else
185 | echo "# saw: ($tap_status) $tap_output"
186 | echo "# not: ($tap_w_status) $tap_w_output"
187 | ok "$tap_desc" false
188 | fi
189 | }
190 |
191 | # Strip a colon and everything after it off the output of a command, as long
192 | # as that colon comes after at least one whitespace character. (This is done
193 | # to avoid stripping the name of the program from the start of an error
194 | # message.) This is used to remove system-specific error messages (coming
195 | # from strerror, for example).
196 | strip_colon_error() {
197 | tap_output=`"$@" 2>&1`
198 | tap_status=$?
199 | tap_output=`puts "$tap_output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
200 | puts "$tap_output"
201 | return $tap_status
202 | }
203 |
204 | # Bail out with an error message.
205 | bail () {
206 | echo 'Bail out!' "$@"
207 | exit 1
208 | }
209 |
210 | # Output a diagnostic on standard error, preceded by the required # mark.
211 | diag () {
212 | echo '#' "$@"
213 | }
214 |
215 | # Search for the given file first in $BUILD and then in $SOURCE and echo the
216 | # path where the file was found, or the empty string if the file wasn't
217 | # found.
218 | #
219 | # This macro uses puts, so don't run it using backticks inside double quotes
220 | # or bizarre quoting behavior will happen with Solaris sh.
221 | test_file_path () {
222 | if [ -n "$BUILD" ] && [ -f "$BUILD/$1" ] ; then
223 | puts "$BUILD/$1"
224 | elif [ -n "$SOURCE" ] && [ -f "$SOURCE/$1" ] ; then
225 | puts "$SOURCE/$1"
226 | else
227 | echo ''
228 | fi
229 | }
230 |
231 | # Create $BUILD/tmp for use by tests for storing temporary files and return
232 | # the path (via standard output).
233 | #
234 | # This macro uses puts, so don't run it using backticks inside double quotes
235 | # or bizarre quoting behavior will happen with Solaris sh.
236 | test_tmpdir () {
237 | if [ -z "$BUILD" ] ; then
238 | tap_tmpdir="./tmp"
239 | else
240 | tap_tmpdir="$BUILD"/tmp
241 | fi
242 | if [ ! -d "$tap_tmpdir" ] ; then
243 | mkdir "$tap_tmpdir" || bail "Error creating $tap_tmpdir"
244 | fi
245 | puts "$tap_tmpdir"
246 | }
247 |
--------------------------------------------------------------------------------
/tools/tests/tap/macros.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Helpful macros for TAP header files.
3 | *
4 | * This is not, strictly speaking, related to TAP, but any TAP add-on is
5 | * probably going to need these macros, so define them in one place so that
6 | * everyone can pull them in.
7 | *
8 | * This file is part of C TAP Harness. The current version plus supporting
9 | * documentation is at .
10 | *
11 | * Copyright 2008, 2012 Russ Allbery
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a
14 | * copy of this software and associated documentation files (the "Software"),
15 | * to deal in the Software without restriction, including without limitation
16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 | * and/or sell copies of the Software, and to permit persons to whom the
18 | * Software is furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 | * DEALINGS IN THE SOFTWARE.
30 | */
31 |
32 | #ifndef TAP_MACROS_H
33 | #define TAP_MACROS_H 1
34 |
35 | /*
36 | * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
37 | * could you use the __format__ form of the attributes, which is what we use
38 | * (to avoid confusion with other macros), and only with gcc 2.96 can you use
39 | * the attribute __malloc__. 2.96 is very old, so don't bother trying to get
40 | * the other attributes to work with GCC versions between 2.7 and 2.96.
41 | */
42 | #ifndef __attribute__
43 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
44 | # define __attribute__(spec) /* empty */
45 | # endif
46 | #endif
47 |
48 | /*
49 | * We use __alloc_size__, but it was only available in fairly recent versions
50 | * of GCC. Suppress warnings about the unknown attribute if GCC is too old.
51 | * We know that we're GCC at this point, so we can use the GCC variadic macro
52 | * extension, which will still work with versions of GCC too old to have C99
53 | * variadic macro support.
54 | */
55 | #if !defined(__attribute__) && !defined(__alloc_size__)
56 | # if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
57 | # define __alloc_size__(spec, args...) /* empty */
58 | # endif
59 | #endif
60 |
61 | /*
62 | * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
63 | * settings that GCC does. For them, suppress warnings about unknown
64 | * attributes on declarations. This unfortunately will affect the entire
65 | * compilation context, but there's no push and pop available.
66 | */
67 | #if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
68 | # pragma GCC diagnostic ignored "-Wattributes"
69 | #endif
70 |
71 | /* Used for unused parameters to silence gcc warnings. */
72 | #define UNUSED __attribute__((__unused__))
73 |
74 | /*
75 | * BEGIN_DECLS is used at the beginning of declarations so that C++
76 | * compilers don't mangle their names. END_DECLS is used at the end.
77 | */
78 | #undef BEGIN_DECLS
79 | #undef END_DECLS
80 | #ifdef __cplusplus
81 | # define BEGIN_DECLS extern "C" {
82 | # define END_DECLS }
83 | #else
84 | # define BEGIN_DECLS /* empty */
85 | # define END_DECLS /* empty */
86 | #endif
87 |
88 | #endif /* TAP_MACROS_H */
89 |
--------------------------------------------------------------------------------
/tools/tests/tap/test_pkg.vhd:
--------------------------------------------------------------------------------
1 | -- Copyright © 2010 Wesley J. Landaker
2 | --
3 | -- This program is free software: you can redistribute it and/or modify
4 | -- it under the terms of the GNU General Public License as published by
5 | -- the Free Software Foundation, either version 3 of the License, or
6 | -- (at your option) any later version.
7 |
8 | --
9 | -- This program is distributed in the hope that it will be useful,
10 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | -- GNU General Public License for more details.
13 | --
14 | -- You should have received a copy of the GNU General Public License
15 | -- along with this program. If not, see .
16 |
17 | -- Output is standard TAP (Test Anything Protocol) version 13
18 | library ieee;
19 | use ieee.std_logic_1164.all;
20 | use ieee.numeric_std.all;
21 | use std.textio.all;
22 | use ieee.std_logic_textio.all;
23 |
24 | package test_pkg is
25 |
26 | function remove_eol(s : string) return string;
27 | procedure init;
28 | procedure test_redirect(filename : string);
29 | procedure test_plan(tests : natural; directive : string := "");
30 | procedure test_abort(reason : string);
31 | procedure test_finished(directive : string := "");
32 | procedure test_comment (message : string);
33 | procedure test_comment_fail (actual,expected : std_logic_vector);
34 | procedure test_pass (description : string := ""; directive : string := "");
35 | procedure test_fail (description : string := ""; directive : string := "");
36 | procedure test_ok (result : boolean; description : string := ""; directive : string := "");
37 | procedure test_equal(actual, expected : integer; description : string := ""; directive : string := "");
38 |
39 | procedure test_equal(actual, expected : std_logic_vector; description : string := ""; directive : string := "");
40 | procedure test_equal(actual, expected : std_logic; description : string := ""; directive : string := "");
41 | function slv(i,s : integer) return std_logic_vector;
42 | function slv(i : integer) return std_logic_vector;
43 | end package;
44 |
45 |
46 |
47 | package body test_pkg is
48 |
49 | file test_output : text;
50 | shared variable initialized : boolean := false;
51 | shared variable have_plan : boolean := false;
52 | shared variable last_test_number : natural := 0;
53 |
54 | function slv(i,s : integer) return std_logic_vector is
55 | variable r : std_logic_vector(s-1 downto 0);
56 | begin
57 | r := std_logic_vector(to_signed(i, s));
58 | return r;
59 | end function slv;
60 |
61 | function slv(i : integer) return std_logic_vector is
62 | begin
63 | return slv(i, 32);
64 | end function slv;
65 |
66 | function remove_eol(s : string) return string is
67 | variable s_no_eol : string(s'range);
68 | begin
69 | for i in s'range loop
70 | case s(i) is
71 | when LF | CR => s_no_eol(i) := '_';
72 | when others => s_no_eol(i) := s(i);
73 | end case;
74 | end loop;
75 | return s_no_eol;
76 | end function;
77 |
78 | function make_safe (s : string) return string is
79 | variable s_no_hash : string(s'range);
80 | begin
81 | for i in s'range loop
82 | case s(i) is
83 | when '#' => s_no_hash(i) := '_';
84 | when others => s_no_hash(i) := s(i);
85 | end case;
86 | end loop;
87 | return remove_eol(s_no_hash);
88 | end function;
89 |
90 | procedure init is
91 | variable l : line;
92 | begin
93 | if initialized then
94 | return;
95 | end if;
96 | initialized := true;
97 | write(l, string'("TAP version 13"));
98 | writeline(output, l);
99 | end procedure;
100 |
101 | procedure test_redirect(filename : string) is
102 | begin
103 | init;
104 | end procedure;
105 |
106 | procedure test_plan(tests : natural; directive : string := "") is
107 | variable l : line;
108 | begin
109 | init;
110 | have_plan := true;
111 | write(l, string'("1.."));
112 | write(l, tests);
113 | if directive'length > 0 then
114 | write(l, " # " & remove_eol(directive));
115 | end if;
116 | writeline(output, l);
117 | end procedure;
118 |
119 | procedure test_abort(reason : string) is
120 | variable l : line;
121 | begin
122 | init;
123 | write(l, "Bail out! " & remove_eol(reason));
124 | writeline(test_output, l);
125 | assert false
126 | report "abort called"
127 | severity failure;
128 | end procedure;
129 |
130 | procedure test_finished (directive : string := "") is
131 | begin
132 | if not have_plan then
133 | test_plan(last_test_number, directive);
134 | elsif directive'length > 0 then
135 | test_comment("1.." & integer'image(last_test_number) & " # " & directive);
136 | else
137 | test_comment("1.." & integer'image(last_test_number));
138 | end if;
139 | end procedure;
140 |
141 | procedure test_comment (message : string) is
142 | variable l : line;
143 | begin
144 | init;
145 | write(l, '#');
146 | if message'length > 0 then
147 | write(l, " " & remove_eol(message));
148 | end if;
149 | writeline(output, l);
150 | end procedure;
151 |
152 | procedure test_comment_fail (actual,expected : std_logic_vector) is
153 | variable l : line;
154 | begin
155 | init;
156 | if actual'length mod 4 = 0 and expected'length mod 4 = 0 then
157 | write(l, string'("# actual is x"));
158 | hwrite(l, actual);
159 | write(l, string'(" expected is x"));
160 | hwrite(l,expected);
161 | else
162 | write(l, string'("# actual is "));
163 | write(l, actual);
164 | write(l, string'(" expected is "));
165 | write(l,expected);
166 | end if;
167 | writeline(output, l);
168 | end procedure;
169 |
170 | procedure result (status : string; description : string; directive : string) is
171 | variable l : line;
172 | begin
173 | init;
174 | last_test_number := last_test_number + 1;
175 | write(l, status & " ");
176 | write(l, last_test_number);
177 | if description'length > 0 then
178 | write(l, " " & make_safe(description));
179 | end if;
180 | if directive'length > 0 then
181 | write(l, " # " & remove_eol(directive));
182 | end if;
183 | writeline(output, l);
184 | end procedure;
185 |
186 | procedure test_pass (description : string := ""; directive : string := "") is
187 | begin
188 | result("ok", description, directive);
189 | end procedure;
190 |
191 | procedure test_fail (description : string := ""; directive : string := "") is
192 | begin
193 | result("not ok", description, directive);
194 | end procedure;
195 |
196 | procedure test_ok (result : boolean; description : string := ""; directive : string := "") is
197 | begin
198 | if result then
199 | test_pass(description, directive);
200 | else
201 | test_fail(description, directive);
202 | end if;
203 | end procedure;
204 |
205 | procedure test_equal(actual, expected : integer; description : string := ""; directive : string := "") is
206 | variable ok : boolean := actual = expected;
207 | begin
208 | test_ok(ok, description, directive);
209 | if not ok then
210 | test_comment("actual = " & integer'image(actual) & ", expected = " & integer'image(expected));
211 | end if;
212 | end procedure;
213 |
214 | procedure test_equal(actual, expected : std_logic_vector;
215 | description : string := ""; directive : string := "") is
216 | variable ok : boolean := actual = expected;
217 | begin
218 | if actual'length /= expected'length then
219 | test_comment_fail(actual,expected);
220 | test_comment("vector length mismatch");
221 | test_ok(false, description, directive);
222 | else
223 | test_ok(ok, description, directive);
224 | if not ok then
225 | test_comment_fail(actual,expected);
226 | end if;
227 | end if;
228 | end procedure;
229 |
230 | procedure test_equal(actual, expected : std_logic; description : string := ""; directive : string := "") is
231 | variable ok : boolean := actual = expected;
232 | begin
233 | test_ok(ok, description, directive);
234 | end procedure;
235 |
236 | end package body;
237 |
--------------------------------------------------------------------------------
/tools/v2p:
--------------------------------------------------------------------------------
1 | #!/opt/local/bin/perl
2 |
3 | # here is an ugly, straight forward C like attempt to parse .vhm 2 process
4 | # templates into clean VHDL. It might break, behave badly or even work.
5 |
6 | use feature ":5.10";
7 |
8 | use strict;
9 | use IPC::Open2;
10 |
11 | # The state of the input, corresponds to entity, architecture, process...
12 | my $state = "none";
13 | my $old_state = "none";
14 | my $white = "";
15 |
16 | # register variables and their attibutes from the arch decl
17 | my @regvar = ();
18 | my @regvar_type = ();
19 | my @regvar_rst = ();
20 |
21 | # strict wants these
22 | my ($i, $j, $line_valid, $entity);
23 | my (@list, @list_r);
24 | my ($old_white, $comment, $args);
25 | my ($arch, $sense);
26 | my ($rst_cond, $process, $regvar, $procvar, $clk_sig, $clk_cond, $rst_sig, $rst_sync);
27 | my (@procvar, @procvar_rst, @procvar_rsync, @procvar_clk);
28 |
29 | my @diversion = ();
30 | my @out = ();
31 |
32 | while()
33 | {
34 | my $line = $_;
35 | chomp($line);
36 | $line_valid = "yes";
37 |
38 | # Separate the initial whitespace and comments from the code
39 | if ($line =~ m/^(\s*)(.*)(--.*)*$/) {
40 | $old_white = $white;
41 | $white = $1;
42 | $line = $2;
43 | $comment = $3;
44 | }
45 |
46 | # transformations go here, based on the current parser state
47 | given($state) {
48 | when ("none") {
49 | # look for entity and record the name
50 | if ($line =~ m/^(entity)(\s+)(\w+)(\s*.*)$/i) {
51 | $state = "entity";
52 | $entity = lc($3);
53 | }
54 | }
55 | when ("entity") {
56 | # find the end of the entity section (well specified or not)
57 | if ($line =~ m/^(end)([\s+|;])(\w*)(\s*.*)$/i) {
58 | if (lc($3) eq $entity or lc($3) eq "entity" or lc($2) eq ";") {
59 | $state = "s_arch";
60 | }
61 | }
62 | }
63 | when ("s_arch") {
64 | # look architecture declariation and check the entity name
65 | if ($line =~ m/^(architecture)(\s+)(\w+)(\s+of\s+)(\w+)(\s*.*)$/i) {
66 | if (lc($5) eq $entity) {
67 | $arch = lc($3);
68 | $state = "arch";
69 | }
70 | }
71 | }
72 | when ("arch") {
73 | # look for the start of the architecture body
74 | if ($line =~ m/^(begin)(\s*.*)$/i) {
75 | $state = "body";
76 | }
77 | # look for 'register variables' and insert signals for them
78 | if ($line =~ m/^(register)(\s+)(variable)(\s+)(\w+)(\s+)(:)(\s*)(.+)(\s+)(reset)(\s*)(:=)(\s*)(.+)(\s*);$/i) {
79 | push(@diversion, $white . "signal" . $2. $5 . "_c" . $6 . ":" . $8 . $9 . ";");
80 | $line = "signal$2$5_r$6:$8$9;";
81 | push(@regvar, $5);
82 | push(@regvar_type, $9);
83 | push(@regvar_rst, $15);
84 | }
85 | }
86 | when ("body") {
87 | # find the end of the architecture body (well specified or not)
88 | if ($line =~ m/^(end)(\s+)(\w+)(\s*.*)$/i) {
89 | if (lc($3) eq $arch or lc($3) eq "architecture") {
90 | @regvar = ();
91 | @regvar_type = ();
92 | @regvar_rst = ();
93 | $state = "none";
94 | }
95 | }
96 | # find processes
97 | if ($line =~ m/^(\w*)(\s*:\s*)*(process)(\s*.*)$/i) {
98 | $line = "$1$2$3";
99 | $process = $1;
100 | $sense = $4;
101 | if ($sense =~ m/^(\s*)\(([\w\s,]*)\)(\s*.*)$/i) {
102 | # parse the sensitivity list and add in the signals for register vars
103 | @list = split(',', $2);
104 | @list_r = ();
105 | foreach $i (@list) {
106 | if (grep {$_ eq $i} @regvar) {
107 | push(@list_r, $i . "_r");
108 | } else {
109 | push(@list_r, $i);
110 | }
111 | }
112 | $args = join(',', @list_r);
113 | $line = "$line$1($args)$4";
114 | } else {
115 | # empty sensitivity list
116 | $line = "$line()$4";
117 | }
118 | @procvar = ();
119 | @procvar_rst = ();
120 | @procvar_rsync = ();
121 | @procvar_clk = ();
122 | $state = "s_process";
123 | }
124 | }
125 | when ("s_process") {
126 | # look for register var register and reset conditions
127 | if ($line =~ m/^(register)(\s+)(\w+)(\s+)(when)(\s+)(.+)(\s+)(reset)(\s*)(sync)?(\s+)(when)(\s+)(.*);$/i) {
128 | $clk_cond = $7;
129 | $rst_sync = $11;
130 | $rst_cond = $15;
131 | push(@procvar, $3);
132 | push(@procvar_rst, $rst_cond);
133 | push(@procvar_rsync, $rst_sync);
134 | push(@procvar_clk, $clk_cond);
135 |
136 | $line_valid = "";
137 | $j = 0;
138 | foreach $regvar(@regvar) {
139 | if ($regvar[$j] eq $3) {
140 | push(@diversion, $white . "variable " . $3 . " : " . $regvar_type[$j] . ";");
141 | }
142 | $j++;
143 | }
144 | }
145 | # look for the start of the process body
146 | if ($line =~ m/^(begin)(\s*.*)$/i) {
147 | $state = "process";
148 | push(@diversion, $white . $line . $comment);
149 | $i = 0;
150 | foreach $procvar(@procvar) {
151 | push(@diversion, $white . " " . $procvar[$i] . " := " . $procvar[$i] . "_r;");
152 | $i++;
153 | }
154 | if ($i>0) {
155 | push(@diversion, "");
156 | }
157 | $line_valid = "";
158 | }
159 | }
160 | when ("process") {
161 | # find the end of the process body
162 | if ($line =~ m/^(end)(\s+)(\w+)(\s*.*)$/i) {
163 | if (lc($3) eq "process") {
164 | $state = "body";
165 | $line_valid = "";
166 |
167 | push(@diversion, "");
168 | foreach $procvar(@procvar) {
169 | push(@diversion, $old_white . $procvar . "_c <= " . $procvar . ";");
170 | }
171 | push(@diversion, $white . $line . $comment);
172 |
173 | $i = 0;
174 | foreach $procvar(@procvar) {
175 |
176 | $j = 0;
177 | foreach $regvar(@regvar) {
178 | if ($regvar[$j] eq $procvar[$i]) {
179 | $rst_cond = $regvar_rst[$j];
180 | }
181 | $j++;
182 | }
183 |
184 | push(@diversion, "");
185 | $procvar_clk[$i] =~ m/^(\s*)(\w+)/;
186 | $clk_sig = $2;
187 |
188 | $procvar_rst[$i] =~ m/^(\s*)(\w+)/;
189 | $rst_sig = $2;
190 |
191 | push(@diversion, $white . $process . "_r" . $i . " : process(" . $clk_sig . ", " . $rst_sig . ")");
192 | push(@diversion, $white . "begin");
193 |
194 | if ($procvar_rsync[$i] =~ m/sync.*/i) {
195 | push(@diversion, $white . " if " . $procvar_clk[$i] . " then");
196 | push(@diversion, $white . " if " . $procvar_rst[$i] . " then");
197 | push(@diversion, $white . " " . $procvar[$i] . "_r <= " . $rst_cond . ";");
198 | push(@diversion, $white . " else");
199 | push(@diversion, $white . " " . $procvar[$i] . "_r <= " . $procvar[$i] . "_c;");
200 | push(@diversion, $white . " end if;");
201 | push(@diversion, $white . " end if;");
202 | push(@diversion, $white . "end process;");
203 | } else {
204 | push(@diversion, $white . " if " . $procvar_rst[$i] . " then");
205 | push(@diversion, $white . " " . $procvar[$i] . "_r <= " . $rst_cond . ";");
206 | push(@diversion, $white . " elsif " . $procvar_clk[$i] . " then");
207 | push(@diversion, $white . " " . $procvar[$i] . "_r <= " . $procvar[$i] . "_c;");
208 | push(@diversion, $white . " end if;");
209 | push(@diversion, $white . "end process;");
210 | }
211 | $i++;
212 | }
213 | }
214 | }
215 | }
216 | }
217 |
218 | if ($state ne $old_state) {
219 | foreach $i (@diversion) {
220 | #print "$i\n";
221 | push @out => $i;
222 | }
223 | @diversion = ();
224 | $old_state = $state;
225 | }
226 | # look for register or comb attribute, replace it. FIXME: wrong place, no error checking.
227 | if ($line_valid eq "yes") {
228 | $line =~ s/(\w)\'register/$1_r/gi;
229 | $line =~ s/(\w)\'combinatorial/$1_c/gi;
230 | $line =~ s/(\w)\'comb/$1_c/gi;
231 | push(@diversion, "$white$line$comment");
232 | }
233 | }
234 |
235 | foreach $i (@diversion) {
236 | #print "$i\n";
237 | push @out => $i;
238 | }
239 | #my $count = 1;
240 | #printf("-- %03d: %s\n", $count++, $_) for @out;
241 |
242 | my($chld_out, $chld_in);
243 | #my $pid = open2($chld_out, $chld_in, 'cpp -w -P -nostdinc -I.');
244 | my $pid = open2($chld_out, $chld_in, 'gcc -E -P -x c -nostdinc -DVHDL -I. -');
245 | print $chld_in join("\n" => @out); close($chld_in);
246 | my @cpp_out = <$chld_out>;
247 | waitpid( $pid, 0 ); close($chld_out);
248 | my $child_exit_status = $? >> 8;
249 |
250 | for(@cpp_out) {
251 | next if $_ =~ /^#/;
252 | print;
253 | }
254 |
--------------------------------------------------------------------------------