├── .gitignore
├── Makefile
├── README.md
├── bench
├── cpp
│ ├── .gitignore
│ ├── Makefile
│ ├── autotest.cpp
│ ├── testb.h
│ ├── testbus_tb.cpp
│ ├── trace.gtkw
│ ├── uartsim.cpp
│ ├── uartsim.h
│ └── vversion.sh
├── formal
│ ├── .gitignore
│ ├── faxil_master.v
│ └── fwb_master.v
└── rtl
│ ├── Makefile
│ ├── memdev.v
│ ├── quikbus.v
│ ├── rxuartlite.v
│ ├── testbus.v
│ ├── txuartlite.v
│ └── wbscope.v
├── doc
├── Makefile
├── gpl-3.0.pdf
├── lgpl-3.0.pdf
└── src
│ ├── gpl-3.0.tex
│ └── lgpl-3.0.tex
├── hexbus
├── README.md
├── bench
│ └── formal
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ ├── fwb_master.v
│ │ ├── hbexec.sby
│ │ ├── hbexecaxi.gtkw
│ │ ├── hbexecaxi.sby
│ │ ├── hbints.sby
│ │ └── hbnewline.sby
├── rtl
│ ├── console.v
│ ├── hbaxil.v
│ ├── hbbus.v
│ ├── hbconsole.v
│ ├── hbdechex.v
│ ├── hbdeword.v
│ ├── hbexec.v
│ ├── hbexecaxi.v
│ ├── hbgenhex.v
│ ├── hbidle.v
│ ├── hbints.v
│ ├── hbnewline.v
│ └── hbpack.v
└── sw
│ ├── hexbus.cpp
│ └── hexbus.h
└── sw
├── Makefile
├── devbus.h
├── llcomms.cpp
├── llcomms.h
├── memscope.cpp
├── netuart.cpp
├── port.h
├── regdefs.cpp
├── regdefs.h
├── scopecls.cpp
├── scopecls.h
└── wbregs.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | legal.txt
2 | .svn
3 | xilinx
4 | obj_dir
5 | obj-pc
6 | obj-zip
7 | *.o
8 | *.a
9 | *.vcd
10 | .swp
11 | .*.swp
12 | .*.swo
13 | svn-commit*
14 | *_tb
15 | *_tb.dbl
16 | *dbg.txt
17 | *dump.txt
18 | *debug.txt
19 | tags
20 | cpudefs.h
21 | design.h
22 | octave-workspace
23 | memscope
24 | netuart
25 | wbregs
26 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: Makefile
4 | ## {{{
5 | ## Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | ##
7 | ## Purpose: A master project makefile. It tries to build all targets
8 | ## within the project, mostly by directing subdirectory makes.
9 | ##
10 | ##
11 | ## Creator: Dan Gisselquist, Ph.D.
12 | ## Gisselquist Technology, LLC
13 | ##
14 | ################################################################################
15 | ## }}}
16 | ## Copyright (C) 2015-2024, Gisselquist Technology, LLC
17 | ## {{{
18 | ## This file is part of the debugging interface demonstration.
19 | ##
20 | ## The debugging interface demonstration is free software (firmware): you can
21 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
22 | ## Public License as published by the Free Software Foundation, either version
23 | ## 3 of the License, or (at your option) any later version.
24 | ##
25 | ## This debugging interface demonstration is distributed in the hope that it
26 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
27 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
28 | ## General Public License
29 | ## for more details.
30 | ##
31 | ## You should have received a copy of the GNU Lesser General Public License
32 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | ## with no target there if the PDF file isn't present.) If not, see
34 | ## for a copy.
35 | ## }}}
36 | ## License: LGPL, v3, as defined and found on www.gnu.org,
37 | ## {{{
38 | ## http://www.gnu.org/licenses/lgpl.html
39 | ##
40 | ################################################################################
41 | ##
42 | ## }}}
43 | # Make certain the "all" target is the first and therefore the default target
44 | .PHONY: all
45 | all: rtl sim sw itest
46 | #
47 | SUBMAKE:= $(MAKE) --no-print-directory -C
48 |
49 | #
50 | #
51 | # Check that we have all the programs available to us that we need
52 | #
53 | #
54 | .PHONY: check-install
55 | check-install: check-verilator check-gpp
56 |
57 | .PHONY: check-verilator
58 | check-verilator:
59 | $(call checkif-installed,verilator,-V)
60 |
61 | .PHONY: check-gpp
62 | check-gpp:
63 | $(call checkif-installed,g++,-v)
64 |
65 | #
66 | #
67 | # Verify that the rtl has no bugs in it, while also creating a Verilator
68 | # simulation class library that we can then use for simulation
69 | #
70 | .PHONY: verilated
71 | verilated: check-verilator
72 | +@$(SUBMAKE) bench/rtl
73 |
74 | .PHONY: rtl
75 | rtl: verilated
76 |
77 | #
78 | #
79 | # Build a simulation of this entire design
80 | #
81 | .PHONY: sim
82 | sim: rtl check-gpp
83 | +@$(SUBMAKE) bench/cpp
84 |
85 | #
86 | #
87 | # Run a scripted test of what would be interactive, were the post to be followed
88 | #
89 | .PHONY: itest
90 | itest: sim
91 | +@$(SUBMAKE) bench/cpp test
92 |
93 | #
94 | #
95 | # Build the host support software
96 | #
97 | .PHONY: sw
98 | sw: check-gpp
99 | +@$(SUBMAKE) sw
100 |
101 | #
102 | #
103 | # Check if the given program is installed
104 | #
105 | define checkif-installed
106 | @bash -c '$(1) $(2) < /dev/null >& /dev/null; if [[ $$? != 0 ]]; then echo "Program not found: $(1)"; exit -1; fi'
107 | endef
108 |
109 |
110 | .PHONY: clean
111 | clean:
112 | +$(SUBMAKE) bench/rtl clean
113 | +$(SUBMAKE) bench/cpp clean
114 | +$(SUBMAKE) sw clean
115 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Debug Bus Interface(s)
2 |
3 | This depository consists of a series of debugging bus interfaces.
4 |
5 | Each interface connects an external debug port, whether UART, SPI, JTAG, or
6 | RPI Parallel port, to the master port of a wishbone
7 | bus. Hence, the debug interface allows you access to any device located on
8 | the wishbone bus--both to read from and write to that bus.
9 |
10 | It is my intention to use the various components of each of the busses as
11 | teaching tools on the [ZipCPU blog](http://zipcpu.com). Indeed, if you
12 | look at the [topics page of the blog](http://zipcpu.com/topics.html), you'll
13 | see that the series is now complete.
14 |
15 | ## License
16 |
17 | All of the files in this repository are licensed by either GPLv3 or the LGPL.
18 | For example, the simple [HEXBUS](/hexbus) interface is licensed under the LGPL, whereas
19 | the other interfaces are (or will be) licensed under GPL.
20 | Should the license provided be insufficient for your needs, please feel free
21 | to contact me for the terms necessary for a more appropriate license.
22 |
23 |
24 |
--------------------------------------------------------------------------------
/bench/cpp/.gitignore:
--------------------------------------------------------------------------------
1 | autotest
2 | testbus_tb
3 |
--------------------------------------------------------------------------------
/bench/cpp/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: bench/cpp/Makefile
4 | ## {{{
5 | ## Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | ##
7 | ## Purpose: To direct the final build of the bench testing (verilator)
8 | ## simulation program.
9 | ##
10 | ## Creator: Dan Gisselquist, Ph.D.
11 | ## Gisselquist Technology, LLC
12 | ##
13 | ################################################################################
14 | ## }}}
15 | ## Copyright (C) 2015-2024, Gisselquist Technology, LLC
16 | ## {{{
17 | ## This file is part of the debugging interface demonstration.
18 | ##
19 | ## The debugging interface demonstration is free software (firmware): you can
20 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
21 | ## Public License as published by the Free Software Foundation, either version
22 | ## 3 of the License, or (at your option) any later version.
23 | ##
24 | ## This debugging interface demonstration is distributed in the hope that it
25 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
26 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
27 | ## General Public License
28 | ## for more details.
29 | ##
30 | ## You should have received a copy of the GNU Lesser General Public License
31 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
32 | ## with no target there if the PDF file isn't present.) If not, see
33 | ## for a copy.
34 | ## }}}
35 | ## License: LGPL, v3, as defined and found on www.gnu.org,
36 | ## {{{
37 | ## http://www.gnu.org/licenses/lgpl.html
38 | ##
39 | ################################################################################
40 | ##
41 | ## }}}
42 | # Make certain the "all" target is the first and therefore the default target
43 | .PHONY: all
44 | all:
45 | # we'll fill in what "all" references in a moment
46 | #
47 | # Set up some variables
48 | CXX := g++
49 | # Cross compilation has taught me to use an object file directory that can be
50 | # adjusted to reference one machine or another.
51 | OBJDIR := obj-pc
52 | # Our bench/rtl directory ...
53 | RTLD := ../rtl
54 | # This has the obj_dir subdirectory within it
55 | VOBJDR := $(RTLD)/obj_dir
56 | # We need to figure out the VERILATOR_ROOT variable. This will tell us where
57 | # all the Grab it from Verilator -V.
58 | VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"')
59 | VROOT := $(VERILATOR_ROOT)
60 | VINCD := $(VROOT)/include
61 | VINC := -I$(VINCD) -I$(VOBJDR) -I../../sw/host -I../../sw
62 | # We'll need to build these two Verilater files, and include them with our
63 | # build
64 | VSRCRAW := verilated.cpp verilated_vcd_c.cpp verilated_threads.cpp
65 | VSRC := $(addprefix $(VINCD)/,$(VSRCRAW))
66 | VOBJ := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(VSRCRAW)))
67 | INCS := $(VINC)
68 | CFLAGS := -Og -g -faligned-new -Wall $(INCS)
69 | #
70 | BUS := hexbus
71 | SUBMAKE := $(MAKE) --no-print-directory -C
72 |
73 | # A list of our sources and headers. These are used by the dependency generator
74 | # below
75 | TBSOURCES := testbus_tb.cpp uartsim.cpp
76 | SOURCES := $(TBSOURCES) autotest.cpp
77 | TBHEADERS := $(foreach header,$(subst .cpp,.h,$(TBSOURCES)),$(wildcard $(header)))
78 | TBOBJECTS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(TBSOURCES))) $(VOBJ)
79 | AUTOSRC := autotest.cpp uartsim.cpp
80 | AUTOHDR := $(foreach header,$(subst .cpp,.h,$(AUTOSRC)),$(wildcard $(header)))
81 | AUTOOBJ := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(AUTOSRC))) $(VOBJ)
82 | #
83 | PROGRAMS := testbus_tb autotest
84 | #
85 | # Now the return to the default/"all" target, and fill in some details
86 | all: $(PROGRAMS) test
87 |
88 | #
89 | # Generic build instructions for object files
90 | $(OBJDIR)/%.o: %.cpp
91 | $(mk-objdir)
92 | $(CXX) $(CFLAGS) -c $< -o $@
93 |
94 | #
95 | # And we'll repeat those instructions for building object files from sources
96 | # within the Verilator directory found within $(VERILATOR_ROOT)
97 | $(OBJDIR)/%.o: $(VINCD)/%.cpp
98 | $(mk-objdir)
99 | $(CXX) $(CFLAGS) -c $< -o $@
100 |
101 | #
102 | # Build our actual target. Note the dependency on the $(OBJECTS) list of
103 | # object files above
104 | testbus_tb: $(TBOBJECTS) $(VOBJDR)/Vtestbus__ALL.a
105 | $(CXX) $(CFLAGS) $(TBOBJECTS) $(VOBJDR)/Vtestbus__ALL.a -lpthread -o $@
106 | #
107 | #
108 | #
109 | autotest: $(AUTOOBJ) $(VOBJDR)/Vtestbus__ALL.a
110 | $(CXX) $(CFLAGS) $(AUTOOBJ) $(VOBJDR)/Vtestbus__ALL.a -lpthread -o $@
111 |
112 | test:
113 | #
114 | #
115 | # The "test" target, runs autotest to check if our core does what it should
116 | # without any user interaction
117 | #
118 | .PHONY: test
119 | test: autotest
120 | ./autotest
121 |
122 | #
123 | # The "depends" target, to know what files things depend upon. The depends
124 | # file itself is kept in $(OBJDIR)/depends.txt
125 | #
126 | define build-depends
127 | $(mk-objdir)
128 | @echo "Building dependency file"
129 | @$(CXX) $(CFLAGS) $(INCS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt
130 | @sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
131 | @rm $(OBJDIR)/xdepends.txt
132 | endef
133 |
134 | .PHONY: depends
135 | depends: tags
136 | $(build-depends)
137 |
138 | $(OBJDIR)/depends.txt: depends
139 |
140 | #
141 | # Make sure the $(OBJDIR)/ directory exists. This has taken some work to get
142 | # right. While "mkdir -p $(OBJDIR)" could be used to do this as well, it
143 | # always bothered me that it seemed to be perpetually running. Hence, we'll
144 | # first check if the directory exists, and only create it if it does not.
145 | # Finally, by adding the @ in front of the bash command, it won't get printed
146 | # to the screen. That way ... I can run it as often as I want without getting
147 | # annoyed by it. ;)
148 | define mk-objdir
149 | @bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
150 | endef
151 |
152 |
153 | #
154 | # The "tags" target
155 | #
156 | tags: $(SOURCES) $(HEADERS)
157 | @echo "Generating tags"
158 | @ctags $(SOURCES) $(HEADERS)
159 |
160 | #
161 | # The "clean" target, removing any and all remaining build (and test) products
162 | #
163 | .PHONY: clean
164 | clean:
165 | rm -f *.vcd
166 | rm -f $(PROGRAMS)
167 | rm -rf $(OBJDIR)/
168 |
169 | #
170 | # Include our generated dependency file. The "-" in front of the include
171 | # basically tells "make" to include it if it can, and ignore it if it cannot
172 | # be included (i.e. if it doesn't exist)
173 | ifneq ($(MAKECMDGOALS),clean)
174 | -include $(OBJDIR)/depends.txt
175 | endif
176 |
--------------------------------------------------------------------------------
/bench/cpp/autotest.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: autotest.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the hexbus debugging interface.
17 | //
18 | // The hexbus interface is free software (firmware): you can redistribute it
19 | // and/or modify it under the terms of the GNU Lesser General Public License
20 | // as published by the Free Software Foundation, either version 3 of the
21 | // License, or (at your option) any later version.
22 | //
23 | // The hexbus interface is distributed in the hope that it will be useful, but
24 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
26 | // for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include "verilated.h"
46 | #include "verilated_vcd_c.h"
47 | #include "Vtestbus.h"
48 | #include "testb.h"
49 | #include "uartsim.h"
50 |
51 | #define UARTSETUP 25
52 | #include "port.h"
53 |
54 | #define TIMEOUT 250
55 | //
56 | // Wrap the bus in a test bench
57 | //
58 | class TESTBUS_TB : public TESTB {
59 | // {{{
60 | public:
61 | unsigned long m_tx_busy_count;
62 | UARTSIM m_uart;
63 | bool m_done;
64 | int m_ticks;
65 |
66 | TESTBUS_TB(const int tcp_port=0) : m_uart(tcp_port) {
67 | m_done = false;
68 | m_ticks = 0;
69 | }
70 |
71 | void trace(const char *vcd_trace_file_name) {
72 | fprintf(stderr, "Opening TRACE(%s)\n", vcd_trace_file_name);
73 | opentrace(vcd_trace_file_name);
74 | }
75 |
76 | void close(void) {
77 | TESTB::closetrace();
78 | }
79 |
80 | void tick(void) {
81 | m_ticks++;
82 | if (m_done)
83 | return;
84 |
85 | if (m_ticks < 25*20)
86 | m_core->i_uart = 1;
87 | else
88 | m_core->i_uart = m_uart(m_core->o_uart,
89 | UARTSETUP);
90 |
91 | TESTB::tick();
92 | }
93 |
94 | bool done(void) {
95 | if (m_done)
96 | return true;
97 | else {
98 | if (Verilated::gotFinish())
99 | m_done = true;
100 | else if (m_core->o_halt)
101 | m_done = true;
102 | return m_done;
103 | }
104 | }
105 | };
106 | // }}}
107 |
108 | void getresponse(int fdin, int fdout, const char *cmd, char *response) {
109 | // {{{
110 | char *rptr = response;
111 | const char *ptr, *sptr;
112 | int posn, nr;
113 |
114 | sptr = cmd;
115 | while(NULL != (ptr = strchr(sptr, '\n'))) {
116 | // Make our request
117 | putc('<', stdout);
118 | putc(' ', stdout);
119 | for(; *sptr && sptr0) {
131 | if (rptr[posn] == '\r')
132 | continue;
133 | if ((posn > 0)&&(rptr[posn] == '\n')&&(rptr[posn-1]=='\n'))
134 | continue;
135 | posn += nr;
136 |
137 | if (rptr[posn-1] == '\n') {
138 | // Check for more ...
139 | struct pollfd fds;
140 |
141 | fds.fd = fdout;
142 | fds.events = POLLIN;
143 | if (poll(&fds, 1, TIMEOUT) <= 0)
144 | break;
145 | }
146 | }
147 | if (nr < 0) {
148 | perror("O/S ERR");
149 | exit(EXIT_FAILURE);
150 | }
151 |
152 | rptr[posn] = '\0';
153 | while(*rptr && isspace(*rptr))
154 | rptr++, posn--;
155 | printf("> %s", rptr);
156 | rptr += posn;
157 | while(*sptr && (isspace(*sptr)))
158 | sptr++;
159 | if ('\0' == *sptr)
160 | break;
161 | }
162 | }
163 | // }}}
164 |
165 | int test1_read(int fdin, int fdout) {
166 | // {{{
167 | const char CHECKSTR[] = "A00002040R20170622\n";
168 | char response[512], *rptr;
169 |
170 | getresponse(fdin, fdout, "A2040R\n",
171 | response);
172 |
173 | rptr = response;
174 | while(*rptr && isspace(*rptr))
175 | rptr++;
176 |
177 | if (0 != strcmp(rptr, CHECKSTR)) {
178 | printf("CHECK1: -- FAILS\n");
179 | printf("RCV: %s", rptr);
180 | printf("PAT: %s", CHECKSTR);
181 | return 1;
182 | }
183 | return 0;
184 | }
185 | // }}}
186 |
187 | int test2_multiread(int fdin, int fdout) {
188 | // {{{
189 | // Pattern isn't stable enough to check
190 | // const char CHECKSTR[] = "A0000204dR0000d0c9\nR00019197\nR000249fc\nR000302e7\n";
191 | char response[512];
192 |
193 | getresponse(fdin, fdout, "A204dR\nR\nR\nR\n",
194 | response);
195 | return 0;
196 | }
197 | // }}}
198 |
199 | int test3_interrupts(int fdin, int fdout) {
200 | // {{{
201 | const char CHECKSTR[] = "A00002051R00000000K00000000I\nK00000000\nK00000000I\nK00000000\n";
202 | char response[512], *rptr;
203 |
204 | getresponse(fdin, fdout, "A2051RW1\nW0\nW1\nW0\n",
205 | response);
206 |
207 | rptr = response;
208 | while(*rptr && isspace(*rptr))
209 | rptr++;
210 |
211 | if (0 != strcmp(rptr, CHECKSTR)) {
212 | printf("CHECK3: -- FAILS\n");
213 | printf("RCV: %s", rptr);
214 | printf("PAT: %s", CHECKSTR);
215 | return 1;
216 | }
217 |
218 | return 0;
219 | }
220 | // }}}
221 |
222 | int test4_scope_trigger(int fdin, int fdout) {
223 | // {{{
224 | const char CHECKSTR[] = "A00002080R12a001fc\nA00004000\nK00000000\nA00002080IR72a001fc\nA00004000Rdeadbeef\n";
225 | char response[512], *rptr;
226 |
227 | getresponse(fdin, fdout, "A2080R\nA4000Wdeadbeef\nA2080R\nA4000R\n",
228 | response);
229 |
230 | rptr = response;
231 | while(*rptr && isspace(*rptr))
232 | rptr++;
233 |
234 | if (0 != strcmp(rptr, CHECKSTR)) {
235 | printf("CHECK4: -- FAILS\n");
236 | printf("RCV: %s", rptr);
237 | printf("PAT: %s", CHECKSTR);
238 |
239 | return 1;
240 | }
241 |
242 | return 0;
243 | }
244 | // }}}
245 |
246 | int test5_scope_data(int fdin, int fdout) {
247 | // {{{
248 | const char CHECKSTR[] = "A00002080R72a001fc\n"
249 | "A00004000\nK00000000\n"
250 | "A00002080R72a001fc\n"
251 | "A00002085R001b6c00\n"
252 | "R001b6c00\n"
253 | "R001b6c00\n"
254 | "R001b6c00\n"
255 | "R001b6c00\n"
256 | "R001b6c00\n";
257 | char response[512], *rptr;
258 |
259 | getresponse(fdin, fdout, "A02080R\nA4000Wdeadbeef\nA2080R\nA2085R\nR\nR\nR\nR\nR\n",
260 | response);
261 |
262 | rptr = response;
263 | while(*rptr && isspace(*rptr))
264 | rptr++;
265 |
266 | if (0 != strcmp(rptr, CHECKSTR)) {
267 | printf("CHECK5: -- FAILS\n");
268 | printf("RCV: %s", rptr);
269 | printf("PAT: %s", CHECKSTR);
270 |
271 | return 1;
272 | }
273 |
274 | return 0;
275 | }
276 | // }}}
277 |
278 | int main(int argc, char **argv) {
279 | // {{{
280 | int childs_stdin[2], childs_stdout[2];
281 |
282 | if ((pipe(childs_stdin)!=0)||(pipe(childs_stdout) != 0)) {
283 | fprintf(stderr, "ERR setting up child pipes\n");
284 | perror("O/S ERR");
285 | printf("TEST FAILURE\n");
286 | exit(EXIT_FAILURE);
287 | }
288 |
289 | pid_t childs_pid = fork();
290 |
291 | if (childs_pid < 0) {
292 | fprintf(stderr, "ERR settingng up child pprocess\n");
293 | perror("O/S ERR");
294 | printf("TEST FAILURE\n");
295 | exit(EXIT_FAILURE);
296 | }
297 |
298 | if (childs_pid) {
299 | int err, fdin, fdout;
300 |
301 | // We are the parent process, which will query the TB
302 | close(childs_stdin[0]);
303 | close(childs_stdout[1]);
304 |
305 | fdin = childs_stdin[1];
306 | fdout = childs_stdout[0];
307 |
308 | err = test1_read(fdin, fdout);
309 | if (0 == err)
310 | err = test2_multiread(fdin, fdout);
311 | if (0 == err)
312 | err = test3_interrupts(fdin, fdout);
313 | if (0 == err)
314 | err = test4_scope_trigger(fdin, fdout);
315 | if (0 == err)
316 | err = test5_scope_data(fdin, fdout);
317 |
318 | kill(childs_pid, 15);
319 | if (err != 0) {
320 | printf("ERR %d\nTEST_FAILURE!\n", err);
321 | exit(EXIT_FAILURE);
322 | } else {
323 | printf("SUCCESS!\n");
324 | exit(EXIT_SUCCESS);
325 | }
326 | } else {
327 |
328 | // Child process that will run the test bench itself
329 | close(childs_stdin[1]);
330 | close(childs_stdout[0]);
331 | close(STDIN_FILENO);
332 | if (dup(childs_stdin[0]) < 0) {
333 | fprintf(stderr, "ERR setting up child FD\n");
334 | perror("O/S ERR");
335 | exit(EXIT_FAILURE);
336 | }
337 | close(STDOUT_FILENO);
338 | if (dup(childs_stdout[1]) < 0) {
339 | fprintf(stderr, "ERR setting up child FD\n");
340 | perror("O/S ERR");
341 | exit(EXIT_FAILURE);
342 | }
343 |
344 | TESTBUS_TB *tb = new TESTBUS_TB();
345 | #define VCDTRACE
346 | #ifdef VCDTRACE
347 | tb->trace("autotest.vcd");
348 | #endif
349 | while(!tb->done())
350 | tb->tick();
351 | }
352 | }
353 | // }}}
354 |
--------------------------------------------------------------------------------
/bench/cpp/testb.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: testb.h
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: A wrapper for a common interface to a clocked FPGA core
8 | // begin exercised in Verilator.
9 | //
10 | // Creator: Dan Gisselquist, Ph.D.
11 | // Gisselquist Technology, LLC
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | // }}}
15 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
16 | // {{{
17 | // This file is part of the debugging interface demonstration.
18 | //
19 | // The debugging interface demonstration is free software (firmware): you can
20 | // redistribute it and/or modify it under the terms of the GNU Lesser General
21 | // Public License as published by the Free Software Foundation, either version
22 | // 3 of the License, or (at your option) any later version.
23 | //
24 | // This debugging interface demonstration is distributed in the hope that it
25 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
26 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
27 | // General Public License for more details.
28 | //
29 | // You should have received a copy of the GNU Lesser General Public License
30 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
31 | // with no target there if the PDF file isn't present.) If not, see
32 | // for a copy.
33 | // }}}
34 | // License: LGPL, v3, as defined and found on www.gnu.org,
35 | // {{{
36 | // http://www.gnu.org/licenses/lgpl.html
37 | //
38 | ////////////////////////////////////////////////////////////////////////////////
39 | //
40 | // }}}
41 | #ifndef TESTB_H
42 | #define TESTB_H
43 |
44 | #include
45 | #include
46 | #include
47 |
48 | #define TBASSERT(TB,A) do { if (!(A)) { (TB).closetrace(); } assert(A); } while(0);
49 |
50 | template class TESTB {
51 | public:
52 | VA *m_core;
53 | VerilatedVcdC* m_trace;
54 | unsigned long m_tickcount;
55 |
56 | TESTB(void) : m_trace(NULL), m_tickcount(0l) {
57 | m_core = new VA;
58 | Verilated::traceEverOn(true);
59 | m_core->i_clk = 0;
60 | eval(); // Get our initial values set properly.
61 | }
62 | virtual ~TESTB(void) {
63 | if (m_trace) m_trace->close();
64 | delete m_core;
65 | m_core = NULL;
66 | }
67 |
68 | virtual void opentrace(const char *vcdname) {
69 | // {{{
70 | if (!m_trace) {
71 | m_trace = new VerilatedVcdC;
72 | m_core->trace(m_trace, 99);
73 | m_trace->open(vcdname);
74 | }
75 | }
76 | // }}}
77 |
78 | virtual void closetrace(void) {
79 | // {{{
80 | if (m_trace) {
81 | m_trace->close();
82 | m_trace = NULL;
83 | }
84 | }
85 | // }}}
86 |
87 | virtual void eval(void) {
88 | m_core->eval();
89 | }
90 |
91 | virtual void tick(void) {
92 | // {{{
93 | m_tickcount++;
94 |
95 | // Make sure we have our evaluations straight before the top
96 | // of the clock. This is necessary since some of the
97 | // connection modules may have made changes, for which some
98 | // logic depends. This forces that logic to be recalculated
99 | // before the top of the clock.
100 | eval();
101 | if (m_trace) m_trace->dump(10*m_tickcount-2);
102 | m_core->i_clk = 1;
103 | eval();
104 | if (m_trace) m_trace->dump(10*m_tickcount);
105 | m_core->i_clk = 0;
106 | eval();
107 | if (m_trace) {
108 | m_trace->dump(10*m_tickcount+5);
109 | m_trace->flush();
110 | }
111 | }
112 | // }}}
113 |
114 | virtual void reset(void) {
115 | // {{{
116 | m_core->i_reset = 1;
117 | tick();
118 | m_core->i_reset = 0;
119 | // printf("RESET\n");
120 | }
121 | // }}}
122 | };
123 |
124 | #endif
125 |
--------------------------------------------------------------------------------
/bench/cpp/testbus_tb.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: testbus_tb.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the debugging interface demonstration.
17 | //
18 | // The debugging interface demonstration is free software (firmware): you can
19 | // redistribute it and/or modify it under the terms of the GNU Lesser General
20 | // Public License as published by the Free Software Foundation, either version
21 | // 3 of the License, or (at your option) any later version.
22 | //
23 | // This debugging interface demonstration is distributed in the hope that it
24 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
26 | // General Public License for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 |
46 | #include "verilated.h"
47 | #include "verilated_vcd_c.h"
48 | #include "Vtestbus.h"
49 |
50 | #include "testb.h"
51 | #include "uartsim.h"
52 |
53 | #define UARTSETUP 25
54 | #include "port.h"
55 |
56 | class TESTBUS_TB : public TESTB {
57 | // {{{
58 | public:
59 | unsigned long m_tx_busy_count;
60 | UARTSIM m_uart;
61 | bool m_done;
62 |
63 | TESTBUS_TB(const int tcp_port=0) : m_uart(tcp_port) {
64 | m_done = false;
65 | }
66 |
67 | void trace(const char *vcd_trace_file_name) {
68 | fprintf(stderr, "Opening TRACE(%s)\n", vcd_trace_file_name);
69 | opentrace(vcd_trace_file_name);
70 | }
71 |
72 | void close(void) {
73 | TESTB::closetrace();
74 | }
75 |
76 | void tick(void) {
77 | // {{{
78 | if (m_done)
79 | return;
80 |
81 | m_core->i_uart = m_uart(m_core->o_uart,
82 | UARTSETUP);
83 |
84 | TESTB::tick();
85 | }
86 | // }}}
87 |
88 | bool done(void) {
89 | // {{{
90 | if (m_done)
91 | return true;
92 | else {
93 | if (Verilated::gotFinish())
94 | m_done = true;
95 | else if (m_core->o_halt)
96 | m_done = true;
97 | return m_done;
98 | }
99 | }
100 | // }}}
101 | };
102 | // }}}
103 |
104 | TESTBUS_TB *tb;
105 |
106 | int main(int argc, char **argv) {
107 | // {{{
108 | Verilated::commandArgs(argc, argv);
109 | tb = new TESTBUS_TB(FPGAPORT);
110 |
111 | // tb->opentrace("trace.vcd");
112 | tb->reset();
113 |
114 | while(!tb->done())
115 | tb->tick();
116 |
117 | tb->close();
118 | exit(0);
119 | }
120 | // }}}
121 |
--------------------------------------------------------------------------------
/bench/cpp/trace.gtkw:
--------------------------------------------------------------------------------
1 | [*]
2 | [*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
3 | [*] Thu Nov 7 16:02:13 2019
4 | [*]
5 | [dumpfile_mtime] "Thu Nov 7 16:01:19 2019"
6 | [dumpfile_size] 485456481
7 | [timestart] 10455760
8 | [size] 1920 1029
9 | [pos] -1 -1
10 | *-12.000000 10471010 -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
11 | [treeopen] TOP.
12 | [treeopen] TOP.testbus.
13 | [treeopen] TOP.testbus.genbus.
14 | [sst_width] 196
15 | [signals_width] 198
16 | [sst_expanded] 1
17 | [sst_vpaned_height] 306
18 | @28
19 | TOP.testbus.i_clk
20 | TOP.testbus.i_reset
21 | @200
22 | -
23 | @29
24 | [color] 3
25 | TOP.testbus.i_uart
26 | @28
27 | TOP.testbus.o_uart
28 | TOP.testbus.o_halt
29 | @c00200
30 | -Transport
31 | @28
32 | TOP.testbus.rx_stb
33 | @22
34 | TOP.testbus.rx_data[7:0]
35 | @820
36 | TOP.testbus.rx_data[7:0]
37 | @200
38 | -
39 | @28
40 | TOP.testbus.tx_stb
41 | @22
42 | TOP.testbus.tx_data[7:0]
43 | @28
44 | TOP.testbus.tx_busy
45 | @1401200
46 | -Transport
47 | @c00200
48 | -HexBus
49 | @28
50 | TOP.testbus.genbus.w_reset
51 | TOP.testbus.genbus.i_rx_stb
52 | @22
53 | TOP.testbus.genbus.i_rx_byte[7:0]
54 | @200
55 | -
56 | @28
57 | TOP.testbus.genbus.dec_stb
58 | @22
59 | TOP.testbus.genbus.dec_bits[4:0]
60 | @200
61 | -
62 | @28
63 | TOP.testbus.genbus.iw_stb
64 | @22
65 | TOP.testbus.genbus.iw_word[33:0]
66 | @200
67 | -
68 | @28
69 | TOP.testbus.genbus.o_wb_cyc
70 | TOP.testbus.genbus.o_wb_stb
71 | TOP.testbus.genbus.o_wb_we
72 | @22
73 | TOP.testbus.genbus.o_wb_addr[29:0]
74 | TOP.testbus.genbus.o_wb_data[31:0]
75 | TOP.testbus.genbus.o_wb_sel[3:0]
76 | @28
77 | TOP.testbus.genbus.i_wb_stall
78 | TOP.testbus.genbus.i_wb_ack
79 | @22
80 | TOP.testbus.genbus.i_wb_data[31:0]
81 | @28
82 | TOP.testbus.genbus.i_wb_err
83 | TOP.testbus.genbus.i_wb_stall
84 | TOP.testbus.genbus.wb_busy
85 | @200
86 | -
87 | @28
88 | TOP.testbus.genbus.ow_stb
89 | @22
90 | TOP.testbus.genbus.ow_word[33:0]
91 | @200
92 | -
93 | @28
94 | TOP.testbus.genbus.int_busy
95 | TOP.testbus.genbus.int_stb
96 | @22
97 | TOP.testbus.genbus.int_word[33:0]
98 | @200
99 | -
100 | @28
101 | TOP.testbus.genbus.idl_busy
102 | TOP.testbus.genbus.idl_stb
103 | @22
104 | TOP.testbus.genbus.idl_word[33:0]
105 | @200
106 | -
107 | @28
108 | TOP.testbus.genbus.hb_busy
109 | TOP.testbus.genbus.hb_stb
110 | @22
111 | TOP.testbus.genbus.hb_bits[4:0]
112 | @200
113 | -
114 | @28
115 | TOP.testbus.genbus.hx_busy
116 | TOP.testbus.genbus.hx_stb
117 | @200
118 | -
119 | @28
120 | TOP.testbus.genbus.nl_busy
121 | @200
122 | -
123 | @22
124 | TOP.testbus.genbus.o_tx_byte[7:0]
125 | @28
126 | TOP.testbus.genbus.o_tx_stb
127 | @22
128 | TOP.testbus.genbus.ow_word[33:0]
129 | @28
130 | TOP.testbus.genbus.w_reset
131 | TOP.testbus.genbus.wb_busy
132 | @200
133 | -
134 | @28
135 | TOP.testbus.genbus.i_tx_busy
136 | TOP.testbus.genbus.o_tx_stb
137 | @22
138 | TOP.testbus.genbus.o_tx_byte[7:0]
139 | @1401200
140 | -HexBus
141 | @28
142 | [color] 3
143 | TOP.testbus.wb_cyc
144 | [color] 3
145 | TOP.testbus.wb_stb
146 | [color] 3
147 | TOP.testbus.wb_we
148 | @22
149 | [color] 3
150 | TOP.testbus.wb_addr[29:0]
151 | [color] 3
152 | TOP.testbus.wb_odata[31:0]
153 | [color] 3
154 | TOP.testbus.wb_sel[3:0]
155 | @28
156 | [color] 2
157 | TOP.testbus.wb_stall
158 | [color] 2
159 | TOP.testbus.wb_ack
160 | @22
161 | [color] 2
162 | TOP.testbus.wb_idata[31:0]
163 | @28
164 | [color] 2
165 | TOP.testbus.wb_err
166 | @200
167 | -
168 | @28
169 | TOP.testbus.bus_interrupt
170 | @200
171 | -
172 | @22
173 | TOP.testbus.bus_err_address[29:0]
174 | TOP.testbus.power_counter[31:0]
175 | @200
176 | -
177 | @28
178 | [color] 3
179 | TOP.testbus.mem_sel
180 | TOP.testbus.mem_stall
181 | TOP.testbus.mem_ack
182 | @22
183 | TOP.testbus.mem_data[31:0]
184 | @200
185 | -
186 | @28
187 | TOP.testbus.scope_trigger
188 | @22
189 | TOP.testbus.debug_data[31:0]
190 | @200
191 | -
192 | @28
193 | [color] 3
194 | TOP.testbus.scop_sel
195 | TOP.testbus.scop_stall
196 | TOP.testbus.scop_ack
197 | @22
198 | TOP.testbus.scop_data[31:0]
199 | @28
200 | TOP.testbus.scop_int
201 | @200
202 | -
203 | @28
204 | [color] 3
205 | TOP.testbus.smpl_sel
206 | TOP.testbus.smpl_stall
207 | TOP.testbus.smpl_ack
208 | @22
209 | TOP.testbus.smpl_data[31:0]
210 | @200
211 | -
212 | @28
213 | TOP.testbus.smpl_interrupt
214 | @22
215 | TOP.testbus.smpl_register[31:0]
216 | @200
217 | -
218 | @28
219 | TOP.testbus.none_sel
220 | [pattern_trace] 1
221 | [pattern_trace] 0
222 |
--------------------------------------------------------------------------------
/bench/cpp/uartsim.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: uartsim.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: To forward a Verilator simulated UART link over a TCP/IP pipe.
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the debugging interface demonstration.
17 | //
18 | // The debugging interface demonstration is free software (firmware): you can
19 | // redistribute it and/or modify it under the terms of the GNU Lesser General
20 | // Public License as published by the Free Software Foundation, either version
21 | // 3 of the License, or (at your option) any later version.
22 | //
23 | // This debugging interface demonstration is distributed in the hope that it
24 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
26 | // General Public License for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 |
51 | #include "uartsim.h"
52 |
53 | // setup_listener
54 | // {{{
55 | void UARTSIM::setup_listener(const int port) {
56 | struct sockaddr_in my_addr;
57 |
58 | signal(SIGPIPE, SIG_IGN);
59 |
60 | printf("Listening on port %d\n", port);
61 |
62 | m_skt = socket(AF_INET, SOCK_STREAM, 0);
63 | if (m_skt < 0) {
64 | perror("ERR: Could not allocate socket: ");
65 | exit(EXIT_FAILURE);
66 | }
67 |
68 | // Set the reuse address option
69 | {
70 | int optv = 1, er;
71 | er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv));
72 | if (er != 0) {
73 | perror("ERR: SockOpt Err:");
74 | exit(EXIT_FAILURE);
75 | }
76 | }
77 |
78 | memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure
79 | my_addr.sin_family = AF_INET;
80 | // Use *all* internet ports to this computer, allowing connections from
81 | // any/every one of them.
82 | my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
83 | my_addr.sin_port = htons(port);
84 |
85 | if (bind(m_skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) {
86 | perror("ERR: BIND FAILED:");
87 | exit(EXIT_FAILURE);
88 | }
89 |
90 | if (listen(m_skt, 1) != 0) {
91 | perror("ERR: Listen failed:");
92 | exit(EXIT_FAILURE);
93 | }
94 | }
95 | // }}}
96 |
97 | // UARTSIM::UARTSIM(const int port)
98 | // {{{
99 | UARTSIM::UARTSIM(const int port) {
100 | m_conrd = m_conwr = m_skt = -1;
101 | if (port == 0) {
102 | m_conrd = STDIN_FILENO;
103 | m_conwr = STDOUT_FILENO;
104 | } else
105 | setup_listener(port);
106 | setup(25); // Set us up for (default) 8N1 w/ a baud rate of CLK/25
107 | m_rx_baudcounter = 0;
108 | m_tx_baudcounter = 0;
109 | m_rx_state = RXIDLE;
110 | m_tx_state = TXIDLE;
111 | }
112 | // }}}
113 |
114 | // UARTSIM::kill
115 | // {{{
116 | void UARTSIM::kill(void) {
117 | fflush(stdout);
118 |
119 | // Quickly double check that we aren't about to close stdin/stdout
120 | if (m_conrd == STDIN_FILENO)
121 | m_conrd = -1;
122 | if (m_conwr == STDOUT_FILENO)
123 | m_conwr = -1;
124 | // Close any active connection
125 | if (m_conrd >= 0) close(m_conrd);
126 | if ((m_conwr >= 0)&&(m_conwr != m_conrd)) close(m_conwr);
127 | if (m_skt >= 0) close(m_skt);
128 |
129 | m_conrd = m_conwr = m_skt = -1;
130 | }
131 | // }}}
132 |
133 | // UARTSIM::setup(isetup)
134 | // {{{
135 | void UARTSIM::setup(unsigned isetup) {
136 | if (isetup != m_setup) {
137 | m_setup = isetup;
138 | m_baud_counts = (isetup & 0x0ffffff);
139 | m_nbits = 8-((isetup >> 28)&0x03);
140 | m_nstop =((isetup >> 27)&1)+1;
141 | m_nparity = (isetup >> 26)&1;
142 | m_fixdp = (isetup >> 25)&1;
143 | m_evenp = (isetup >> 24)&1;
144 | }
145 | }
146 | // }}}
147 |
148 | // UARTSIM::check_for_new_connections
149 | // {{{
150 | void UARTSIM::check_for_new_connections(void) {
151 | if ((m_conrd < 0)&&(m_conwr<0)&&(m_skt>=0)) {
152 | // Can we accept a connection?
153 | struct pollfd pb;
154 |
155 | pb.fd = m_skt;
156 | pb.events = POLLIN;
157 | poll(&pb, 1, 0);
158 |
159 | if (pb.revents & POLLIN) {
160 | m_conrd = accept(m_skt, 0, 0);
161 | m_conwr = m_conrd;
162 |
163 | if (m_conrd < 0)
164 | perror("Accept failed:");
165 | // else printf("New connection accepted!\n");
166 | }
167 | }
168 |
169 | }
170 | // }}}
171 |
172 | // UARTSIM::rawtick(i_tx, network)
173 | // {{{
174 | int UARTSIM::rawtick(const int i_tx, const bool network) {
175 | int o_rx = 1, nr = 0;
176 |
177 | if (network)
178 | check_for_new_connections();
179 |
180 | if ((!i_tx)&&(m_last_tx))
181 | m_rx_changectr = 0;
182 | else m_rx_changectr++;
183 | m_last_tx = i_tx;
184 |
185 | if (m_rx_state == RXIDLE) {
186 | if (!i_tx) {
187 | m_rx_state = RXDATA;
188 | m_rx_baudcounter =m_baud_counts+m_baud_counts/2-1;
189 | m_rx_baudcounter -= m_rx_changectr;
190 | m_rx_busy = 0;
191 | m_rx_data = 0;
192 | }
193 | } else if (m_rx_baudcounter <= 0) {
194 | if (m_rx_busy >= (1<<(m_nbits+m_nparity+m_nstop-1))) {
195 | m_rx_state = RXIDLE;
196 | if (m_conwr >= 0) {
197 | char buf[1];
198 | buf[0] = (m_rx_data >> (32-m_nbits-m_nstop-m_nparity))&0x0ff;
199 | if ((network)&&(1 != send(m_conwr, buf, 1, 0))) {
200 | close(m_conwr);
201 | m_conrd = m_conwr = -1;
202 | fprintf(stderr, "Failed write, connection closed\n");
203 | } else if ((!network)&&(1 != write(m_conwr, buf, 1))) {
204 | fprintf(stderr, "ERR while attempting to write out--closing output port\n");
205 | perror("UARTSIM::write() ");
206 | m_conrd = m_conwr = -1;
207 | }
208 | }
209 | } else {
210 | m_rx_busy = (m_rx_busy << 1)|1;
211 | // Low order bit is transmitted first, in this
212 | // order:
213 | // Start bit (1'b1)
214 | // bit 0
215 | // bit 1
216 | // bit 2
217 | // ...
218 | // bit N-1
219 | // (possible parity bit)
220 | // stop bit
221 | // (possible secondary stop bit)
222 | m_rx_data = ((i_tx&1)<<31) | (m_rx_data>>1);
223 | } m_rx_baudcounter = m_baud_counts-1;
224 | } else
225 | m_rx_baudcounter--;
226 |
227 | if ((m_tx_state == TXIDLE)&&((network)||(m_conrd >= 0))) {
228 | struct pollfd pb;
229 | pb.fd = m_conrd;
230 | pb.events = POLLIN;
231 | if (poll(&pb, 1, 0) < 0)
232 | perror("Polling error:");
233 |
234 | if (pb.revents & POLLIN) {
235 | char buf[1];
236 |
237 | if (network)
238 | nr = recv(m_conrd, buf, 1, MSG_DONTWAIT);
239 | else
240 | nr = read(m_conrd, buf, 1);
241 | if (1 == nr) {
242 | m_tx_data = (-1<<(m_nbits+m_nparity+1))
243 | // << nstart_bits
244 | |((buf[0]<<1)&0x01fe);
245 | if (m_nparity) {
246 | int p;
247 |
248 | // If m_nparity is set, we need to then
249 | // create the parity bit.
250 | if (m_fixdp)
251 | p = m_evenp;
252 | else {
253 | p = (m_tx_data >> 1)&0x0ff;
254 | p = p ^ (p>>4);
255 | p = p ^ (p>>2);
256 | p = p ^ (p>>1);
257 | p &= 1;
258 | p ^= m_evenp;
259 | }
260 | m_tx_data |= (p<<(m_nbits+m_nparity));
261 | }
262 | m_tx_busy = (1<<(m_nbits+m_nparity+m_nstop+1))-1;
263 | m_tx_state = TXDATA;
264 | o_rx = 0;
265 | m_tx_baudcounter = m_baud_counts-1;
266 | } else if ((network)&&(nr == 0)) {
267 | close(m_conrd);
268 | m_conrd = m_conwr = -1;
269 | // printf("Closing network connection\n");
270 | } else if (nr < 0) {
271 | if (!network) {
272 | fprintf(stderr, "ERR while attempting to read in--closing input port\n");
273 | perror("UARTSIM::read() ");
274 | m_conrd = -1;
275 | } else {
276 | perror("O/S Read err:");
277 | close(m_conrd);
278 | m_conrd = m_conwr = -1;
279 | }
280 | }
281 | }
282 | } else if (m_tx_baudcounter <= 0) {
283 | m_tx_data >>= 1;
284 | m_tx_busy >>= 1;
285 | if (!m_tx_busy)
286 | m_tx_state = TXIDLE;
287 | else
288 | m_tx_baudcounter = m_baud_counts-1;
289 | o_rx = m_tx_data&1;
290 | } else {
291 | m_tx_baudcounter--;
292 | o_rx = m_tx_data&1;
293 | }
294 |
295 | return o_rx;
296 | }
297 | // }}}
298 |
299 | // UARTSIM::nettick
300 | // {{{
301 | int UARTSIM::nettick(const int i_tx) {
302 | return rawtick(i_tx, true);
303 | }
304 | // }}}
305 |
306 | // UARTSIM::fdtick
307 | // {{{
308 | int UARTSIM::fdtick(const int i_tx) {
309 | return rawtick(i_tx, false);
310 | }
311 | // }}}
312 |
--------------------------------------------------------------------------------
/bench/cpp/uartsim.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: uartsim.h
4 | // {{{
5 | // Project: wbuart32, a full featured UART with simulator
6 | //
7 | // Purpose: To forward a Verilator simulated UART link over a TCP/IP pipe.
8 | //
9 | // This file provides the description of the interface between the UARTSIM
10 | // and the rest of the world. See below for more detailed descriptions.
11 | //
12 | // Creator: Dan Gisselquist, Ph.D.
13 | // Gisselquist Technology, LLC
14 | //
15 | ////////////////////////////////////////////////////////////////////////////////
16 | // }}}
17 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
18 | // {{{
19 | // This file is part of the debugging interface demonstration.
20 | //
21 | // The debugging interface demonstration is free software (firmware): you can
22 | // redistribute it and/or modify it under the terms of the GNU Lesser General
23 | // Public License as published by the Free Software Foundation, either version
24 | // 3 of the License, or (at your option) any later version.
25 | //
26 | // This debugging interface demonstration is distributed in the hope that it
27 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
28 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
29 | // General Public License for more details.
30 | //
31 | // You should have received a copy of the GNU Lesser General Public License
32 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | // with no target there if the PDF file isn't present.) If not, see
34 | // for a copy.
35 | // }}}
36 | // License: LGPL, v3, as defined and found on www.gnu.org,
37 | // {{{
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 | //
42 | // }}}
43 | #ifndef UARTSIM_H
44 | #define UARTSIM_H
45 |
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 |
56 | #define TXIDLE 0
57 | #define TXDATA 1
58 | #define RXIDLE 0
59 | #define RXDATA 1
60 |
61 | class UARTSIM {
62 | // Member declarations
63 | // {{{
64 | // The file descriptors:
65 | // m_skt is the socket/port we are listening on
66 | // m_conrd is the file descriptor to read from
67 | // m_conwr is the file descriptor to write to
68 | int m_skt, m_conrd, m_conwr;
69 | //
70 | // The m_setup register is the 29'bit control register used within
71 | // the core.
72 | unsigned m_setup;
73 | // And the pieces of the setup register broken out.
74 | int m_nparity, m_fixdp, m_evenp, m_nbits, m_nstop, m_baud_counts;
75 |
76 | // UART state
77 | int m_rx_baudcounter, m_rx_state, m_rx_busy,
78 | m_rx_changectr, m_last_tx;
79 | int m_tx_baudcounter, m_tx_state, m_tx_busy;
80 | unsigned m_rx_data, m_tx_data;
81 | // }}}
82 |
83 | // Private methods
84 | // {{{
85 | // setup_listener is an attempt to encapsulate all of the network
86 | // related setup stuff.
87 | void setup_listener(const int port);
88 |
89 | // Call check_for_new_connections() to see if we can accept a new
90 | // network socket connection to our device
91 | void check_for_new_connections(void);
92 |
93 | // nettick() gets called if we are connected to a network, and
94 | int nettick(const int i_tx);
95 | int fdtick(const int i_tx);
96 | int rawtick(const int i_tx, const bool network);
97 |
98 | // We'll use the file descriptor for the listener socket to determine
99 | // whether we are connected to the network or not. If not connected
100 | // to the network, then we assume m_conrd and m_conwr refer to
101 | // your more traditional file descriptors, and use them as such.
102 | int tick(const int i_tx) {
103 | return rawtick(i_tx, (m_skt >= 0));
104 | }
105 | // }}}
106 | public:
107 | // Public member functions
108 | // {{{
109 |
110 | // UARTSIM(port)
111 | // {{{
112 | // The UARTSIM constructor takes one argument: the port on the
113 | // localhost to listen in on. Once started, connections may be made
114 | // to this port to get the output from the port.
115 | UARTSIM(const int port);
116 | // }}}
117 |
118 | // kill(void)
119 | // {{{
120 | // kill() closes any active connection and the socket. Once killed,
121 | // no further output will be sent to the port.
122 | void kill(void);
123 | // }}}
124 |
125 | // setup(isetup)
126 | // {{{
127 | // setup() busts out the bits from isetup to the various internal
128 | // parameters. It is ideally only called between bits at appropriate
129 | // transition intervals.
130 | void setup(unsigned isetup);
131 | // }}}
132 |
133 | // operator()(i_tx)
134 | // {{{
135 | // The operator() function is called on every tick. The input is the
136 | // the output txuart transmit wire from the device. The output is to
137 | // be connected to the the rxuart receive wire into the device. This
138 | // makes hookup and operation very simple.
139 | //
140 | // This is the most appropriate simulation entry function if the
141 | // setup register will never change.
142 | //
143 | int operator()(int i_tx) {
144 | return tick(i_tx); }
145 | // }}}
146 |
147 | // operator()(i_tx, isetup)
148 | // {{{
149 | // If there is a possibility that the core might change the UART setup,
150 | // then it makes sense to include that current setup when calling the
151 | // tick operator.
152 | int operator()(int i_tx, unsigned isetup) {
153 | setup(isetup); return tick(i_tx); }
154 | // }}}
155 | // }}}
156 | };
157 |
158 | #endif
159 |
--------------------------------------------------------------------------------
/bench/cpp/vversion.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ################################################################################
3 | ##
4 | ## Filename: vversion.sh
5 | ## {{{
6 | ## Project: ZBasic, a generic toplevel impl using the full ZipCPU
7 | ##
8 | ## Purpose: To determine whether or not the verilator prefix for internal
9 | ## variables is v__DOT__ or the name of the top level followed by
10 | ## __DOT__. If it is the later, output -DNEW_VERILATOR, else be silent.
11 | ##
12 | ##
13 | ## Creator: Dan Gisselquist, Ph.D.
14 | ## Gisselquist Technology, LLC
15 | ##
16 | ################################################################################
17 | ## }}}
18 | ## Copyright (C) 2017-2024, Gisselquist Technology, LLC
19 | ## {{{
20 | ## This file is part of the debugging interface demonstration.
21 | ##
22 | ## The debugging interface demonstration is free software (firmware): you can
23 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
24 | ## Public License as published by the Free Software Foundation, either version
25 | ## 3 of the License, or (at your option) any later version.
26 | ##
27 | ## This debugging interface demonstration is distributed in the hope that it
28 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
30 | ## General Public License
31 | ## for more details.
32 | ##
33 | ## You should have received a copy of the GNU Lesser General Public License
34 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
35 | ## with no target there if the PDF file isn't present.) If not, see
36 | ## for a copy.
37 | ## }}}
38 | ## License: GPL, v3, as defined and found on www.gnu.org,
39 | ## {{{
40 | ## http://www.gnu.org/licenses/gpl.html
41 | ##
42 | ################################################################################
43 | ##
44 | ## }}}
45 | if [[ x${VERILATOR_ROOT} != "x" && -x ${VERILATOR_ROOT}/bin/verilator ]];
46 | then
47 | export VERILATOR=${VERILATOR_ROOT}/bin/verilator
48 | fi
49 | if [[ ! -x ${VERILATOR} ]];
50 | then
51 | export VERILATOR=verilator
52 | fi
53 | if [[ ! -x `which ${VERILATOR}` ]];
54 | then
55 | echo "Verilator not found in environment or in path"
56 | exit -1
57 | fi
58 |
59 | VVERLINE=`${VERILATOR} -V | grep -i ^Verilator`
60 | VVER=`echo ${VVERLINE} | cut -d " " -f 2`
61 | LATER=`echo $VVER \>= 3.9 | bc`
62 | if [[ $LATER > 0 ]];
63 | then
64 | RLATER=`echo $VVER \>= 4.2 | bc`
65 | if [[ $RLATER > 0 ]];
66 | then
67 | ## I'm not quite certain when Verilator started requiring a further
68 | ## subreference through rootp-> and including the Vdesign___024root.h
69 | ## include file. My best guess is that it is Verilator 4.2, but I don't
70 | ## know that for certain. What I do know is that on the development
71 | ## version 4.211, it requires different semantics to peek at register
72 | ## names. This is our attempt to capture that dependency.
73 | echo "-DROOT_VERILATOR"
74 | else
75 | echo "-DNEW_VERILATOR"
76 | fi
77 | else
78 | echo "-DOLD_VERILATOR"
79 | fi
80 | exit 0
81 |
--------------------------------------------------------------------------------
/bench/formal/.gitignore:
--------------------------------------------------------------------------------
1 | zmiter_*/
2 | miter_*/
3 | miter.v
4 | miter.sby
5 | zmiter.v
6 | zmiter.sby
7 |
--------------------------------------------------------------------------------
/bench/rtl/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: bench/rtl/Makefile
4 | ## {{{
5 | ## Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | ##
7 | ## Purpose: This Makefile guides the translation of the project RTL files
8 | ## into a library (Vtestbus__ALL.a) file that can then be linked
9 | ## with our C++ test-bench driver routine.
10 | ##
11 | ## Targets:
12 | ##
13 | ## verilate
14 | ## This target runs Verilator to produce its files in $(VDIRFB)
15 | ## (i.e. in obj_dir). This target depends upon the projects
16 | ## verilog files.
17 | ##
18 | ## library
19 | ## This target tells make to CD into the $(VDIRFB) (i.e. obj_dir)
20 | ## directory created by verilator, and to run make on the
21 | ## Verilator produced output. The result is a V(*)__ALL.a file
22 | ## that we can then link with later.
23 | ##
24 | ## Creator: Dan Gisselquist, Ph.D.
25 | ## Gisselquist Technology, LLC
26 | ##
27 | ################################################################################
28 | ## }}}
29 | ## Copyright (C) 2017-2024, Gisselquist Technology, LLC
30 | ## {{{
31 | ## This file is part of the debugging interface demonstration.
32 | ##
33 | ## The debugging interface demonstration is free software (firmware): you can
34 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
35 | ## Public License as published by the Free Software Foundation, either version
36 | ## 3 of the License, or (at your option) any later version.
37 | ##
38 | ## This debugging interface demonstration is distributed in the hope that it
39 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
40 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
41 | ## General Public License
42 | ## for more details.
43 | ##
44 | ## You should have received a copy of the GNU Lesser General Public License
45 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
46 | ## with no target there if the PDF file isn't present.) If not, see
47 | ## for a copy.
48 | ## }}}
49 | ## License: LGPL, v3, as defined and found on www.gnu.org,
50 | ## {{{
51 | ## http://www.gnu.org/licenses/lgpl.html
52 | ##
53 | ################################################################################
54 | ##
55 | ## }}}
56 | # all, the first target, becomes the default target
57 | all:
58 | #
59 | # We'll place into the $(BUS) variable which (of possibly multiple) debugging
60 | # bus we want to test. (Around here, I've also got wbubus and exbus as options,
61 | # options that are not yet in the repository ... if they ever will be.)
62 | BUS ?= hexbus
63 | #
64 | # Verilator places everything into obj_dir by default. By creating a variable
65 | # with this name, we can adjust it and everything will adjust as appropriate
66 | VDIRFB := obj_dir
67 | #
68 | # We'll need to call make in subdirectories. Here's how we're going to do it.
69 | # The actual call will need to look like $(SUBMAKE)
70 | SUBMAKE := $(MAKE) --no-print-directory -C
71 | #
72 | # In case you have verilator in a strange place that's not necessarily in your
73 | # path, we allow it to be overridden here.
74 | VERILATOR := verilator
75 | #
76 | # Verilator flags
77 | # -Wall Turn all warnings on, and stop on a warning as if an error
78 | # --MMD Build/update a dependency file, so we know when we need to
79 | # rebuild
80 | # -trace Build a VCD generation facility into Verilator's output
81 | # -y Let verilator know that some of our source is in the
82 | # directory
83 | # --Mdir Place our output files into , or $(VDIRFB) here
84 | # -cc Create C++ output files (in $(VDIRFB)
85 | #
86 | VFLAGS := -Wall --MMD -trace -y ../../$(BUS)/rtl --Mdir $(VDIRFB) -cc
87 |
88 | #
89 | # Now that all of our defines are out of the way, we'll specify two default
90 | # targets. The first just runs verilator. The second actually builds our
91 | # library within the $(VDIRFB) directory
92 | .PHONY: all
93 | all: verilate library quikbus quiklib
94 |
95 | .DELETE_ON_ERROR:
96 |
97 | #
98 | # The "verilate" target doesn't produce any files. Just insist instead
99 | # that the Vtestbus.h file exist
100 | .PHONY: verilate
101 | verilate: $(VDIRFB)/Vtestbus.h
102 | .PHONY: quikbus
103 | quikbus: $(VDIRFB)/Vquikbus.h
104 |
105 | #
106 | # Run Verilator on our RTL code
107 | $(VDIRFB)/Vtestbus.h:
108 | $(VERILATOR) $(VFLAGS) testbus.v
109 | $(VDIRFB)/Vquikbus.h:
110 | $(VERILATOR) $(VFLAGS) quikbus.v
111 |
112 | .PHONY: library
113 | ## {{{
114 | ## Build the library from the Verialtor outputs.
115 | ## This just runs make in the $(VDIRFB) directory on the file Vtestbus.mk
116 | ## (also in the $(VDIRFB) directory)
117 | library: $(VDIRFB)/Vtestbus.h
118 | $(SUBMAKE) $(VDIRFB)/ -f Vtestbus.mk
119 | ## }}}
120 |
121 | quiklib: $(VDIRFB)/Vquikbus.h
122 | $(SUBMAKE) $(VDIRFB)/ -f Vquikbus.mk
123 |
124 | .PHONY: clean
125 | ## {{{
126 | ## Clean up any make by products, so we can start from scratch if we need to
127 | clean:
128 | rm -rf $(VDIRFB)/
129 | ## }}}
130 |
131 | #
132 | # Note and incorporate any dependency information, so that we'll know when/if
133 | # we need to rebuild.
134 | DEPS := $(wildcard $(VDIRFB)/*.d)
135 |
136 | ifneq ($(DEPS),)
137 | include $(DEPS)
138 | endif
139 |
--------------------------------------------------------------------------------
/bench/rtl/memdev.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: memdev.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This file is really simple: it creates an on-chip memory,
8 | // accessible via the wishbone bus, that can be used in this
9 | // project. The memory has single cycle pipeline access, although the
10 | // memory pipeline here still costs a cycle and there may be other cycles
11 | // lost between the ZipCPU (or whatever is the master of the bus) and this,
12 | // thus costing more cycles in access. Either way, operations can be
13 | // pipelined for single cycle access on subsequent transactions.
14 | //
15 | //
16 | // Creator: Dan Gisselquist, Ph.D.
17 | // Gisselquist Technology, LLC
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | // }}}
21 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
22 | // {{{
23 | // This file is part of the debugging interface demonstration.
24 | //
25 | // The debugging interface demonstration is free software (firmware): you can
26 | // redistribute it and/or modify it under the terms of the GNU Lesser General
27 | // Public License as published by the Free Software Foundation, either version
28 | // 3 of the License, or (at your option) any later version.
29 | //
30 | // This debugging interface demonstration is distributed in the hope that it
31 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
32 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
33 | // General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public License
36 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
37 | // with no target there if the PDF file isn't present.) If not, see
38 | // for a copy.
39 | // }}}
40 | // License: LGPL, v3, as defined and found on www.gnu.org,
41 | // {{{
42 | // http://www.gnu.org/licenses/lgpl.html
43 | //
44 | ////////////////////////////////////////////////////////////////////////////////
45 | //
46 | `default_nettype none
47 | // }}}
48 | module memdev #(
49 | // {{{
50 | parameter LGMEMSZ=15, DW=32, EXTRACLOCK= 1,
51 | parameter HEXFILE="",
52 | parameter [0:0] OPT_ROM = 1'b0,
53 | localparam AW = LGMEMSZ - $clog2(DW/8)
54 | // }}}
55 | ) (
56 | // {{{
57 | input wire i_clk, i_reset,
58 | input wire i_wb_cyc, i_wb_stb, i_wb_we,
59 | input wire [(AW-1):0] i_wb_addr,
60 | input wire [(DW-1):0] i_wb_data,
61 | input wire [(DW/8-1):0] i_wb_sel,
62 | output wire o_wb_stall,
63 | output reg o_wb_ack,
64 | output reg [(DW-1):0] o_wb_data
65 | // }}}
66 | );
67 |
68 | // Local declarations
69 | // {{{
70 | wire w_wstb, w_stb;
71 | wire [(DW-1):0] w_data;
72 | wire [(AW-1):0] w_addr;
73 | wire [(DW/8-1):0] w_sel;
74 |
75 | // Declare the memory itself
76 | reg [(DW-1):0] mem [0:((1< for a copy.
35 | // }}}
36 | // License: LGPL, v3, as defined and found on www.gnu.org,
37 | // {{{
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 | //
42 | `default_nettype none
43 | // }}}
44 | module quikbus #(
45 | // UARTSETUP must match testbus_tb, =4Mb w/ a 100MHz ck
46 | parameter UARTSETUP = 25
47 | ) (
48 | // {{{
49 | input wire i_clk,
50 | input wire i_uart,
51 | output wire o_uart,
52 | input wire i_scope_ce, i_scope_trigger,
53 | input wire [31:0] i_scope_data
54 | // }}}
55 | );
56 |
57 | // Local declarations
58 | // {{{
59 | wire rx_stb;
60 | wire [7:0] rx_data;
61 | wire tx_stb, tx_busy;
62 | wire [7:0] tx_data;
63 |
64 | // Bus interface wires
65 | wire wb_cyc, wb_stb, wb_we;
66 | wire [29:0] wb_addr;
67 | wire [31:0] wb_odata;
68 | wire [3:0] wb_sel;
69 | wire wb_ack;
70 | wire wb_stall;
71 | wire wb_err;
72 | wire [31:0] wb_idata;
73 | wire scop_int;
74 |
75 | //
76 | // Define some wires for returning values to the bus from our various
77 | // components
78 | wire [31:0] scop_data;
79 | wire scop_stall;
80 | wire scop_ack;
81 | // }}}
82 | ////////////////////////////////////////////////////////////////////////
83 | //
84 | // Control the design via the serial port
85 | // {{{
86 | ////////////////////////////////////////////////////////////////////////
87 | //
88 | //
89 |
90 | rxuartlite #(
91 | .CLOCKS_PER_BAUD(UARTSETUP)
92 | ) rxtransport(
93 | // {{{
94 | i_clk, i_uart, rx_stb, rx_data
95 | // }}}
96 | );
97 |
98 | txuartlite #(
99 | .CLOCKS_PER_BAUD(UARTSETUP)
100 | ) txtransport(
101 | // {{{
102 | i_clk, tx_stb, tx_data, o_uart, tx_busy
103 | // }}}
104 | );
105 |
106 | // }}}
107 | ////////////////////////////////////////////////////////////////////////
108 | //
109 | // Convert serial data to bus commands and back
110 | // {{{
111 | ////////////////////////////////////////////////////////////////////////
112 | //
113 | //
114 |
115 | hbbus
116 | genbus(
117 | // {{{
118 | .i_clk(i_clk),
119 | // The receive transport wires
120 | .i_rx_stb(rx_stb), .i_rx_byte(rx_data),
121 | // The bus control output wires
122 | .o_wb_cyc(wb_cyc), .o_wb_stb(wb_stb), .o_wb_we(wb_we),
123 | .o_wb_addr(wb_addr), .o_wb_data(wb_odata),
124 | .o_wb_sel(wb_sel),
125 | // The return bus wires
126 | .i_wb_stall(wb_stall), .i_wb_ack(wb_ack),
127 | .i_wb_data(wb_idata), .i_wb_err(wb_err),
128 | // An interrupt line
129 | .i_interrupt(scop_int),
130 | // The return transport wires
131 | .o_tx_stb(tx_stb), .o_tx_byte(tx_data), .i_tx_busy(tx_busy)
132 | // }}}
133 | );
134 |
135 | assign wb_err = 1'b0;
136 | // }}}
137 | ////////////////////////////////////////////////////////////////////////
138 | //
139 | // A wishbone scope -- the goal of this design
140 | // {{{
141 | ////////////////////////////////////////////////////////////////////////
142 | //
143 | //
144 |
145 | wbscope
146 | thescope(
147 | // {{{
148 | .i_data_clk(i_clk), .i_ce(i_scope_ce),
149 | .i_trigger(i_scope_trigger), .i_data(i_scope_data),
150 | .i_wb_clk(i_clk), .i_wb_cyc(wb_cyc), .i_wb_stb(wb_stb),
151 | .i_wb_we(wb_we), .i_wb_addr(wb_addr[0]),
152 | .i_wb_data(wb_odata), .i_wb_sel(4'hf),
153 | .o_wb_stall(scop_stall), .o_wb_ack(scop_ack),
154 | .o_wb_data(scop_data),
155 | .o_interrupt(scop_int)
156 | // }}}
157 | );
158 |
159 | // }}}
160 | ////////////////////////////////////////////////////////////////////////
161 | //
162 | // Bus response composition
163 | // {{{
164 | ////////////////////////////////////////////////////////////////////////
165 | //
166 | //
167 |
168 | // Now, let's put those bus responses together
169 | //
170 | assign wb_ack = scop_ack;
171 | assign wb_idata = scop_data;
172 | assign wb_stall = scop_stall;
173 | // }}}
174 |
175 | // Make verilator happy
176 | // {{{
177 | // verilator lint_off UNUSED
178 | wire unused;
179 | assign unused = &{ 1'b0, wb_addr[29:1], wb_sel };
180 | // verilator lint_on UNUSED
181 | // }}}
182 | endmodule
183 |
--------------------------------------------------------------------------------
/bench/rtl/rxuartlite.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: rxuartlite.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: Receive and decode inputs from a single UART line.
8 | //
9 | //
10 | // To interface with this module, connect it to your system clock,
11 | // and a UART input. Set the parameter to the number of clocks per
12 | // baud. When data becomes available, the o_wr line will be asserted
13 | // for one clock cycle.
14 | //
15 | // This interface only handles 8N1 serial port communications. It does
16 | // not handle the break, parity, or frame error conditions.
17 | //
18 | //
19 | // Creator: Dan Gisselquist, Ph.D.
20 | // Gisselquist Technology, LLC
21 | //
22 | ////////////////////////////////////////////////////////////////////////////////
23 | // }}}
24 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
25 | // {{{
26 | // This file is part of the debugging interface demonstration.
27 | //
28 | // The debugging interface demonstration is free software (firmware): you can
29 | // redistribute it and/or modify it under the terms of the GNU Lesser General
30 | // Public License as published by the Free Software Foundation, either version
31 | // 3 of the License, or (at your option) any later version.
32 | //
33 | // This debugging interface demonstration is distributed in the hope that it
34 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
35 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
36 | // General Public License for more details.
37 | //
38 | // You should have received a copy of the GNU Lesser General Public License
39 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
40 | // with no target there if the PDF file isn't present.) If not, see
41 | // for a copy.
42 | // }}}
43 | // License: LGPL, v3, as defined and found on www.gnu.org,
44 | // {{{
45 | // http://www.gnu.org/licenses/lgpl.html
46 | //
47 | ////////////////////////////////////////////////////////////////////////////////
48 | //
49 | `default_nettype none
50 | // }}}
51 | module rxuartlite #(
52 | // {{{
53 | parameter TIMER_BITS = 10,
54 | `ifdef FORMAL
55 | parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 16, // Necessary for formal proof
56 | `else
57 | parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 868, // 115200 Baud at 100MHz
58 | `endif
59 | localparam TB = TIMER_BITS,
60 | //
61 | localparam [3:0] RXUL_BIT_ZERO = 4'h0,
62 | // Verilator lint_off UNUSED
63 | // These are used by the formal solver
64 | localparam [3:0] RXUL_BIT_ONE = 4'h1,
65 | localparam [3:0] RXUL_BIT_TWO = 4'h2,
66 | localparam [3:0] RXUL_BIT_THREE = 4'h3,
67 | localparam [3:0] RXUL_BIT_FOUR = 4'h4,
68 | localparam [3:0] RXUL_BIT_FIVE = 4'h5,
69 | localparam [3:0] RXUL_BIT_SIX = 4'h6,
70 | localparam [3:0] RXUL_BIT_SEVEN = 4'h7,
71 | // Verilator lint_on UNUSED
72 | localparam [3:0] RXUL_STOP = 4'h8,
73 | localparam [3:0] RXUL_WAIT = 4'h9,
74 | localparam [3:0] RXUL_IDLE = 4'hf
75 | // }}}
76 | ) (
77 | // {{{
78 | input wire i_clk,
79 | input wire i_uart_rx,
80 | output reg o_wr,
81 | output reg [7:0] o_data
82 | // }}}
83 | );
84 |
85 | // Signal/register declarations
86 | // {{{
87 | wire [(TB-1):0] half_baud;
88 | reg [3:0] state;
89 |
90 | assign half_baud = { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] };
91 | reg [(TB-1):0] baud_counter;
92 | reg zero_baud_counter;
93 |
94 | reg q_uart, qq_uart, ck_uart;
95 | reg [(TB-1):0] chg_counter;
96 | reg half_baud_time;
97 | reg [7:0] data_reg;
98 | // }}}
99 |
100 | // ck_uart
101 | // {{{
102 | // Since this is an asynchronous receiver, we need to register our
103 | // input a couple of clocks over to avoid any problems with
104 | // metastability. We do that here, and then ignore all but the
105 | // ck_uart wire.
106 | initial q_uart = 1'b1;
107 | initial qq_uart = 1'b1;
108 | initial ck_uart = 1'b1;
109 | always @(posedge i_clk)
110 | { ck_uart, qq_uart, q_uart } <= { qq_uart, q_uart, i_uart_rx };
111 | // }}}
112 |
113 | // chg_counter
114 | // {{{
115 | // Keep track of the number of clocks since the last change.
116 | //
117 | // This is used to determine if we are in either a break or an idle
118 | // condition, as discussed further below.
119 | initial chg_counter = {(TB){1'b1}};
120 | always @(posedge i_clk)
121 | if (qq_uart != ck_uart)
122 | chg_counter <= 0;
123 | else if (chg_counter != { (TB){1'b1} })
124 | chg_counter <= chg_counter + 1;
125 | // }}}
126 |
127 | // half_baud_time
128 | // {{{
129 | // Are we in the middle of a baud iterval? Specifically, are we
130 | // in the middle of a start bit? Set this to high if so. We'll use
131 | // this within our state machine to transition out of the IDLE
132 | // state.
133 | initial half_baud_time = 0;
134 | always @(posedge i_clk)
135 | half_baud_time <= (!ck_uart)&&(chg_counter >= half_baud-1'b1-1'b1);
136 | // }}}
137 |
138 | // state
139 | // {{{
140 | initial state = RXUL_IDLE;
141 | always @(posedge i_clk)
142 | if (state == RXUL_IDLE)
143 | begin // Idle state, independent of baud counter
144 | // {{{
145 | // By default, just stay in the IDLE state
146 | state <= RXUL_IDLE;
147 | if ((!ck_uart)&&(half_baud_time))
148 | // UNLESS: We are in the center of a valid
149 | // start bit
150 | state <= RXUL_BIT_ZERO;
151 | // }}}
152 | end else if ((state >= RXUL_WAIT)&&(ck_uart))
153 | state <= RXUL_IDLE;
154 | else if (zero_baud_counter)
155 | begin
156 | // {{{
157 | if (state <= RXUL_STOP)
158 | // Data arrives least significant bit first.
159 | // By the time this is clocked in, it's what
160 | // you'll have.
161 | state <= state + 1;
162 | // }}}
163 | end
164 | // }}}
165 |
166 | // data_reg
167 | // {{{
168 | // Data bit capture logic.
169 | //
170 | // This is drastically simplified from the state machine above, based
171 | // upon: 1) it doesn't matter what it is until the end of a captured
172 | // byte, and 2) the data register will flush itself of any invalid
173 | // data in all other cases. Hence, let's keep it real simple.
174 | always @(posedge i_clk)
175 | if ((zero_baud_counter)&&(state != RXUL_STOP))
176 | data_reg <= { qq_uart, data_reg[7:1] };
177 | // }}}
178 |
179 | // o_wr, o_data
180 | // {{{
181 | // Our data bit logic doesn't need nearly the complexity of all that
182 | // work above. Indeed, we only need to know if we are at the end of
183 | // a stop bit, in which case we copy the data_reg into our output
184 | // data register, o_data, and tell others (for one clock) that data is
185 | // available.
186 | //
187 | initial o_wr = 1'b0;
188 | initial o_data = 8'h00;
189 | always @(posedge i_clk)
190 | if ((zero_baud_counter)&&(state == RXUL_STOP)&&(ck_uart))
191 | begin
192 | o_wr <= 1'b1;
193 | o_data <= data_reg;
194 | end else
195 | o_wr <= 1'b0;
196 | // }}}
197 |
198 | // baud_counter -- The baud counter
199 | // {{{
200 | // This is used as a "clock divider" if you will, but the clock needs
201 | // to be reset before any byte can be decoded. In all other respects,
202 | // we set ourselves up for CLOCKS_PER_BAUD counts between baud
203 | // intervals.
204 | initial baud_counter = 0;
205 | always @(posedge i_clk)
206 | if (((state==RXUL_IDLE))&&(!ck_uart)&&(half_baud_time))
207 | baud_counter <= CLOCKS_PER_BAUD-1'b1;
208 | else if (state == RXUL_WAIT)
209 | baud_counter <= 0;
210 | else if ((zero_baud_counter)&&(state < RXUL_STOP))
211 | baud_counter <= CLOCKS_PER_BAUD-1'b1;
212 | else if (!zero_baud_counter)
213 | baud_counter <= baud_counter-1'b1;
214 | // }}}
215 |
216 | // zero_baud_counter
217 | // {{{
218 | // Rather than testing whether or not (baud_counter == 0) within our
219 | // (already too complicated) state transition tables, we use
220 | // zero_baud_counter to pre-charge that test on the clock
221 | // before--cleaning up some otherwise difficult timing dependencies.
222 | initial zero_baud_counter = 1'b1;
223 | always @(posedge i_clk)
224 | if ((state == RXUL_IDLE)&&(!ck_uart)&&(half_baud_time))
225 | zero_baud_counter <= 1'b0;
226 | else if (state == RXUL_WAIT)
227 | zero_baud_counter <= 1'b1;
228 | else if ((zero_baud_counter)&&(state < RXUL_STOP))
229 | zero_baud_counter <= 1'b0;
230 | else if (baud_counter == 1)
231 | zero_baud_counter <= 1'b1;
232 | // }}}
233 | ////////////////////////////////////////////////////////////////////////////////
234 | ////////////////////////////////////////////////////////////////////////////////
235 | ////////////////////////////////////////////////////////////////////////////////
236 | //
237 | // Formal properties
238 | // {{{
239 | ////////////////////////////////////////////////////////////////////////////////
240 | ////////////////////////////////////////////////////////////////////////////////
241 | ////////////////////////////////////////////////////////////////////////////////
242 | `ifdef FORMAL
243 | // The formal properties for this file are maintained elsewhere
244 | `endif
245 | endmodule
246 |
247 |
248 |
--------------------------------------------------------------------------------
/bench/rtl/testbus.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: testbus.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This file composes a top level "demonstration" bus that can
8 | // be used to prove that things work. Components contained within
9 | // this demonstration include:
10 | //
11 | //
12 | // Creator: Dan Gisselquist, Ph.D.
13 | // Gisselquist Technology, LLC
14 | //
15 | ////////////////////////////////////////////////////////////////////////////////
16 | // }}}
17 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
18 | // {{{
19 | // This file is part of the debugging interface demonstration.
20 | //
21 | // The debugging interface demonstration is free software (firmware): you can
22 | // redistribute it and/or modify it under the terms of the GNU Lesser General
23 | // Public License as published by the Free Software Foundation, either version
24 | // 3 of the License, or (at your option) any later version.
25 | //
26 | // This debugging interface demonstration is distributed in the hope that it
27 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
28 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
29 | // General Public License for more details.
30 | //
31 | // You should have received a copy of the GNU Lesser General Public License
32 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | // with no target there if the PDF file isn't present.) If not, see
34 | // for a copy.
35 | // }}}
36 | // License: LGPL, v3, as defined and found on www.gnu.org,
37 | // {{{
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 | //
42 | `default_nettype none
43 | // }}}
44 | module testbus #(
45 | // {{{
46 | // Must match testbus_tb, =4Mb w/ a 100MHz ck
47 | parameter UARTSETUP = 25
48 | // }}}
49 | ) (
50 | // {{{
51 | input wire i_clk,
52 | // verilator lint_off UNUSED
53 | input wire i_reset, // Ignored, but needed for our test infra.
54 | // verilator lint_on UNUSED
55 | input wire i_uart,
56 | output wire o_uart
57 | `ifdef VERILATOR
58 | , output reg o_halt // Tell the SIM when to stop
59 | `endif
60 | // }}}
61 | );
62 |
63 | // Local declarations
64 | // {{{
65 | wire rx_stb;
66 | wire [7:0] rx_data;
67 | wire tx_stb, tx_busy;
68 | wire [7:0] tx_data;
69 |
70 | // Bus interface wires
71 | wire wb_cyc, wb_stb, wb_we;
72 | wire [29:0] wb_addr;
73 | wire [31:0] wb_odata;
74 | wire [3:0] wb_sel;
75 | reg wb_ack;
76 | wire wb_stall;
77 | reg wb_err;
78 | reg [31:0] wb_idata;
79 | wire bus_interrupt;
80 |
81 | //
82 | // Define some wires for returning values to the bus from our various
83 | // components
84 | reg [31:0] smpl_data;
85 | wire [31:0] mem_data, scop_data;
86 | wire smpl_stall, mem_stall, scop_stall;
87 | wire scop_int;
88 | reg smpl_interrupt;
89 | wire scop_ack, mem_ack;
90 | reg smpl_ack;
91 |
92 | wire smpl_sel, scop_sel, mem_sel;
93 |
94 | reg [31:0] smpl_register, power_counter;
95 | reg [29:0] bus_err_address;
96 |
97 | wire none_sel;
98 | wire scope_trigger;
99 | wire [31:0] debug_data;
100 | // }}}
101 | ////////////////////////////////////////////////////////////////////////
102 | //
103 | // Serial port
104 | // {{{
105 | ////////////////////////////////////////////////////////////////////////
106 | //
107 | //
108 |
109 | rxuartlite #(24,
110 | .CLOCKS_PER_BAUD(UARTSETUP)
111 | ) rxtransport(
112 | // {{{
113 | i_clk, i_uart, rx_stb, rx_data
114 | // }}}
115 | );
116 |
117 | txuartlite #(24,
118 | .CLOCKS_PER_BAUD(UARTSETUP)
119 | ) txtransport(
120 | // {{{
121 | i_clk, tx_stb, tx_data, o_uart, tx_busy
122 | // }}}
123 | );
124 | // }}}
125 | ////////////////////////////////////////////////////////////////////////
126 | //
127 | // Turn serial bytes into bus requests
128 | // {{{
129 | ////////////////////////////////////////////////////////////////////////
130 | //
131 | //
132 |
133 | hbbus
134 | genbus(
135 | // {{{
136 | .i_clk(i_clk),
137 | // The receive transport wires
138 | .i_rx_stb(rx_stb), .i_rx_byte(rx_data),
139 | // The bus control output wires
140 | .o_wb_cyc(wb_cyc), .o_wb_stb(wb_stb), .o_wb_we(wb_we),
141 | .o_wb_addr(wb_addr), .o_wb_data(wb_odata),
142 | .o_wb_sel(wb_sel),
143 | // The return bus wires
144 | .i_wb_stall(wb_stall), .i_wb_ack(wb_ack),
145 | .i_wb_data(wb_idata), .i_wb_err(wb_err),
146 | // An interrupt line
147 | .i_interrupt(bus_interrupt),
148 | // The return transport wires
149 | .o_tx_stb(tx_stb), .o_tx_byte(tx_data), .i_tx_busy(tx_busy)
150 | // }}}
151 | );
152 | // }}}
153 | // Nothing should be assigned to the null page
154 | assign smpl_sel = (wb_addr[29:4] == 26'h081);
155 | assign scop_sel = (wb_addr[29:4] == 26'h082);
156 | assign mem_sel = (wb_addr[29:12] ==18'h1);
157 |
158 | ////////////////////////////////////////////////////////////////////////
159 | //
160 | // The "null" device
161 | // {{{
162 | //
163 | // Replaced with looking for nothing being selected
164 | assign none_sel = (!smpl_sel)&&(!scop_sel)&&(!mem_sel);
165 |
166 | always @(posedge i_clk)
167 | wb_err <= (wb_stb)&&(none_sel);
168 |
169 | ////////////////////////////////////////////////////////////////////////
170 | //
171 | // A "Simple" example device
172 | // {{{
173 | ////////////////////////////////////////////////////////////////////////
174 | //
175 | //
176 |
177 | initial smpl_ack = 1'b0;
178 | always @(posedge i_clk)
179 | smpl_ack <= ((wb_stb)&&(smpl_sel));
180 | assign smpl_stall = 1'b0;
181 |
182 | always @(posedge i_clk)
183 | case(wb_addr[3:0])
184 | 4'h0: smpl_data <= 32'h20170622;
185 | 4'h1: smpl_data <= smpl_register;
186 | 4'h2: smpl_data <= { bus_err_address, 2'b00 };
187 | 4'h3: smpl_data <= power_counter;
188 | 4'h4: smpl_data <= { 31'h0, smpl_interrupt };
189 | default: smpl_data <= 32'h00;
190 | endcase
191 |
192 | // simpl_interrupt, simpl_register, o_halt
193 | // {{{
194 | initial smpl_interrupt = 1'b0;
195 | always @(posedge i_clk)
196 | if ((wb_stb)&&(smpl_sel)&&(wb_we))
197 | begin
198 | case(wb_addr[3:0])
199 | 4'h1: smpl_register <= wb_odata;
200 | 4'h4: smpl_interrupt <= wb_odata[0];
201 | `ifdef VERILATOR
202 | 4'h5: o_halt <= wb_odata[0];
203 | `endif
204 | default: begin end
205 | endcase
206 | end
207 | // }}}
208 |
209 | // Start our clocks since power up counter from zero
210 | initial power_counter = 0;
211 | always @(posedge i_clk)
212 | // Count up from zero until the top bit is set
213 | if (!power_counter[31])
214 | power_counter <= power_counter + 1'b1;
215 | else // Once the top bit is set, keep it set forever
216 | power_counter[30:0] <= power_counter[30:0] + 1'b1;
217 |
218 | initial bus_err_address = 0;
219 | always @(posedge i_clk)
220 | if (wb_err)
221 | bus_err_address <= wb_addr;
222 |
223 | // }}}
224 | ////////////////////////////////////////////////////////////////////////
225 | //
226 | // An example block RAM device
227 | // {{{
228 | ////////////////////////////////////////////////////////////////////////
229 | //
230 | //
231 | memdev #(14)
232 | blkram(
233 | // {{{
234 | i_clk, 1'b0, wb_cyc, (wb_stb)&&(mem_sel), wb_we, wb_addr[11:0],
235 | wb_odata, wb_sel,
236 | mem_stall, mem_ack, mem_data
237 | // }}}
238 | );
239 | // }}}
240 | ////////////////////////////////////////////////////////////////////////
241 | //
242 | // A wishbone scope
243 | // {{{
244 | ////////////////////////////////////////////////////////////////////////
245 | //
246 | //
247 |
248 | assign scope_trigger = (mem_sel)&&(wb_stb);
249 | assign debug_data = { wb_cyc, wb_stb, wb_we, wb_ack, wb_stall,
250 | wb_addr[5:0], 1'b1, wb_odata[9:0], wb_idata[9:0] };
251 |
252 | wbscope
253 | thescope(
254 | // {{{
255 | .i_data_clk(i_clk), .i_ce(1'b1), .i_trigger(scope_trigger),
256 | .i_data(debug_data),
257 | .i_wb_clk(i_clk), .i_wb_cyc(wb_cyc),
258 | .i_wb_stb((wb_stb)&&(scop_sel)),
259 | .i_wb_we(wb_we), .i_wb_addr(wb_addr[0]),
260 | .i_wb_data(wb_odata), .i_wb_sel(wb_sel),
261 | .o_wb_stall(scop_stall), .o_wb_ack(scop_ack),
262 | .o_wb_data(scop_data),
263 | .o_interrupt(scop_int)
264 | // }}}
265 | );
266 | // }}}
267 | ////////////////////////////////////////////////////////////////////////
268 | //
269 | // Bus response composition
270 | // {{{
271 | ////////////////////////////////////////////////////////////////////////
272 | //
273 | //
274 |
275 | // Now, let's put those bus responses together
276 | //
277 | initial wb_ack = 1'b0;
278 | always @(posedge i_clk)
279 | wb_ack <= (smpl_ack)||(scop_ack)||(mem_ack);
280 |
281 | always @(posedge i_clk)
282 | if (smpl_ack)
283 | wb_idata <= smpl_data;
284 | else if (scop_ack)
285 | wb_idata <= scop_data;
286 | else if (mem_ack)
287 | wb_idata <= mem_data;
288 | else
289 | wb_idata <= 32'h0;
290 |
291 | assign wb_stall = ((smpl_sel)&&(smpl_stall))
292 | ||((scop_sel)&&(scop_stall))
293 | ||((mem_sel)&&(mem_stall));
294 |
295 | assign bus_interrupt = (smpl_interrupt) | (scop_int);
296 | // }}}
297 | endmodule
298 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: Makefile
4 | ## {{{
5 | ## Project: wbuart32, a full featured UART with simulator
6 | ##
7 | ## Purpose: To coordinate the build of documentation PDFs from their
8 | ## LaTeX sources.
9 | ##
10 | ## Targets include:
11 | ## all Builds all documents
12 | ##
13 | ## gpl-3.0.pdf Builds the GPL license that some of the files in
14 | ## this repository are released under.
15 | ##
16 | ## lgpl-3.0.pdf Builds the LGPL license that everything else is
17 | ## released under.
18 | ##
19 | ## Creator: Dan Gisselquist, Ph.D.
20 | ## Gisselquist Technology, LLC
21 | ##
22 | ################################################################################
23 | ## }}}
24 | ## Copyright (C) 2015-2024, Gisselquist Technology, LLC
25 | ## {{{
26 | ## This program is free software (firmware): you can redistribute it and/or
27 | ## modify it under the terms of the GNU General Public License as published
28 | ## by the Free Software Foundation, either version 3 of the License, or (at
29 | ## your option) any later version.
30 | ##
31 | ## This program is distributed in the hope that it will be useful, but WITHOUT
32 | ## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
33 | ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34 | ## for more details.
35 | ##
36 | ## You should have received a copy of the GNU General Public License along
37 | ## with this program. (It's in the $(ROOT)/doc directory. Run make with no
38 | ## target there if the PDF file isn't present.) If not, see
39 | ## for a copy.
40 | ## }}}
41 | ## License: GPL, v3, as defined and found on www.gnu.org,
42 | ## {{{
43 | ## http://www.gnu.org/licenses/gpl.html
44 | ##
45 | ################################################################################
46 | ##
47 | ## }}}
48 | .PHONY: all
49 | all: gpl lgpl
50 | pdf: gpl lgpl
51 | DSRC := src
52 |
53 | .PHONY: gpl
54 | ## GPL
55 | ## {{{
56 | gpl: gpl-3.0.pdf
57 | gpl-3.0.pdf: $(DSRC)/gpl-3.0.tex
58 | latex $(DSRC)/gpl-3.0.tex
59 | latex $(DSRC)/gpl-3.0.tex
60 | dvips -q -z -t letter -P pdf -o gpl-3.0.ps gpl-3.0.dvi
61 | ps2pdf -dAutoRotatePages=/All gpl-3.0.ps gpl-3.0.pdf
62 | rm gpl-3.0.dvi gpl-3.0.log gpl-3.0.aux gpl-3.0.ps
63 | ## }}}
64 |
65 | .PHONY: lgpl
66 | ## LGPL
67 | ## {{{
68 | lgpl: lgpl-3.0.pdf
69 | lgpl-3.0.pdf: $(DSRC)/lgpl-3.0.tex
70 | latex $(DSRC)/lgpl-3.0.tex
71 | latex $(DSRC)/lgpl-3.0.tex
72 | dvips -q -z -t letter -P pdf -o lgpl-3.0.ps lgpl-3.0.dvi
73 | ps2pdf -dAutoRotatePages=/All lgpl-3.0.ps lgpl-3.0.pdf
74 | rm lgpl-3.0.dvi lgpl-3.0.log lgpl-3.0.aux lgpl-3.0.ps
75 | ## }}}
76 |
77 | .PHONY: clean
78 | ## {{{
79 | clean:
80 | rm -f gpl-3.0.pdf
81 | rm -f lgpl-3.0.pdf
82 | ## }}}
83 |
--------------------------------------------------------------------------------
/doc/gpl-3.0.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZipCPU/dbgbus/a1043274d0a462f986690536f7b2cf97df12051f/doc/gpl-3.0.pdf
--------------------------------------------------------------------------------
/doc/lgpl-3.0.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZipCPU/dbgbus/a1043274d0a462f986690536f7b2cf97df12051f/doc/lgpl-3.0.pdf
--------------------------------------------------------------------------------
/doc/src/lgpl-3.0.tex:
--------------------------------------------------------------------------------
1 | \documentclass[11pt]{article}
2 |
3 | % match lgpl-3.0.txt
4 | \renewcommand{\labelenumii}{\alph{enumii})}
5 | \renewcommand{\labelenumiii}{\arabic{enumiii})}
6 |
7 | \title{GNU LESSER GENERAL PUBLIC LICENSE}
8 | \date{Version 3, 29 June 2007}
9 |
10 | \begin{document}
11 | \maketitle
12 |
13 | \begin{center}
14 | {\parindent 0in
15 |
16 | Copyright \copyright\ 2007 Free Software Foundation, Inc. \texttt{http://fsf.org/}
17 |
18 | \bigskip
19 | Everyone is permitted to copy and distribute verbatim copies of this
20 |
21 | license document, but changing it is not allowed.}
22 |
23 | \end{center}
24 |
25 |
26 | This version of the GNU Lesser General Public License incorporates
27 | the terms and conditions of version 3 of the GNU General Public
28 | License, supplemented by the additional permissions listed below.
29 |
30 | \begin{enumerate}
31 | \addtocounter{enumi}{-1} % start at 0
32 |
33 | \item Additional Definitions.
34 |
35 | As used herein, ``this License'' refers to version 3 of the GNU Lesser
36 | General Public License, and the ``GNU GPL'' refers to version 3 of the GNU
37 | General Public License.
38 |
39 | ``The Library'' refers to a covered work governed by this License,
40 | other than an Application or a Combined Work as defined below.
41 |
42 | An ``Application'' is any work that makes use of an interface provided
43 | by the Library, but which is not otherwise based on the Library.
44 | Defining a subclass of a class defined by the Library is deemed a mode
45 | of using an interface provided by the Library.
46 |
47 | A ``Combined Work'' is a work produced by combining or linking an
48 | Application with the Library. The particular version of the Library
49 | with which the Combined Work was made is also called the ``Linked
50 | Version''.
51 |
52 | The ``Minimal Corresponding Source'' for a Combined Work means the
53 | Corresponding Source for the Combined Work, excluding any source code
54 | for portions of the Combined Work that, considered in isolation, are
55 | based on the Application, and not on the Linked Version.
56 |
57 | The ``Corresponding Application Code'' for a Combined Work means the
58 | object code and/or source code for the Application, including any data
59 | and utility programs needed for reproducing the Combined Work from the
60 | Application, but excluding the System Libraries of the Combined Work.
61 |
62 | \item Exception to Section 3 of the GNU GPL.
63 |
64 | You may convey a covered work under sections 3 and 4 of this License
65 | without being bound by section 3 of the GNU GPL.
66 |
67 | \item Conveying Modified Versions.
68 |
69 | If you modify a copy of the Library, and, in your modifications, a
70 | facility refers to a function or data to be supplied by an Application
71 | that uses the facility (other than as an argument passed when the
72 | facility is invoked), then you may convey a copy of the modified
73 | version:
74 |
75 | \begin{enumerate}
76 | \item under this License, provided that you make a good faith effort to
77 | ensure that, in the event an Application does not supply the
78 | function or data, the facility still operates, and performs
79 | whatever part of its purpose remains meaningful, or
80 |
81 | \item under the GNU GPL, with none of the additional permissions of
82 | this License applicable to that copy.
83 | \end{enumerate}
84 |
85 | \item Object Code Incorporating Material from Library Header Files.
86 |
87 | The object code form of an Application may incorporate material from
88 | a header file that is part of the Library. You may convey such object
89 | code under terms of your choice, provided that, if the incorporated
90 | material is not limited to numerical parameters, data structure
91 | layouts and accessors, or small macros, inline functions and templates
92 | (ten or fewer lines in length), you do both of the following:
93 |
94 | \begin{enumerate}
95 | \item Give prominent notice with each copy of the object code that the
96 | Library is used in it and that the Library and its use are
97 | covered by this License.
98 |
99 | \item Accompany the object code with a copy of the GNU GPL and this license
100 | document.
101 | \end{enumerate}
102 |
103 | \item Combined Works.
104 |
105 | You may convey a Combined Work under terms of your choice that,
106 | taken together, effectively do not restrict modification of the
107 | portions of the Library contained in the Combined Work and reverse
108 | engineering for debugging such modifications, if you also do each of
109 | the following:
110 |
111 | \begin{enumerate}
112 | \item Give prominent notice with each copy of the Combined Work that
113 | the Library is used in it and that the Library and its use are
114 | covered by this License.
115 |
116 | \item Accompany the Combined Work with a copy of the GNU GPL and this license
117 | document.
118 |
119 | \item For a Combined Work that displays copyright notices during
120 | execution, include the copyright notice for the Library among
121 | these notices, as well as a reference directing the user to the
122 | copies of the GNU GPL and this license document.
123 |
124 | \item Do one of the following:
125 |
126 | \begin{enumerate}
127 | \addtocounter{enumiii}{-1} % start at 0
128 | \item Convey the Minimal Corresponding Source under the terms of this
129 | License, and the Corresponding Application Code in a form
130 | suitable for, and under terms that permit, the user to
131 | recombine or relink the Application with a modified version of
132 | the Linked Version to produce a modified Combined Work, in the
133 | manner specified by section 6 of the GNU GPL for conveying
134 | Corresponding Source.
135 |
136 | \item Use a suitable shared library mechanism for linking with the
137 | Library. A suitable mechanism is one that (a) uses at run time
138 | a copy of the Library already present on the user's computer
139 | system, and (b) will operate properly with a modified version
140 | of the Library that is interface-compatible with the Linked
141 | Version.
142 | \end{enumerate}
143 |
144 | \item Provide Installation Information, but only if you would otherwise
145 | be required to provide such information under section 6 of the
146 | GNU GPL, and only to the extent that such information is
147 | necessary to install and execute a modified version of the
148 | Combined Work produced by recombining or relinking the
149 | Application with a modified version of the Linked Version. (If
150 | you use option 4d0, the Installation Information must accompany
151 | the Minimal Corresponding Source and Corresponding Application
152 | Code. If you use option 4d1, you must provide the Installation
153 | Information in the manner specified by section 6 of the GNU GPL
154 | for conveying Corresponding Source.)
155 | \end{enumerate}
156 |
157 | \item Combined Libraries.
158 |
159 | You may place library facilities that are a work based on the
160 | Library side by side in a single library together with other library
161 | facilities that are not Applications and are not covered by this
162 | License, and convey such a combined library under terms of your
163 | choice, if you do both of the following:
164 |
165 | \begin{enumerate}
166 | \item Accompany the combined library with a copy of the same work based
167 | on the Library, uncombined with any other library facilities,
168 | conveyed under the terms of this License.
169 |
170 | \item Give prominent notice with the combined library that part of it
171 | is a work based on the Library, and explaining where to find the
172 | accompanying uncombined form of the same work.
173 | \end{enumerate}
174 |
175 | \item Revised Versions of the GNU Lesser General Public License.
176 |
177 | The Free Software Foundation may publish revised and/or new versions
178 | of the GNU Lesser General Public License from time to time. Such new
179 | versions will be similar in spirit to the present version, but may
180 | differ in detail to address new problems or concerns.
181 |
182 | Each version is given a distinguishing version number. If the
183 | Library as you received it specifies that a certain numbered version
184 | of the GNU Lesser General Public License ``or any later version''
185 | applies to it, you have the option of following the terms and
186 | conditions either of that published version or of any later version
187 | published by the Free Software Foundation. If the Library as you
188 | received it does not specify a version number of the GNU Lesser
189 | General Public License, you may choose any version of the GNU Lesser
190 | General Public License ever published by the Free Software Foundation.
191 |
192 | If the Library as you received it specifies that a proxy can decide
193 | whether future versions of the GNU Lesser General Public License shall
194 | apply, that proxy's public statement of acceptance of any version is
195 | permanent authorization for you to choose that version for the
196 | Library.
197 |
198 | \end{enumerate}
199 |
200 | \end{document}
201 |
202 | %%% Local Variables:
203 | %%% mode: latex
204 | %%% TeX-master: t
205 | %%% End:
206 |
207 |
--------------------------------------------------------------------------------
/hexbus/README.md:
--------------------------------------------------------------------------------
1 | # HexBus Debugging Protocol
2 |
3 | The files in this directory contain a *very simple* protocol for commanding
4 | a wishbone bus. I call it the "Hex Bus" protocol. It is designed to be
5 | a simple demonstration of what can be done with an on-board protocol.
6 |
7 | ## Design Goals
8 |
9 | The protocol was built with two primary goals in mind:
10 |
11 | - It should be easy for someone new to FPGA's to understand
12 |
13 | - It should be easy for someone reading the protocol to understand what's taking place across it.
14 |
15 | Note what's not a part of this protocol: efficiency. There are a lot of
16 | efficiency things that can be added to this bus. Those are left as the
17 | topic of another design on another day.
18 |
19 | ## Posts Describing this port
20 |
21 | This port is being developed and presented as part of the
22 | [ZipCPU Blog](http://zipcpu.com). On that blog, you'll find articles
23 | describing:
24 |
25 | 1. An overview of a debugging wishbone interface
26 | [[Ref]](http://zipcpu.com/blog/2017/06/05/wb-bridge-overview.html)
27 |
28 | 2. A description of the wishbone bus master portion of the interface
29 | [[Ref]](http://zipcpu.com/blog/2017/06/08/simple-wb-master.html)
30 |
31 | 3. A description of the Verilog end of this interface
32 | [[1]](http://zipcpu.com/blog/2017/06/14/creating-words-from-bytes.html)
33 | [[2]](http://zipcpu.com/blog/2017/06/15/words-back-to-bytes.html)
34 | [[3]](http://zipcpu.com/blog/2017/06/16/adding-ints.html)
35 | [[4]](http://zipcpu.com/blog/2017/06/19/debug-idles.html)
36 | [[5]](http://zipcpu.com/blog/2017/06/20/dbg-put-together.html)
37 |
38 | 4. A description of the [software interface](sw)
39 | [[Ref]](http://zipcpu.com/blog/2017/06/29/sw-dbg-interface.html)
40 |
41 | 5. Several articles discussing why you should care about an interface like this
42 | one, or even want one within your own design
43 | [[1]](http://zipcpu.com/blog/2017/05/19/fpga-hell.html)
44 | [[2]](http://zipcpu.com/blog/2017/05/22/a-vision-for-controlling-fpgas.html)
45 | [[3]](http://zipcpu.com/blog/2017/05/26/simpledbg.html)
46 | [[4]](http://zipcpu.com/digilent/2017/05/29/fft-debugging.html)
47 | [[5]](http://zipcpu.com/blog/2017/06/02/design-process.html)
48 | [[6]](http://zipcpu.com/blog/2017/06/16/dbg-bus-forest.html)
49 | [[7]](http://zipcpu.com/blog/2017/06/17/why-network-debugging.html)
50 | [[8]](http://zipcpu.com/blog/2017/06/21/looking-at-verilator.html)
51 | [[9]](http://zipcpu.com/blog/2017/06/28/dbgbus-goal.html)
52 |
53 | 6. A description of the AXI-Lite bus master interface implementation
54 | [[Ref]](http://zipcpu.com/blog/2021/12/30/dbgaxil.html)
55 |
56 |
57 | ## Making things legible
58 |
59 | If you are new to running a command link across a serial port, then you may
60 | be curious how the whole thing works. You'd like to watch the interaction
61 | between the host computer and the FPGA and understand the link. You might
62 | even wish to debug the link, by watching it and seeing what's going on.
63 |
64 | For this reason, every character used on this link is a printable character.
65 | Newlines and carriage returns among them will not break the link. You could
66 | even type commands into the serial port by hand [using a
67 | terminal](http://zipcpu.com/blog/2017/06/26/dbgbus-verilator.html), if you
68 | like. (Not recommended, but there is a time and place for it ...)
69 |
70 | In our port, there are four basic commands that you can send to the FPGA:
71 |
72 | - A set address request starts with an 'A', and it is followed by the address
73 | in question in lower case hexadecimal. Only word addressing is supported,
74 | therefore the last two bits
75 | are special. addr[0], if set, means that subsequent reads (or writes) will
76 | not increment the address. addr[1] if set means this is a difference address
77 | that will be added to the last address.
78 |
79 | - A read request starts with an 'R'. Since the address has already been given,
80 | no further information is required to accomplish a single read.
81 |
82 | - A write request starts with a 'W' and is followed by up to 8 lower case
83 | hexadecimal characters. Any unspecified upper bits are filled with zeros.
84 |
85 | Multiple writes may be separated by either commas, newlines, or any other
86 | character not otherwise used in the protocol.
87 |
88 | - You can also reset the port by sending a 'T' (for reseT).
89 |
90 | The bus will then return a response to these various commands:
91 |
92 | - Set address commands will receive a confirmation containing new address in
93 | response. This response will begin with an 'A', and will end with up to
94 | eight 4-bit hex words.
95 |
96 | - Read request commands will receive a read response. Read responses begin
97 | with and 'R', and they are followed with up to eight hexadecimal characters
98 |
99 | - Write requests are acknowledged with a simple 'W' per request.
100 |
101 | - If reset, the board will respond with a 'T'
102 |
103 | - In an interrupt occurrs on the board, the board will place an 'I' into the
104 | channel. It will not produce any more interrupts down the channel until
105 | the interrupt line is reset
106 |
107 | - If the channel is idle, then periodically an idle byte ('Z') will be sent
108 | through the channel just so you know that it's there.
109 |
110 | - Any and all other "special" responses will start with a 'S' and be followed
111 | by up to 8-hex characters indicating the payload of the response
112 |
113 | As an example, suppose we wish to write a 0x823471 to address 0x01000. If we
114 | prefix commands sent to the bus with "< " and things received with "> ", the
115 | interaction would look something like:
116 |
117 | ```text
118 | > Z
119 | < A1000W823471
120 | > W
121 | > Z
122 | ```
123 |
124 | ## Hex Bus Capabilities
125 |
126 | Eventually, we'll compare and contrast various bus capabilities against each
127 | other. For now, it's worth describing the command link into the FPGA with
128 | the characteristics:
129 |
130 | | Performance Measure | Value |
131 | |:------------------------|------------------:|
132 | | Codeword size | 34-bits |
133 | | Compression | None |
134 | | Data bits used per byte | 4 |
135 | | Vector Read Support | No |
136 | | Asynchronous Read/Write | No |
137 | | Commands Accepted | Set address, Read, Write, Reset |
138 | | Bytes per Address | 2-9 |
139 | | Bytes per Write | 2-9 |
140 | | Bytes per Read | 1 |
141 | | Worst case (Write) Rate | 9(N+1) |
142 |
143 | The reverse link, coming back from the FPGA, may be summarized as:
144 |
145 | | Performance Measure | Value
146 | |:------------------------|------------------:|
147 | | Data bits used per byte | 4 |
148 | | Compression | None |
149 | | Interrupt Support | Yes |
150 | | Vector Read Support | No |
151 | | Asynchronous Read/Write | No |
152 | | Commands Accepted | Set address, Read, Write, Reset, Idle, Interrupt |
153 | | Bytes per Address | 2-9 |
154 | | Bytes per Write | 1 |
155 | | Bytes per Read | 2-9 on return |
156 | | Worst case (Read) Rate | 9(N+1) |
157 |
158 | ## Not Rocket Science
159 |
160 | This command link is far from rocket science. It's not a very high performance
161 | link: it doesn't support compression, can't handle more than one transaction
162 | at a time, has no FIFO support, and has a very low bandwidth at up to 9 bytes
163 | required per transaction. Still, it's a working bus and worth looking into
164 | to understand how such a bus might be written.
165 |
166 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/.gitignore:
--------------------------------------------------------------------------------
1 | hbexec_*/
2 | hbints_*/
3 | hbnewline_*/
4 | hbexecaxi_*/
5 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: Makefile
4 | ## {{{
5 | ## Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | ##
7 | ## Purpose: A formal bench-test makefile. Directs formal proofs only.
8 | ## "make" or "make all" will therefore run all proofs in this
9 | ## directory to completion or failure.
10 | ##
11 | ## Creator: Dan Gisselquist, Ph.D.
12 | ## Gisselquist Technology, LLC
13 | ##
14 | ################################################################################
15 | ## }}}
16 | ## Copyright (C) 2015-2024, Gisselquist Technology, LLC
17 | ## {{{
18 | ## This file is part of the debugging interface demonstration.
19 | ##
20 | ## The debugging interface demonstration is free software (firmware): you can
21 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
22 | ## Public License as published by the Free Software Foundation, either version
23 | ## 3 of the License, or (at your option) any later version.
24 | ##
25 | ## This debugging interface demonstration is distributed in the hope that it
26 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
27 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
28 | ## General Public License
29 | ## for more details.
30 | ##
31 | ## You should have received a copy of the GNU Lesser General Public License
32 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | ## with no target there if the PDF file isn't present.) If not, see
34 | ## for a copy.
35 | ## }}}
36 | ## License: LGPL, v3, as defined and found on www.gnu.org,
37 | ## {{{
38 | ## http://www.gnu.org/licenses/lgpl.html
39 | ##
40 | ################################################################################
41 | ##
42 | ## }}}
43 | # Make certain the "all" target is the first and therefore the default target
44 | .PHONY: all
45 | all: hbexec hbexecaxi hbints hbnewline
46 | #
47 | RTL := ../../rtl
48 | FWB := fwb_master.v
49 | FAXIL := ../../../bench/formal/faxil_master.v
50 |
51 | .PHONY: hbexec
52 | ## {{{
53 | hbexec: hbexec_prf/PASS
54 | hbexec_prf/PASS: hbexec.sby $(RTL)/hbexec.v fwb_master.v
55 | sby -f hbexec.sby prf
56 | ## }}}
57 |
58 | .PHONY: hbexecaxi
59 | ## {{{
60 | hbexecaxi: hbexecaxi_prf/PASS hbexecaxi_prflp/PASS hbexecaxi_cvr/PASS
61 | hbexecaxi_prf/PASS: hbexecaxi.sby $(RTL)/hbexecaxi.v $(FAXIL)
62 | sby -f hbexecaxi.sby prf
63 | hbexecaxi_prflp/PASS: hbexecaxi.sby $(RTL)/hbexecaxi.v $(FAXIL)
64 | sby -f hbexecaxi.sby prflp
65 | hbexecaxi_cvr/PASS: hbexecaxi.sby $(RTL)/hbexecaxi.v $(FAXIL)
66 | sby -f hbexecaxi.sby cvr
67 | ## }}}
68 |
69 | .PHONY: hbints
70 | ## {{{
71 | hbints: hbints_prf/PASS
72 | hbints_prf/PASS: hbints.sby $(RTL)/hbints.v
73 | sby -f hbints.sby prf
74 | ## }}}
75 |
76 | .PHONY: hbnewline
77 | ## {{{
78 | hbnewline: hbnewline_prf/PASS
79 | hbnewline_prf/PASS: hbnewline.sby $(RTL)/hbnewline.v
80 | sby -f hbnewline.sby prf
81 | ## }}}
82 |
83 | .PHONY: clean
84 | ## {{{
85 | clean:
86 | rm -rf hbexec_*/
87 | rm -rf hbexecaxi_*/
88 | rm -rf hbints_*/
89 | rm -rf hbnewline_*/
90 | ## }}}
91 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/hbexec.sby:
--------------------------------------------------------------------------------
1 | [tasks]
2 | prf
3 |
4 | [options]
5 | mode prove
6 | depth 4
7 |
8 | [engines]
9 | smtbmc
10 |
11 | [script]
12 | read -sv fwb_master.v
13 | read -sv hbexec.v
14 | prep -top hbexec
15 |
16 | [files]
17 | fwb_master.v
18 | ../../rtl/hbexec.v
19 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/hbexecaxi.gtkw:
--------------------------------------------------------------------------------
1 | [*]
2 | [*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
3 | [*] Tue Feb 25 19:28:29 2020
4 | [*]
5 | [dumpfile] "(null)"
6 | [timestart] 0
7 | [size] 1920 1054
8 | [pos] -1 -1
9 | *-3.696020 54 -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
10 | [sst_width] 196
11 | [signals_width] 238
12 | [sst_expanded] 1
13 | [sst_vpaned_height] 315
14 | @28
15 | hbexecaxi.i_clk
16 | hbexecaxi.i_reset
17 | @200
18 | -
19 | @28
20 | hbexecaxi.i_cmd_stb
21 | hbexecaxi.o_cmd_busy
22 | @22
23 | hbexecaxi.i_cmd_word[33:0]
24 | @201
25 | -
26 | @28
27 | hbexecaxi.o_rsp_stb
28 | @22
29 | hbexecaxi.o_rsp_word[33:0]
30 | @200
31 | -
32 | @28
33 | hbexecaxi.i_cmd_wr
34 | hbexecaxi.i_cmd_rd
35 | hbexecaxi.i_cmd_addr
36 | @200
37 | -
38 | @28
39 | hbexecaxi.M_AXI_AWVALID
40 | hbexecaxi.M_AXI_AWREADY
41 | @22
42 | hbexecaxi.M_AXI_AWADDR[31:0]
43 | @28
44 | hbexecaxi.M_AXI_AWPROT[2:0]
45 | @200
46 | -
47 | @22
48 | hbexecaxi.M_AXI_WDATA[31:0]
49 | @28
50 | hbexecaxi.M_AXI_WREADY
51 | @22
52 | hbexecaxi.M_AXI_WSTRB[3:0]
53 | @28
54 | hbexecaxi.M_AXI_WVALID
55 | @200
56 | -
57 | @28
58 | hbexecaxi.M_AXI_BREADY
59 | hbexecaxi.M_AXI_BRESP[1:0]
60 | hbexecaxi.M_AXI_BVALID
61 | @200
62 | -
63 | @28
64 | hbexecaxi.M_AXI_ARVALID
65 | hbexecaxi.M_AXI_ARREADY
66 | @22
67 | hbexecaxi.M_AXI_ARADDR[31:0]
68 | @28
69 | hbexecaxi.M_AXI_ARPROT[2:0]
70 | @200
71 | -
72 | @28
73 | hbexecaxi.M_AXI_RVALID
74 | hbexecaxi.M_AXI_RREADY
75 | @22
76 | hbexecaxi.M_AXI_RDATA[31:0]
77 | @28
78 | hbexecaxi.M_AXI_RRESP[1:0]
79 | @200
80 | -
81 | @28
82 | hbexecaxi.newaddr
83 | hbexecaxi.faxil_awr_outstanding[1:0]
84 | hbexecaxi.faxil_rd_outstanding[1:0]
85 | hbexecaxi.faxil_wr_outstanding[1:0]
86 | [pattern_trace] 1
87 | [pattern_trace] 0
88 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/hbexecaxi.sby:
--------------------------------------------------------------------------------
1 | [tasks]
2 | prf
3 | prflp prf opt_lowpower
4 | cvr
5 |
6 | [options]
7 | prf: mode prove
8 | prf: depth 3
9 | cvr: mode cover
10 | cvr: depth 30
11 |
12 | [engines]
13 | smtbmc
14 |
15 | [script]
16 | read -formal faxil_master.v
17 | read -formal -D HBEXECAXI hbexecaxi.v
18 | --pycode-begin--
19 | cmd = "hierarchy -top hbexecaxi"
20 | cmd += " -chparam OPT_LOWPOWER %d" % (1 if "opt_lowpower" in tags else 0);
21 | output(cmd)
22 | --pycode-end--
23 | prep -top hbexecaxi
24 |
25 | [files]
26 | ../../../bench/formal/faxil_master.v
27 | ../../rtl/hbexecaxi.v
28 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/hbints.sby:
--------------------------------------------------------------------------------
1 | [tasks]
2 | prf
3 |
4 | [options]
5 | mode prove
6 | depth 5
7 |
8 | [engines]
9 | smtbmc yices
10 | # smtbmc boolector
11 | # smtbmc z3
12 |
13 | [script]
14 | read_verilog -DHBINTS -formal hbints.v
15 | prep -top hbints
16 |
17 | [files]
18 | ../../rtl/hbints.v
19 |
--------------------------------------------------------------------------------
/hexbus/bench/formal/hbnewline.sby:
--------------------------------------------------------------------------------
1 | [tasks]
2 | prf
3 |
4 | [options]
5 | mode prove
6 | depth 4
7 |
8 | [engines]
9 | smtbmc yices
10 | # smtbmc boolector
11 | # smtbmc z3
12 |
13 | [script]
14 | # read -sv pport.v
15 | read_verilog -DHBNEWLINE -formal hbnewline.v
16 | prep -top hbnewline
17 |
18 | [files]
19 | ../../rtl/hbnewline.v
20 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbaxil.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbaxil.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This is the top level of the debug bus itself, converting
8 | // 8-bit input words to bus requests and bus returns to outgoing
9 | // 8-bit words.
10 | //
11 | // This particular version is modified from hbbus so that it can drive an
12 | // AXI-Lite bus.
13 | //
14 | // Creator: Dan Gisselquist, Ph.D.
15 | // Gisselquist Technology, LLC
16 | //
17 | ////////////////////////////////////////////////////////////////////////////////
18 | // }}}
19 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
20 | // {{{
21 | // This file is part of the hexbus debugging interface.
22 | //
23 | // The hexbus interface is free software (firmware): you can redistribute it
24 | // and/or modify it under the terms of the GNU Lesser General Public License
25 | // as published by the Free Software Foundation, either version 3 of the
26 | // License, or (at your option) any later version.
27 | //
28 | // The hexbus interface is distributed in the hope that it will be useful, but
29 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
30 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
31 | // for more details.
32 | //
33 | // You should have received a copy of the GNU Lesser General Public License
34 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
35 | // with no target there if the PDF file isn't present.) If not, see
36 | // for a copy.
37 | // }}}
38 | // License: LGPL, v3, as defined and found on www.gnu.org,
39 | // {{{
40 | // http://www.gnu.org/licenses/lgpl.html
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 | //
44 | `default_nettype none
45 | // }}}
46 | module hbaxil #(
47 | // {{{
48 | parameter C_AXI_ADDR_WIDTH=32,
49 | localparam DW=32, AW = C_AXI_ADDR_WIDTH-2
50 | // }}}
51 | ) (
52 | // {{{
53 | input wire S_AXI_ACLK,
54 | input wire i_rx_stb,
55 | input wire [7:0] i_rx_byte,
56 | //
57 | output wire M_AXI_AWVALID,
58 | input wire M_AXI_AWREADY,
59 | output wire [AW+1:0] M_AXI_AWADDR,
60 | output wire [2:0] M_AXI_AWPROT,
61 | //
62 | output wire M_AXI_WVALID,
63 | input wire M_AXI_WREADY,
64 | output wire [DW-1:0] M_AXI_WDATA,
65 | output wire [3:0] M_AXI_WSTRB,
66 | //
67 | input wire M_AXI_BVALID,
68 | output wire M_AXI_BREADY,
69 | input wire [1:0] M_AXI_BRESP,
70 | //
71 | output wire M_AXI_ARVALID,
72 | input wire M_AXI_ARREADY,
73 | output wire [AW+1:0] M_AXI_ARADDR,
74 | output wire [2:0] M_AXI_ARPROT,
75 | //
76 | input wire M_AXI_RVALID,
77 | output wire M_AXI_RREADY,
78 | input wire [DW-1:0] M_AXI_RDATA,
79 | input wire [1:0] M_AXI_RRESP,
80 | //
81 | input wire i_interrupt,
82 | output wire o_tx_stb,
83 | output wire [7:0] o_tx_byte,
84 | input wire i_tx_busy
85 | // }}}
86 | );
87 |
88 | // Local declarations
89 | // {{{
90 | wire i_clk;
91 | assign i_clk = S_AXI_ACLK;
92 |
93 | wire w_reset;
94 | wire dec_stb;
95 | wire [4:0] dec_bits;
96 | wire iw_stb;
97 | wire [33:0] iw_word;
98 | wire ow_stb;
99 | wire [33:0] ow_word;
100 | wire idl_busy, int_stb;
101 | wire [33:0] int_word;
102 | wire hb_busy, idl_stb;
103 | wire [33:0] idl_word;
104 | wire hb_stb, hx_busy;
105 | wire [4:0] hb_bits;
106 | wire hx_stb, nl_busy;
107 | wire [6:0] hx_byte;
108 | // verilator lint_off UNUSED
109 | wire wb_busy;
110 | wire int_busy;
111 | // verilator lint_on UNUSED
112 | // }}}
113 |
114 | //
115 | //
116 | // The incoming stream ...
117 | //
118 | //
119 | // First step, convert the incoming bytes into bits
120 | hbdechex
121 | dechxi(
122 | // {{{
123 | .i_clk(i_clk),
124 | .i_stb(i_rx_stb), .i_byte(i_rx_byte),
125 | .o_dh_stb(dec_stb), .o_reset(w_reset), .o_dh_bits(dec_bits)
126 | // }}}
127 | );
128 |
129 |
130 | // ... that can then be transformed into bus command words
131 | hbpack
132 | packxi(
133 | // {{{
134 | .i_clk(i_clk), .i_reset(w_reset),
135 | .i_stb(dec_stb), .i_bits(dec_bits),
136 | .o_pck_stb(iw_stb), .o_pck_word(iw_word)
137 | // }}}
138 | );
139 |
140 | //
141 | // We'll use these bus command words to drive a wishbone bus
142 | //
143 | hbexecaxi #(AW)
144 | axilexec(
145 | // {{{
146 | .i_clk(i_clk), .i_reset(w_reset),
147 | .i_cmd_stb(iw_stb), .i_cmd_word(iw_word), .o_cmd_busy(wb_busy),
148 | .o_rsp_stb(ow_stb), .o_rsp_word(ow_word),
149 | //
150 | .M_AXI_AWVALID(M_AXI_AWVALID),
151 | .M_AXI_AWREADY(M_AXI_AWREADY),
152 | .M_AXI_AWADDR(M_AXI_AWADDR),
153 | .M_AXI_AWPROT(M_AXI_AWPROT),
154 | //
155 | .M_AXI_WVALID(M_AXI_WVALID),
156 | .M_AXI_WREADY(M_AXI_WREADY),
157 | .M_AXI_WDATA(M_AXI_WDATA),
158 | .M_AXI_WSTRB(M_AXI_WSTRB),
159 | //
160 | .M_AXI_BVALID(M_AXI_BVALID),
161 | .M_AXI_BREADY(M_AXI_BREADY),
162 | .M_AXI_BRESP(M_AXI_BRESP),
163 | //
164 | .M_AXI_ARVALID(M_AXI_ARVALID),
165 | .M_AXI_ARREADY(M_AXI_ARREADY),
166 | .M_AXI_ARADDR(M_AXI_ARADDR),
167 | .M_AXI_ARPROT(M_AXI_ARPROT),
168 | //
169 | .M_AXI_RVALID(M_AXI_RVALID),
170 | .M_AXI_RREADY(M_AXI_RREADY),
171 | .M_AXI_RDATA(M_AXI_RDATA),
172 | .M_AXI_RRESP(M_AXI_RRESP)
173 | // }}}
174 | );
175 |
176 | // We'll then take the responses from the bus, and add an interrupt
177 | // flag to the output any time things are idle. This also acts
178 | // as a one-stage FIFO
179 | hbints
180 | addints(
181 | // {{{
182 | .i_clk(i_clk), .i_reset(w_reset), .i_interrupt(i_interrupt),
183 | .i_stb(ow_stb), .i_word(ow_word), .o_int_busy(int_busy),
184 | .o_int_stb(int_stb), .o_int_word(int_word),
185 | .i_busy(idl_busy)
186 | // }}}
187 | );
188 |
189 | //
190 | //
191 | //
192 | hbidle
193 | addidles(
194 | // {{{
195 | .i_clk(i_clk), .i_reset(w_reset),
196 | .i_cmd_stb(int_stb), .i_cmd_word(int_word),
197 | .o_idl_busy(idl_busy),
198 | .o_idl_stb(idl_stb), .o_idl_word(idl_word),
199 | .i_busy(hb_busy)
200 | // }}}
201 | );
202 |
203 | // We'll then take that ouput from that stage, and disassemble the
204 | // response word into smaller (5-bit) sized units ...
205 | hbdeword
206 | unpackx(
207 | // {{{
208 | .i_clk(i_clk), .i_reset(w_reset),
209 | .i_stb(idl_stb), .i_word(idl_word), .o_dw_busy(hb_busy),
210 | .o_dw_stb(hb_stb), .o_dw_bits(hb_bits), .i_tx_busy(hx_busy)
211 | // }}}
212 | );
213 |
214 | // ... that can then be transmitted back down the channel
215 | hbgenhex
216 | genhex(
217 | // {{{
218 | .i_clk(i_clk), .i_reset(w_reset),
219 | .i_stb(hb_stb), .i_bits(hb_bits), .o_gx_busy(hx_busy),
220 | .o_gx_stb(hx_stb), .o_gx_char(hx_byte), .i_busy(nl_busy)
221 | // }}}
222 | );
223 |
224 | //
225 | // We'll also add carriage return newline pairs any time the channel
226 | // goes idle
227 | hbnewline
228 | addnl(
229 | // {{{
230 | .i_clk(i_clk), .i_reset(w_reset),
231 | .i_stb(hx_stb), .i_byte(hx_byte),
232 | .o_nl_busy(nl_busy),
233 | .o_nl_stb(o_tx_stb), .o_nl_byte(o_tx_byte[6:0]),
234 | .i_busy(i_tx_busy)
235 | // }}}
236 | );
237 |
238 | assign o_tx_byte[7] = 1'b0;
239 |
240 | endmodule
241 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbbus.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbbus.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This is the top level of the debug bus itself, converting
8 | // 8-bit input words to bus requests and bus returns to outgoing
9 | // 8-bit words.
10 | //
11 | // Creator: Dan Gisselquist, Ph.D.
12 | // Gisselquist Technology, LLC
13 | //
14 | ////////////////////////////////////////////////////////////////////////////////
15 | // }}}
16 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
17 | // {{{
18 | // This file is part of the hexbus debugging interface.
19 | //
20 | // The hexbus interface is free software (firmware): you can redistribute it
21 | // and/or modify it under the terms of the GNU Lesser General Public License
22 | // as published by the Free Software Foundation, either version 3 of the
23 | // License, or (at your option) any later version.
24 | //
25 | // The hexbus interface is distributed in the hope that it will be useful, but
26 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
27 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
28 | // for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public License
31 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
32 | // with no target there if the PDF file isn't present.) If not, see
33 | // for a copy.
34 | // }}}
35 | // License: LGPL, v3, as defined and found on www.gnu.org,
36 | // {{{
37 | // http://www.gnu.org/licenses/lgpl.html
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 | //
41 | `default_nettype none
42 | // }}}
43 | module hbbus #(
44 | // {{{
45 | parameter AW=30,
46 | localparam DW=32
47 | // }}}
48 | ) (
49 | // {{{
50 | input wire i_clk,
51 | input wire i_rx_stb,
52 | input wire [7:0] i_rx_byte,
53 | output wire o_wb_cyc, o_wb_stb, o_wb_we,
54 | output wire [(AW-1):0] o_wb_addr,
55 | output wire [(DW-1):0] o_wb_data,
56 | output wire [(DW/8-1):0] o_wb_sel,
57 | input wire i_wb_stall, i_wb_ack,
58 | input wire [(DW-1):0] i_wb_data,
59 | input wire i_wb_err,
60 | input wire i_interrupt,
61 | output wire o_tx_stb,
62 | output wire [7:0] o_tx_byte,
63 | input wire i_tx_busy
64 | // }}}
65 | );
66 |
67 | // Local declarations
68 | // {{{
69 | wire w_reset;
70 | wire dec_stb;
71 | wire [4:0] dec_bits;
72 | wire iw_stb;
73 | wire [33:0] iw_word;
74 | wire ow_stb;
75 | wire [33:0] ow_word;
76 | wire idl_busy, int_stb;
77 | wire [33:0] int_word;
78 | wire hb_busy, idl_stb;
79 | wire [33:0] idl_word;
80 | wire hb_stb, hx_busy;
81 | wire [4:0] hb_bits;
82 | wire hx_stb, nl_busy;
83 | wire [6:0] hx_byte;
84 | // verilator lint_off UNUSED
85 | wire wb_busy;
86 | wire int_busy;
87 | // verilator lint_on UNUSED
88 | // }}}
89 |
90 | //
91 | //
92 | // The incoming stream ...
93 | //
94 | //
95 | // First step, convert the incoming bytes into bits
96 | hbdechex
97 | dechxi(
98 | // {{{
99 | .i_clk(i_clk),
100 | .i_stb(i_rx_stb), .i_byte(i_rx_byte),
101 | .o_dh_stb(dec_stb), .o_reset(w_reset), .o_dh_bits(dec_bits)
102 | // }}}
103 | );
104 |
105 |
106 | // ... that can then be transformed into bus command words
107 | hbpack packxi(
108 | // {{{
109 | .i_clk(i_clk), .i_reset(w_reset),
110 | .i_stb(dec_stb), .i_bits(dec_bits),
111 | .o_pck_stb(iw_stb), .o_pck_word(iw_word)
112 | // }}}
113 | );
114 |
115 | //
116 | // We'll use these bus command words to drive a wishbone bus
117 | //
118 | hbexec #(AW)
119 | wbexec(
120 | // {{{
121 | .i_clk(i_clk), .i_reset(w_reset),
122 | .i_cmd_stb(iw_stb), .i_cmd_word(iw_word), .o_cmd_busy(wb_busy),
123 | .o_rsp_stb(ow_stb), .o_rsp_word(ow_word),
124 | .o_wb_cyc(o_wb_cyc), .o_wb_stb(o_wb_stb),
125 | .o_wb_we(o_wb_we), .o_wb_addr(o_wb_addr),
126 | .o_wb_data(o_wb_data), .o_wb_sel(o_wb_sel),
127 | .i_wb_stall(i_wb_stall), .i_wb_ack(i_wb_ack),
128 | .i_wb_err(i_wb_err), .i_wb_data(i_wb_data)
129 | // }}}
130 | );
131 |
132 | // We'll then take the responses from the bus, and add an interrupt
133 | // flag to the output any time things are idle. This also acts
134 | // as a one-stage FIFO
135 | hbints
136 | addints(
137 | // {{{
138 | .i_clk(i_clk), .i_reset(w_reset), .i_interrupt(i_interrupt),
139 | .i_stb(ow_stb), .i_word( ow_word), .o_int_busy(int_busy),
140 | .o_int_stb(int_stb), .o_int_word(int_word), .i_busy(idl_busy)
141 | // }}}
142 | );
143 |
144 | //
145 | //
146 | //
147 | hbidle
148 | addidles(
149 | // {{{
150 | .i_clk(i_clk), .i_reset(w_reset),
151 | .i_cmd_stb(int_stb), .i_cmd_word(int_word),
152 | .o_idl_busy(idl_busy),
153 | .o_idl_stb(idl_stb), .o_idl_word(idl_word),
154 | .i_busy(hb_busy)
155 | // }}}
156 | );
157 |
158 | // We'll then take that ouput from that stage, and disassemble the
159 | // response word into smaller (5-bit) sized units ...
160 | hbdeword
161 | unpackx(
162 | // {{{
163 | .i_clk(i_clk), .i_reset(w_reset),
164 | .i_stb(idl_stb), .i_word(idl_word), .o_dw_busy(hb_busy),
165 | .o_dw_stb(hb_stb), .o_dw_bits(hb_bits), .i_tx_busy(hx_busy)
166 | // }}}
167 | );
168 |
169 | // ... that can then be transmitted back down the channel
170 | hbgenhex
171 | genhex(
172 | // {{{
173 | .i_clk(i_clk), .i_reset(w_reset),
174 | .i_stb(hb_stb), .i_bits(hb_bits), .o_gx_busy(hx_busy),
175 | .o_gx_stb(hx_stb), .o_gx_char(hx_byte), .i_busy(nl_busy)
176 | // }}}
177 | );
178 |
179 | //
180 | // We'll also add carriage return newline pairs any time the channel
181 | // goes idle
182 | hbnewline
183 | addnl(
184 | // {{{
185 | .i_clk(i_clk), .i_reset(w_reset),
186 | .i_stb(hx_stb), .i_byte(hx_byte), .o_nl_busy(nl_busy),
187 | .o_nl_stb(o_tx_stb), .o_nl_byte(o_tx_byte[6:0]),
188 | .i_busy(i_tx_busy)
189 | // }}}
190 | );
191 |
192 | assign o_tx_byte[7] = 1'b0;
193 |
194 | endmodule
195 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbconsole.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbconsole.v
4 | // {{{
5 | // Project: FPGA library
6 | //
7 | // Purpose: This is a replacement wrapper to the original hbbus.v debugging
8 | // bus module. It is intended to provide all of the functionality
9 | // of hbbus, while ...
10 | //
11 | // 1. Keeping the debugging bus within the lower 7-bits of the byte
12 | // 2. Muxing a 7-bit (ascii) console also in the lower 7-bits of the byte
13 | // 3. Using the top bit to indicate which channel is being referenced.
14 | // 1'b1 for dbgbus, 1'b0 for the console.
15 | //
16 | // Creator: Dan Gisselquist, Ph.D.
17 | // Gisselquist Technology, LLC
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | // }}}
21 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
22 | // {{{
23 | // This program is free software (firmware): you can redistribute it and/or
24 | // modify it under the terms of the GNU General Public License as published
25 | // by the Free Software Foundation, either version 3 of the License, or (at
26 | // your option) any later version.
27 | //
28 | // This program is distributed in the hope that it will be useful, but WITHOUT
29 | // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
30 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31 | // for more details.
32 | //
33 | // You should have received a copy of the GNU General Public License along
34 | // with this program. (It's in the $(ROOT)/doc directory. Run make with no
35 | // target there if the PDF file isn't present.) If not, see
36 | // for a copy.
37 | //
38 | // License: GPL, v3, as defined and found on www.gnu.org,
39 | // http://www.gnu.org/licenses/gpl.html
40 | //
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 | //
44 | `default_nettype none
45 | // }}}
46 | module hbconsole #(
47 | // {{{
48 | parameter AW = 30,
49 | localparam DW = 32
50 | // }}}
51 | ) (
52 | // {{{
53 | input wire i_clk,
54 | input wire i_rx_stb,
55 | input wire [7:0] i_rx_byte,
56 | // Wishbone
57 | // {{{
58 | output wire o_wb_cyc, o_wb_stb, o_wb_we,
59 | output wire [AW-1:0] o_wb_addr,
60 | output wire [DW-1:0] o_wb_data,
61 | output wire [DW/8-1:0] o_wb_sel,
62 | input wire i_wb_stall, i_wb_ack, i_wb_err,
63 | input wire [DW-1:0] i_wb_data,
64 | // }}}
65 | input wire i_interrupt,
66 | output wire o_tx_stb,
67 | output wire [7:0] o_tx_data,
68 | input wire i_tx_busy,
69 | //
70 | input wire i_console_stb,
71 | input wire [6:0] i_console_data,
72 | output wire o_console_busy,
73 | //
74 | output reg o_console_stb,
75 | output reg [6:0] o_console_data
76 | // }}}
77 | );
78 |
79 | // Local declarations
80 | // {{{
81 | wire w_reset;
82 | wire dec_stb;
83 | wire [4:0] dec_bits;
84 | wire iw_stb;
85 | wire [33:0] iw_word;
86 | // verilator lint_off UNUSED
87 | wire wb_busy;
88 | // verilator lint_on UNUSED
89 | wire ow_stb;
90 | wire [33:0] ow_word;
91 | // verilator lint_off UNUSED
92 | wire int_busy;
93 | // verilator lint_on UNUSED
94 | wire idl_busy, int_stb;
95 | wire [33:0] int_word;
96 | wire hb_busy, idl_stb;
97 | wire [33:0] idl_word;
98 | wire hb_stb, hx_busy;
99 | wire [4:0] hb_bits;
100 | wire hx_stb, nl_busy;
101 | wire [6:0] hx_byte;
102 | wire fnl_stb;
103 | wire [6:0] fnl_byte;
104 | reg ps_full;
105 | reg [7:0] ps_data;
106 | // }}}
107 |
108 | always @(posedge i_clk)
109 | o_console_stb <= (i_rx_stb)&&(i_rx_byte[7] == 1'b0);
110 | always @(posedge i_clk)
111 | o_console_data <= i_rx_byte[6:0];
112 |
113 |
114 | //
115 | //
116 | // The incoming stream ...
117 | //
118 | //
119 | // First step, convert the incoming bytes into bits
120 | hbdechex
121 | dechxi(
122 | // {{{
123 | .i_clk(i_clk),
124 | .i_stb(i_rx_stb), .i_byte(i_rx_byte),
125 | .o_dh_stb(dec_stb), .o_reset(w_reset), .o_dh_bits(dec_bits)
126 | // }}}
127 | );
128 |
129 |
130 | // ... that can then be transformed into bus command words
131 | hbpack packxi(
132 | // {{{
133 | .i_clk(i_clk), .i_reset(w_reset),
134 | .i_stb(dec_stb), .i_bits(dec_bits),
135 | .o_pck_stb(iw_stb), .o_pck_word(iw_word)
136 | // }}}
137 | );
138 |
139 | //
140 | // We'll use these bus command words to drive a wishbone bus
141 | //
142 | hbexec #(AW)
143 | wbexec(
144 | // {{{
145 | .i_clk(i_clk), .i_reset(w_reset),
146 | .i_cmd_stb(iw_stb), .i_cmd_word(iw_word), .o_cmd_busy(wb_busy),
147 | .o_rsp_stb(ow_stb), .o_rsp_word(ow_word),
148 | .o_wb_cyc(o_wb_cyc), .o_wb_stb(o_wb_stb),
149 | .o_wb_we(o_wb_we), .o_wb_addr(o_wb_addr),
150 | .o_wb_data(o_wb_data), .o_wb_sel(o_wb_sel),
151 | .i_wb_stall(i_wb_stall), .i_wb_ack(i_wb_ack),
152 | .i_wb_err(i_wb_err), .i_wb_data(i_wb_data)
153 | // }}}
154 | );
155 |
156 | // We'll then take the responses from the bus, and add an interrupt
157 | // flag to the output any time things are idle. This also acts
158 | // as a one-stage FIFO
159 | hbints
160 | addints(
161 | // {{{
162 | .i_clk(i_clk), .i_reset(w_reset), .i_interrupt(i_interrupt),
163 | .i_stb(ow_stb), .i_word( ow_word), .o_int_busy(int_busy),
164 | .o_int_stb(int_stb), .o_int_word(int_word), .i_busy(idl_busy)
165 | // }}}
166 | );
167 |
168 | //
169 | //
170 | //
171 | hbidle
172 | addidles(
173 | // {{{
174 | .i_clk(i_clk), .i_reset(w_reset),
175 | .i_cmd_stb(int_stb), .i_cmd_word(int_word),
176 | .o_idl_busy(idl_busy),
177 | .o_idl_stb(idl_stb), .o_idl_word(idl_word),
178 | .i_busy(hb_busy)
179 | // }}}
180 | );
181 |
182 | // We'll then take that ouput from that stage, and disassemble the
183 | // response word into smaller (5-bit) sized units ...
184 | hbdeword
185 | unpackx(
186 | // {{{
187 | i_clk, w_reset,
188 | idl_stb, idl_word, hb_busy,
189 | hb_stb, hb_bits, hx_busy
190 | // }}}
191 | );
192 |
193 | // ... that can then be transmitted back down the channel
194 | hbgenhex
195 | genhex(
196 | // {{{
197 | .i_clk(i_clk), .i_reset(w_reset),
198 | .i_stb(hb_stb), .i_bits(hb_bits), .o_gx_busy(hx_busy),
199 | .o_gx_stb(hx_stb), .o_gx_char(hx_byte), .i_busy(nl_busy)
200 | // }}}
201 | );
202 |
203 | //
204 | // We'll also add carriage return newline pairs any time the channel
205 | // goes idle
206 | hbnewline
207 | addnl(
208 | // {{{
209 | .i_clk(i_clk), .i_reset(w_reset),
210 | .i_stb(hx_stb), .i_byte(hx_byte), .o_nl_busy(nl_busy),
211 | .o_nl_stb(fnl_stb), .o_nl_byte(fnl_byte),
212 | .i_busy((i_tx_busy)&&(ps_full))
213 | // }}}
214 | );
215 |
216 | // ps_full, ps_data
217 | // {{{
218 | // Let's now arbitrate between the two outputs
219 | initial ps_full = 1'b0;
220 | always @(posedge i_clk)
221 | if (!ps_full)
222 | begin
223 | if (fnl_stb)
224 | begin
225 | ps_full <= 1'b1;
226 | ps_data <= { 1'b1, fnl_byte[6:0] };
227 | end else if (i_console_stb)
228 | begin
229 | ps_full <= 1'b1;
230 | ps_data <= { 1'b0, i_console_data[6:0] };
231 | end
232 | end else if (!i_tx_busy)
233 | begin
234 | ps_full <= fnl_stb;
235 | ps_data <= { 1'b1, fnl_byte[6:0] };
236 | end
237 | // }}}
238 |
239 | assign o_tx_stb = ps_full;
240 | assign o_tx_data = ps_data;
241 | assign o_console_busy = (fnl_stb)||(ps_full);
242 | ////////////////////////////////////////////////////////////////////////////////
243 | ////////////////////////////////////////////////////////////////////////////////
244 | ////////////////////////////////////////////////////////////////////////////////
245 | //
246 | // Formal properties
247 | // {{{
248 | ////////////////////////////////////////////////////////////////////////////////
249 | ////////////////////////////////////////////////////////////////////////////////
250 | ////////////////////////////////////////////////////////////////////////////////
251 | `ifdef FORMAL
252 | reg f_past_valid;
253 | initial f_past_valid = 1'b0;
254 | always @(posedge i_clk)
255 | f_past_valid <= 1'b1;
256 |
257 | always @(*)
258 | if (int_busy)
259 | assume(!ow_stb);
260 |
261 | always @(posedge i_clk)
262 | if ((f_past_valid)&&(!$past(w_reset)))
263 | begin
264 | //if (($past(int_stb))&&($past(idl_busy)))
265 | // assert(($stable(int_stb))&&($stable(int_word)));
266 |
267 | if (($past(idl_stb))&&($past(hb_busy)))
268 | assert(($stable(idl_stb))&&($stable(idl_word)));
269 |
270 | if (($past(hb_stb))&&($past(hx_busy)))
271 | assert(($stable(hb_stb))&&($stable(hb_bits)));
272 |
273 | if (($past(hx_stb))&&($past(nl_busy)))
274 | assert(($stable(hx_stb))&&($stable(hx_byte)));
275 |
276 | // if (($past(fnl_stb))&&(!$past(w_reset))&&($past(ps_full)))
277 | // assert(($stable(fnl_stb))&&($stable(fnl_byte)));
278 |
279 | if (($past(i_console_stb))&&($past(o_console_busy)))
280 | assume(($stable(i_console_stb))
281 | &&($stable(i_console_data)));
282 |
283 | if (($past(o_tx_stb))&&($past(i_tx_busy)))
284 | assert(($stable(o_tx_stb))&&($stable(o_tx_data)));
285 | end
286 |
287 | always @(posedge i_clk)
288 | if ((f_past_valid)&&(!$past(w_reset))
289 | &&($past(fnl_stb))&&($past(fnl_byte==7'ha)))
290 | assert((!fnl_stb)||(fnl_byte != 7'h30));
291 |
292 | `endif
293 | // }}}
294 | endmodule
295 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbdechex.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbdechex.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: To decode incoming hexadecimal numbers, together with some
8 | // out of band control characters, into a stream that can be
9 | // further processed into a wishbone bus command stream.
10 | //
11 | // Note that the decoding is stateless, yet it still requires one clock.
12 | //
13 | //
14 | // Creator: Dan Gisselquist, Ph.D.
15 | // Gisselquist Technology, LLC
16 | //
17 | ////////////////////////////////////////////////////////////////////////////////
18 | // }}}
19 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
20 | // {{{
21 | // This file is part of the hexbus debugging interface.
22 | //
23 | // The hexbus interface is free software (firmware): you can redistribute it
24 | // and/or modify it under the terms of the GNU Lesser General Public License
25 | // as published by the Free Software Foundation, either version 3 of the
26 | // License, or (at your option) any later version.
27 | //
28 | // The hexbus interface is distributed in the hope that it will be useful, but
29 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
30 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
31 | // for more details.
32 | //
33 | // You should have received a copy of the GNU Lesser General Public License
34 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
35 | // with no target there if the PDF file isn't present.) If not, see
36 | // for a copy.
37 | //
38 | // License: LGPL, v3, as defined and found on www.gnu.org,
39 | // http://www.gnu.org/licenses/lgpl.html
40 | //
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 | //
44 | `default_nettype none
45 | // }}}
46 | module hbdechex (
47 | // {{{
48 | input wire i_clk, i_stb,
49 | input wire [7:0] i_byte,
50 | output reg o_dh_stb,
51 | output reg o_reset,
52 | output reg [4:0] o_dh_bits
53 | // }}}
54 | );
55 |
56 | initial o_reset = 1'b1;
57 | always @(posedge i_clk)
58 | o_reset <= (i_stb)&&(i_byte[6:0] == 7'h54);
59 |
60 | initial o_dh_stb = 1'b0;
61 | always @(posedge i_clk)
62 | o_dh_stb <= (i_stb)&&(i_byte[6:0] != 7'h7f);
63 |
64 | always @(posedge i_clk)
65 | begin
66 | // These are the defaults, to be overwridden by the ifs below
67 | o_dh_bits <= 5'h00;
68 |
69 | case(i_byte[6:0])
70 | // Transform hexadecimal characters '0' to '9' to their
71 | // binary equivalents, with the out of band flag cleared
72 | 7'h30: o_dh_bits <= 5'h00;
73 | 7'h31: o_dh_bits <= 5'h01;
74 | 7'h32: o_dh_bits <= 5'h02;
75 | 7'h33: o_dh_bits <= 5'h03;
76 | 7'h34: o_dh_bits <= 5'h04;
77 | 7'h35: o_dh_bits <= 5'h05;
78 | 7'h36: o_dh_bits <= 5'h06;
79 | 7'h37: o_dh_bits <= 5'h07;
80 | 7'h38: o_dh_bits <= 5'h08;
81 | 7'h39: o_dh_bits <= 5'h09;
82 | //
83 | // Hexadecimal characters 'a' through 'f'
84 | // (Note that 'A' is used for 'Address' and hence we don't
85 | // support upper case hexadecimal letters here)
86 | 7'h61: o_dh_bits <= 5'h0a;
87 | 7'h62: o_dh_bits <= 5'h0b;
88 | 7'h63: o_dh_bits <= 5'h0c;
89 | 7'h64: o_dh_bits <= 5'h0d;
90 | 7'h65: o_dh_bits <= 5'h0e;
91 | 7'h66: o_dh_bits <= 5'h0f;
92 | //
93 | // Other characters set out of band information (o_dh_bits[4])
94 | // These are primarily the bus command bits
95 | 7'h52: o_dh_bits <= 5'h10; // 'R'
96 | 7'h57: o_dh_bits <= 5'h11; // 'W'
97 | 7'h41: o_dh_bits <= 5'h12; // 'A'
98 | 7'h53: o_dh_bits <= 5'h13; // 'S'
99 | 7'h54: o_dh_bits <= 5'h16; // 'T' --set for form only
100 | default: // an "other" character, to be subsequently ignored.
101 | // Also used as an end of word character, if received
102 | o_dh_bits <= 5'h1f;
103 | endcase
104 | end
105 |
106 | // And just to keep verilator happy
107 | // verilator lint_on UNUSED
108 | wire unused;
109 | assign unused = i_byte[7];
110 | // verilator lint_off UNUSED
111 |
112 | endmodule
113 |
114 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbdeword.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbdeword.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: Once a word has come from the bus, hbdeword turns that 34-bit
8 | // word into a series of 5-bit data values. The top bit of this
9 | // five bit word is an out of band bit, indicating that the top two
10 | // command bits of the interface have changed.
11 | //
12 | //
13 | // Creator: Dan Gisselquist, Ph.D.
14 | // Gisselquist Technology, LLC
15 | //
16 | ////////////////////////////////////////////////////////////////////////////////
17 | // }}}
18 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
19 | // {{{
20 | // This file is part of the hexbus debugging interface.
21 | //
22 | // The hexbus interface is free software (firmware): you can redistribute it
23 | // and/or modify it under the terms of the GNU Lesser General Public License
24 | // as published by the Free Software Foundation, either version 3 of the
25 | // License, or (at your option) any later version.
26 | //
27 | // The hexbus interface is distributed in the hope that it will be useful, but
28 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
29 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
30 | // for more details.
31 | //
32 | // You should have received a copy of the GNU Lesser General Public License
33 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
34 | // with no target there if the PDF file isn't present.) If not, see
35 | // for a copy.
36 | //
37 | // License: LGPL, v3, as defined and found on www.gnu.org,
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 | //
43 | `default_nettype none
44 | // }}}
45 | module hbdeword(
46 | // {{{
47 | input wire i_clk, i_reset,
48 | // The input command word interface
49 | input wire i_stb,
50 | input wire [33:0] i_word,
51 | output wire o_dw_busy,
52 | // The output command word interface
53 | output reg o_dw_stb,
54 | output reg [4:0] o_dw_bits,
55 | input wire i_tx_busy
56 | // }}}
57 | );
58 |
59 | reg [3:0] r_len;
60 | reg [31:0] r_word;
61 |
62 | initial o_dw_stb = 1'b0;
63 | initial r_len = 4'h0;
64 |
65 | always @(posedge i_clk)
66 | if (i_reset)
67 | begin
68 | r_len <= 0;
69 | o_dw_stb <= 0;
70 | end else if ((i_stb)&&(!o_dw_busy))
71 | begin
72 | o_dw_stb <= 1'b1;
73 | if (i_word[33:32] == 2'b11)
74 | r_len <= 4'h0;
75 | else
76 | r_len <= 4'h8;
77 | end else if (!i_tx_busy)
78 | begin
79 | o_dw_stb <= (r_len != 4'h0);
80 | if (r_len != 4'h0)
81 | r_len <= r_len - 1'b1;
82 | end
83 |
84 | always @(posedge i_clk)
85 | // No reset logic needed
86 | if ((i_stb)&&(!o_dw_busy))
87 | r_word <= i_word[31:0];
88 | else if (!i_tx_busy)
89 | // Whenever we aren't busy, a new nibble is accepted
90 | // and the word shifts. If we never set our output
91 | // strobe, this will never become busy, but if the
92 | // register isn't in use, there's no penalty for
93 | // clearing it repeatedly
94 | r_word <= { r_word[27:0], 4'h0 };
95 |
96 | always @(posedge i_clk)
97 | if (i_stb && !o_dw_busy)
98 | begin
99 | if (i_word[33:32] == 2'b11)
100 | o_dw_bits <= i_word[33:29];
101 | else
102 | o_dw_bits <= { 3'b100, i_word[33:32] };
103 | end else if (!i_tx_busy)
104 | o_dw_bits <= { 1'b0, r_word[31:28] };
105 |
106 | assign o_dw_busy = o_dw_stb;
107 |
108 | endmodule
109 |
110 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbgenhex.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbgenhex.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: Supports a conversion from a five digit channel to a printable
8 | // ASCII character representing the lower four bits, or special
9 | // command characters instead if the MSB (fifth bit) is set. We use an
10 | // lowercase hexadecimal for the conversion as follows:
11 | //
12 | // 1'b0,0-9 -> 0-9
13 | // 1'b0,10-15 -> a-f
14 | //
15 | // Other out of band characters are:
16 | //
17 | // 5'h10 -> R (Read)
18 | // 5'h11 -> W (Write)
19 | // 5'h12 -> A (Address)
20 | // 5'h13 -> S (Special)
21 | // 5'h14 -> I (Interrupt)
22 | // 5'h15 -> Z (IDLE)
23 | // 5'h16 -> T (Reset)
24 | //
25 | // All others characters will cause a carriage return, newline pair
26 | // to be sent, with the exception that duplicate carriage return, newlin
27 | // pairs will be suppressed.
28 | //
29 | //
30 | //
31 | // Creator: Dan Gisselquist, Ph.D.
32 | // Gisselquist Technology, LLC
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 | // }}}
36 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
37 | // {{{
38 | // This file is part of the hexbus debugging interface.
39 | //
40 | // The hexbus interface is free software (firmware): you can redistribute it
41 | // and/or modify it under the terms of the GNU Lesser General Public License
42 | // as published by the Free Software Foundation, either version 3 of the
43 | // License, or (at your option) any later version.
44 | //
45 | // The hexbus interface is distributed in the hope that it will be useful, but
46 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
47 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
48 | // for more details.
49 | //
50 | // You should have received a copy of the GNU Lesser General Public License
51 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
52 | // with no target there if the PDF file isn't present.) If not, see
53 | // for a copy.
54 | // }}}
55 | // License: LGPL, v3, as defined and found on www.gnu.org,
56 | // {{{
57 | // http://www.gnu.org/licenses/lgpl.html
58 | //
59 | ////////////////////////////////////////////////////////////////////////////////
60 | //
61 | `default_nettype none
62 | // }}}
63 | module hbgenhex (
64 | // {{{
65 | input wire i_clk, i_reset,
66 | input wire i_stb,
67 | input wire [4:0] i_bits,
68 | output wire o_gx_busy,
69 | output reg o_gx_stb,
70 | output reg [6:0] o_gx_char,
71 | input wire i_busy
72 | // }}}
73 | );
74 |
75 | reg [7:0] w_gx_char;
76 |
77 | // o_gx_stb
78 | // {{{
79 | initial o_gx_stb = 1'b0;
80 | always @(posedge i_clk)
81 | if (i_reset)
82 | o_gx_stb <= 1'b0;
83 | else if (!o_gx_busy)
84 | o_gx_stb <= i_stb;
85 | // }}}
86 |
87 | // w_gx_char
88 | // {{{
89 | always @(*)
90 | case(i_bits)
91 | 5'h00: w_gx_char = "0";
92 | 5'h01: w_gx_char = "1";
93 | 5'h02: w_gx_char = "2";
94 | 5'h03: w_gx_char = "3";
95 | 5'h04: w_gx_char = "4";
96 | 5'h05: w_gx_char = "5";
97 | 5'h06: w_gx_char = "6";
98 | 5'h07: w_gx_char = "7";
99 | 5'h08: w_gx_char = "8";
100 | 5'h09: w_gx_char = "9";
101 | 5'h0a: w_gx_char = "a";
102 | 5'h0b: w_gx_char = "b";
103 | 5'h0c: w_gx_char = "c";
104 | 5'h0d: w_gx_char = "d";
105 | 5'h0e: w_gx_char = "e";
106 | 5'h0f: w_gx_char = "f";
107 | //
108 | 5'h10: w_gx_char = "R"; // Read response w/data
109 | 5'h11: w_gx_char = "K"; // Write ACK
110 | 5'h12: w_gx_char = "A"; // Address was set
111 | 5'h13: w_gx_char = "S"; // Special
112 | //
113 | 5'h18: w_gx_char = "T"; // reseT
114 | 5'h19: w_gx_char = "E"; // BUS Error
115 | 5'h1a: w_gx_char = "I"; // Interrupt
116 | 5'h1b: w_gx_char = "Z"; // Zzzz -- I'm here, but sleeping
117 | default: w_gx_char = 8'hd; // Carriage return
118 | endcase
119 | // }}}
120 |
121 | // o_gx_char
122 | // {{{
123 | initial o_gx_char = 7'h00;
124 | always @(posedge i_clk)
125 | if (!o_gx_busy)
126 | o_gx_char <= w_gx_char[6:0];
127 | // }}}
128 |
129 | assign o_gx_busy = (o_gx_stb)&&(i_busy);
130 |
131 | // Make Verilator happy
132 | // {{{
133 | // Verilator lint_off UNUSED
134 | wire unused;
135 | assign unused = &{ 1'b0, w_gx_char[7] };
136 | // Verilator lint_on UNUSED
137 | // }}}
138 | ////////////////////////////////////////////////////////////////////////////////
139 | ////////////////////////////////////////////////////////////////////////////////
140 | ////////////////////////////////////////////////////////////////////////////////
141 | //
142 | // Formal properties
143 | // {{{
144 | ////////////////////////////////////////////////////////////////////////////////
145 | ////////////////////////////////////////////////////////////////////////////////
146 | ////////////////////////////////////////////////////////////////////////////////
147 | `ifdef FORMAL
148 | `ifdef HBGENHEX
149 | `define ASSUME assume
150 | `define ASSERT assert
151 | `else
152 | `define ASSUME assert
153 | `define ASSERT assert
154 | `endif
155 | ////
156 | reg f_past_valid;
157 | initial f_past_valid = 1'b0;
158 | always @(posedge i_clk)
159 | f_past_valid <= 1'b1;
160 |
161 | always @(posedge i_clk)
162 | if ((f_past_valid)&&(!$past(i_reset))
163 | &&($past(i_stb))&&($past(o_gx_busy)))
164 | `ASSUME(($stable(i_stb))&&($stable(i_bits)));
165 | always @(posedge i_clk)
166 | if ((f_past_valid)&&(!$past(i_reset))
167 | &&($past(o_gx_stb))&&($past(i_busy)))
168 | `ASSERT(($stable(o_gx_stb))&&($stable(o_gx_char)));
169 | always @(posedge i_clk)
170 | if ((f_past_valid)&&(!$past(i_reset))&&($past(i_stb))&&(!$past(i_busy)))
171 | `ASSERT(o_gx_stb);
172 | `endif
173 | // }}}
174 | endmodule
175 |
176 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbidle.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbidle.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the hexbus debugging interface.
17 | //
18 | // The hexbus interface is free software (firmware): you can redistribute it
19 | // and/or modify it under the terms of the GNU Lesser General Public License
20 | // as published by the Free Software Foundation, either version 3 of the
21 | // License, or (at your option) any later version.
22 | //
23 | // The hexbus interface is distributed in the hope that it will be useful, but
24 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
26 | // for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | `default_nettype none
40 | //
41 | `define IDLE_SUB_WORD 5'b11011
42 | `define IDLE_WORD { `IDLE_SUB_WORD, {(34-5){1'b0}} }
43 | //
44 | // }}}
45 | module hbidle (
46 | // {{{
47 | input wire i_clk, i_reset,
48 | //
49 | input wire i_cmd_stb,
50 | input wire [33:0] i_cmd_word,
51 | output wire o_idl_busy,
52 | //
53 | output reg o_idl_stb,
54 | output reg [33:0] o_idl_word,
55 | input wire i_busy
56 | // }}}
57 | );
58 |
59 | // Local declarations
60 | // {{{
61 | // If our bus has been idle for a long time, then set an idle_stb, so
62 | // that we can send a message back just to say that we are alive.
63 | //
64 | reg idle_stb;
65 | `ifdef VERILATOR
66 | reg [22:0] idle_counter;
67 | `else
68 | reg [29:0] idle_counter;
69 | `endif
70 | // }}}
71 |
72 | // idle_stb, idle_counter
73 | // {{{
74 | initial idle_stb = 0;
75 | initial idle_counter = 0;
76 | always @(posedge i_clk)
77 | if ((i_reset)||(i_cmd_stb))
78 | begin
79 | idle_stb <= 1'b0;
80 | idle_counter <= 0;
81 | end else
82 | { idle_stb, idle_counter } <= idle_counter + 1'b1;
83 | // }}}
84 |
85 | // o_idl_stb
86 | // {{{
87 | initial o_idl_stb = 1'b0;
88 | always @(posedge i_clk)
89 | if (i_reset)
90 | o_idl_stb <= 1'b0;
91 | else if ((i_cmd_stb)&&(!o_idl_busy))
92 | o_idl_stb <= 1'b1;
93 | else if ((idle_stb)&&(!o_idl_stb))
94 | o_idl_stb <= 1'b1;
95 | else if (!i_busy)
96 | o_idl_stb <= 1'b0;
97 | // }}}
98 |
99 | // o_idl_word
100 | // {{{
101 | initial o_idl_word = `IDLE_WORD;
102 | always @(posedge i_clk)
103 | if ((i_cmd_stb)&&(!o_idl_busy))
104 | o_idl_word <= i_cmd_word;
105 | else if (!i_busy)
106 | o_idl_word <= `IDLE_WORD;
107 | // }}}
108 |
109 | assign o_idl_busy = (o_idl_stb)&&(i_busy);
110 |
111 | endmodule
112 |
113 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbints.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbints.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the hexbus debugging interface.
17 | //
18 | // The hexbus interface is free software (firmware): you can redistribute it
19 | // and/or modify it under the terms of the GNU Lesser General Public License
20 | // as published by the Free Software Foundation, either version 3 of the
21 | // License, or (at your option) any later version.
22 | //
23 | // The hexbus interface is distributed in the hope that it will be useful, but
24 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
26 | // for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | `default_nettype none
40 | // }}}
41 | module hbints(
42 | // {{{
43 | input wire i_clk, i_reset,
44 | input wire i_interrupt,
45 | //
46 | input wire i_stb,
47 | input wire [33:0] i_word,
48 | output wire o_int_busy,
49 | //
50 | output reg o_int_stb,
51 | output reg [33:0] o_int_word,
52 | input wire i_busy
53 | // }}}
54 | );
55 |
56 | // Local declarations
57 | // {{{
58 | localparam [4:0] INT_PREFIX = 5'b11010;
59 | localparam [33:0] INT_WORD = { INT_PREFIX, {(34-5){1'b0}} };
60 | reg int_state, pending_interrupt, loaded, int_loaded;
61 | // }}}
62 |
63 | // int_state
64 | // {{{
65 | initial int_state = 1'b0;
66 | always @(posedge i_clk)
67 | if (i_reset)
68 | int_state <= 1'b0;
69 | else if ((i_interrupt)&&(!int_state))
70 | int_state <= 1'b1;
71 | else if ((!pending_interrupt)&&(!i_interrupt))
72 | int_state <= 1'b0;
73 | // }}}
74 |
75 | // pending_interrupt
76 | // {{{
77 | initial pending_interrupt = 1'b0;
78 | always @(posedge i_clk)
79 | if (i_reset)
80 | pending_interrupt <= 1'b0;
81 | else if ((i_interrupt)&&(!int_state))
82 | pending_interrupt <= 1'b1;
83 | else if ((o_int_stb)&&(!i_busy)&&(int_loaded))
84 | pending_interrupt <= 1'b0;
85 | // }}}
86 |
87 | // loaded
88 | // {{{
89 | initial loaded = 1'b0;
90 | always @(posedge i_clk)
91 | if (i_reset)
92 | loaded <= 1'b0;
93 | else if ((i_stb)&&(!o_int_busy))
94 | loaded <= 1'b1;
95 | else if ((o_int_stb)&&(!i_busy))
96 | loaded <= 1'b0;
97 | // }}}
98 |
99 | // o_int_stb
100 | // {{{
101 | initial o_int_stb = 1'b0;
102 | always @(posedge i_clk)
103 | if (i_reset)
104 | o_int_stb <= 1'b0;
105 | else if ((i_stb)&&(!o_int_busy))
106 | o_int_stb <= 1'b1;
107 | else if ((pending_interrupt)&&((!int_loaded)||(i_busy)))
108 | o_int_stb <= 1'b1;
109 | else if ((!loaded)||(!i_busy))
110 | o_int_stb <= 1'b0;
111 | // }}}
112 |
113 | // int_loaded, o_int_word
114 | // {{{
115 | initial int_loaded = 1'b1;
116 | initial o_int_word = INT_WORD;
117 | always @(posedge i_clk)
118 | if ((i_stb)&&(!o_int_busy))
119 | begin
120 | int_loaded <= 1'b0;
121 | o_int_word <= i_word;
122 | end else if ((!i_busy)||(!o_int_stb))
123 | begin
124 | // Send an interrupt
125 | o_int_word <= INT_WORD;
126 | int_loaded <= 1'b1;
127 | end
128 | // }}}
129 |
130 | assign o_int_busy = (o_int_stb)&&(loaded);
131 | ////////////////////////////////////////////////////////////////////////////////
132 | ////////////////////////////////////////////////////////////////////////////////
133 | ////////////////////////////////////////////////////////////////////////////////
134 | //
135 | // Formal properties
136 | // {{{
137 | ////////////////////////////////////////////////////////////////////////////////
138 | ////////////////////////////////////////////////////////////////////////////////
139 | ////////////////////////////////////////////////////////////////////////////////
140 | `ifdef FORMAL
141 | `ifdef HBINTS
142 | `define ASSUME assume
143 | `define ASSERT assert
144 | `else
145 | `define ASSUME assert
146 | `define ASSERT assert
147 | `endif
148 |
149 | reg f_past_valid;
150 | initial f_past_valid = 1'b0;
151 |
152 | always @(posedge i_clk)
153 | f_past_valid <= 1'b1;
154 |
155 | always @(posedge i_clk)
156 | if ((f_past_valid)&&(!$past(i_reset))&&($past(i_stb))&&($past(o_int_busy)))
157 | `ASSUME(($stable(i_stb))&&($stable(i_word)));
158 |
159 | always @(posedge i_clk)
160 | if ((f_past_valid)&&(!$past(i_reset))&&($past(i_busy))&&($past(o_int_word != INT_WORD))
161 | &&($past(o_int_stb)))
162 | `ASSERT(($stable(o_int_stb))&&($stable(o_int_word)));
163 |
164 | always @(posedge i_clk)
165 | if ((f_past_valid)&&(!$past(i_reset))&&($past(i_stb))&&(!$past(o_int_busy)))
166 | `ASSERT((o_int_stb)&&(o_int_word == $past(i_word)));
167 |
168 | always @(posedge i_clk)
169 | if ((f_past_valid)&&(!$past(i_reset))&&(o_int_word != INT_WORD))
170 | `ASSERT((!o_int_stb)||(loaded));
171 |
172 | always @(*)
173 | if (loaded)
174 | `ASSERT(o_int_stb);
175 |
176 | always @(*)
177 | if (i_stb)
178 | `ASSUME(i_word != INT_WORD);
179 |
180 | // If we just sent an interrupt signal, then don't send another
181 | always @(posedge i_clk)
182 | if((f_past_valid)&&($past(o_int_stb))&&($past(o_int_word == INT_WORD))
183 | &&(!$past(i_busy)))
184 | `ASSERT((!o_int_stb)||(o_int_word != INT_WORD));
185 |
186 | always @(*)
187 | `ASSERT(int_loaded == (o_int_word == INT_WORD));
188 | /*
189 | reg f_state;
190 | always @(posedge i_clk)
191 | if (f_past_valid)
192 | case(f_state)
193 | if ((f_past_valid)&&($past(i_interrupt))&&(!$past(int_state)))
194 | f_state <= 2'b00
195 | */
196 | `endif
197 | // }}}
198 | endmodule
199 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbnewline.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbnewlines.v
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: Add a newline to the response stream any time the receive bus
8 | // goes from busy to idle.
9 | //
10 | // Creator: Dan Gisselquist, Ph.D.
11 | // Gisselquist Technology, LLC
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | // }}}
15 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
16 | // {{{
17 | // This file is part of the hexbus debugging interface.
18 | //
19 | // The hexbus interface is free software (firmware): you can redistribute it
20 | // and/or modify it under the terms of the GNU Lesser General Public License
21 | // as published by the Free Software Foundation, either version 3 of the
22 | // License, or (at your option) any later version.
23 | //
24 | // The hexbus interface is distributed in the hope that it will be useful, but
25 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
27 | // for more details.
28 | //
29 | // You should have received a copy of the GNU Lesser General Public License
30 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
31 | // with no target there if the PDF file isn't present.) If not, see
32 | // for a copy.
33 | // }}}
34 | // License: LGPL, v3, as defined and found on www.gnu.org,
35 | // {{{
36 | // http://www.gnu.org/licenses/lgpl.html
37 | //
38 | ////////////////////////////////////////////////////////////////////////////////
39 | //
40 | //
41 | `default_nettype none
42 | // }}}
43 | module hbnewline (
44 | // {{{
45 | input wire i_clk, i_reset,
46 | //
47 | input wire i_stb,
48 | input wire [6:0] i_byte,
49 | output wire o_nl_busy,
50 | //
51 | output reg o_nl_stb,
52 | output reg [6:0] o_nl_byte,
53 | input wire i_busy
54 | // }}}
55 | );
56 |
57 | // Local declarations
58 | // {{{
59 | // LAST_CR will be true any time we have sent a carriage return, but
60 | // have not yet sent any valid words. Hence, once the valid words
61 | // stop, last_cr will go true and a carriage return will be sent.
62 | // No further carriage returns will be sent until after the next
63 | // valid word.
64 | reg last_cr;
65 |
66 | // CR_STATE will be true any time we have sent a carriage return, but
67 | // not the following newline
68 | reg cr_state;
69 |
70 | // The loaded register indicates whether or not we have a valid
71 | // command word (that cannot be interrupted) loaded into our buffer.
72 | // Valid words are anything given us from our input, as well as the
73 | // line-feed following a carriage return. We use this logic so that
74 | // a desired output that should only be output when the bus is idle
75 | // (such as a newline) can be pre-empted when a new command comes
76 | // down the interface, but before the bus has had a chance to become
77 | // idle.
78 | reg loaded;
79 | // }}}
80 |
81 | // last_cr, cr_state, o_nl_stb, loaded, o_nl_byte
82 | // {{{
83 | initial last_cr = 1'b1;
84 | initial cr_state = 1'b0;
85 | initial o_nl_stb = 1'b0;
86 | initial loaded = 1'b0;
87 | initial o_nl_byte = 7'h7f;
88 | always @(posedge i_clk)
89 | if (i_reset)
90 | begin
91 | cr_state <= 1'b0;
92 | last_cr <= 1'b1;
93 | o_nl_stb <= 1'b0;
94 | loaded <= 1'b0;
95 | o_nl_byte<= 7'h7f;
96 | end else if ((i_stb)&&(!o_nl_busy))
97 | begin
98 | o_nl_stb <= i_stb;
99 | o_nl_byte <= i_byte;
100 | cr_state <= (i_byte[6:0]==7'hd);
101 | last_cr <= (i_byte[6:0] == 7'hd);
102 | loaded <= 1'b1;
103 | end else if (!i_busy)
104 | begin
105 | if (!last_cr)
106 | begin
107 | // A command just ended, send an
108 | // (interruptable) CR
109 | cr_state <= 1'b1;
110 | o_nl_byte <= 7'hd;
111 | last_cr <= (!i_stb);
112 | o_nl_stb <= (!i_stb);
113 | loaded <= 1'b0;
114 | end else if (cr_state)
115 | begin
116 | cr_state <= 1'b0;
117 | o_nl_byte <= 7'ha;
118 | o_nl_stb <= 1'b1;
119 | loaded <= 1'b1;
120 | end else
121 | begin
122 | loaded <= 1'b0;
123 | o_nl_stb <= 1'b0;
124 | o_nl_byte <= 7'h7f;
125 | end
126 | end
127 | // }}}
128 |
129 | // assign o_nl_busy = (o_nl_stb)&&(loaded);
130 | assign o_nl_busy = ((i_busy)&&(o_nl_stb)&&(loaded))
131 | ||((cr_state)&&(!i_busy));
132 | ////////////////////////////////////////////////////////////////////////////////
133 | ////////////////////////////////////////////////////////////////////////////////
134 | ////////////////////////////////////////////////////////////////////////////////
135 | //
136 | // Formal properties
137 | // {{{
138 | ////////////////////////////////////////////////////////////////////////////////
139 | ////////////////////////////////////////////////////////////////////////////////
140 | ////////////////////////////////////////////////////////////////////////////////
141 | `ifdef FORMAL
142 | `ifdef HBNEWLINE
143 | `define ASSUME assume
144 | `define ASSERT assert
145 | `else
146 | `define ASSUME assert
147 | `define ASSERT assert
148 | `endif
149 |
150 | reg f_past_valid;
151 | initial f_past_valid = 1'b0;
152 | always @(posedge i_clk)
153 | f_past_valid <= 1'b1;
154 |
155 | always @(posedge i_clk)
156 | if ((f_past_valid)&&(!$past(i_reset))&&($past(i_stb))&&($past(o_nl_busy)))
157 | `ASSUME(($stable(i_stb))&&($stable(i_byte)));
158 |
159 | always @(*)
160 | `ASSUME(i_byte != 7'ha);
161 | always @(*)
162 | `ASSUME(i_byte != 7'h7f);
163 |
164 | ///////////////////////////
165 | //
166 | // Stability
167 | //
168 | always @(posedge i_clk)
169 | if ((f_past_valid)&&(!$past(i_reset))&&($past(o_nl_stb))
170 | &&($past(i_busy)))
171 | begin
172 | if ($past(o_nl_byte) != 7'hd)
173 | `ASSERT(($stable(o_nl_stb))&&($stable(o_nl_byte)));
174 | else
175 | `ASSERT((o_nl_byte == 7'hd)
176 | ||(o_nl_byte == $past(i_byte)));
177 | end
178 |
179 | // Forward any incoming bytes immediately to the output
180 | always @(posedge i_clk)
181 | if ((f_past_valid)&&(!$past(i_reset))
182 | &&($past(i_stb))&&(!$past(o_nl_busy)))
183 | `ASSERT((o_nl_stb)&&(o_nl_byte == $past(i_byte)));
184 |
185 | // Following a carriage return, always a new-line
186 | always @(posedge i_clk)
187 | if ((f_past_valid)&&(!$past(i_reset))&&($past(o_nl_stb))
188 | &&(!$past(i_busy))&&($past(o_nl_byte)==7'hd))
189 | `ASSERT((o_nl_stb)&&(o_nl_byte == 7'ha));
190 |
191 | // Following a newline, either a new character or nothing
192 | always @(posedge i_clk)
193 | if ((f_past_valid)&&($past(o_nl_stb))&&(!$past(i_busy))
194 | &&($past(o_nl_byte)==7'ha))
195 | `ASSERT((!o_nl_stb)||(o_nl_byte != 7'ha));
196 |
197 | always @(*)
198 | if (!o_nl_stb)
199 | `ASSERT(o_nl_byte == 7'h7f);
200 |
201 |
202 | // Consistency checks
203 | always @(*)
204 | if ((o_nl_stb)&&(o_nl_byte == 7'hd))
205 | `ASSERT((last_cr)&&(cr_state));
206 | always @(*)
207 | if ((last_cr)&&(o_nl_stb))
208 | `ASSERT((o_nl_byte==7'hd)||(o_nl_byte==7'ha));
209 |
210 | always @(*)
211 | if(!i_stb)
212 | `ASSERT((o_nl_byte == 7'hd)== ((last_cr)&&(cr_state)));
213 |
214 | always @(*)
215 | `ASSERT((o_nl_byte==7'ha)==
216 | ((o_nl_stb)&&(last_cr)&&(!cr_state)&&(loaded)));
217 |
218 | always @(*)
219 | if ((o_nl_byte != 7'h7f)&&(o_nl_byte != 7'hd)&&(o_nl_byte != 7'ha))
220 | `ASSERT((o_nl_stb)&&(loaded)&&(!last_cr)&&(!cr_state));
221 |
222 | always @(*)
223 | if (o_nl_byte == 7'h7f)
224 | `ASSERT((!o_nl_stb)&&(!loaded)&&(last_cr)&&(!cr_state));
225 |
226 | always @(*)
227 | if ((o_nl_stb)&&(o_nl_byte == 7'ha))
228 | `ASSERT((last_cr)&&(!cr_state));
229 |
230 | always @(*)
231 | `ASSERT(cr_state == (o_nl_byte == 7'hd));
232 |
233 | `endif
234 | // }}}
235 | endmodule
236 |
--------------------------------------------------------------------------------
/hexbus/rtl/hbpack.v:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hbpack
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: Given a set of incoming bits (4 at a time, with one out of band
8 | // indicator), turn them into 34-bit command bits for our wishbone
9 | // protocol.
10 | //
11 | // Values 5'h0 through 5'hf are used to build a data word to be sent with
12 | // the 34-bit command as the lower 32 bits.
13 | //
14 | // Any value with the 5'th bit set, 5'h10-5'h1f, is an out of band
15 | // indicator. These are used as indicators to end command words and start
16 | // the next command word. Specific out of band words include:
17 | //
18 | // 5'h10 Read, top 2-bits set to 2'b00
19 | // 5'h11 Write, top 2-bits set to 2'b01
20 | // Payload is the value to be written
21 | //
22 | // 5'h12 Address, top 2-bits set to 2'b10
23 | // Payload is the new address to go to
24 | //
25 | // 5'h13 Special, top 2-bits set to 2'b11
26 | //
27 | // All other out of band characters are quietly ignored
28 | //
29 | // Creator: Dan Gisselquist, Ph.D.
30 | // Gisselquist Technology, LLC
31 | //
32 | ////////////////////////////////////////////////////////////////////////////////
33 | // }}}
34 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
35 | // {{{
36 | // This file is part of the hexbus debugging interface.
37 | //
38 | // The hexbus interface is free software (firmware): you can redistribute it
39 | // and/or modify it under the terms of the GNU Lesser General Public License
40 | // as published by the Free Software Foundation, either version 3 of the
41 | // License, or (at your option) any later version.
42 | //
43 | // The hexbus interface is distributed in the hope that it will be useful, but
44 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
45 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
46 | // for more details.
47 | //
48 | // You should have received a copy of the GNU Lesser General Public License
49 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
50 | // with no target there if the PDF file isn't present.) If not, see
51 | // for a copy.
52 | // }}}
53 | // License: LGPL, v3, as defined and found on www.gnu.org,
54 | // {{{
55 | // http://www.gnu.org/licenses/lgpl.html
56 | //
57 | ////////////////////////////////////////////////////////////////////////////////
58 | //
59 | `default_nettype none
60 | // }}}
61 | module hbpack (
62 | // {{{
63 | input wire i_clk, i_reset,
64 | // The incoming (partially decoded) byte stream
65 | input wire i_stb, // True if something is valid on input
66 | input wire [4:0] i_bits, // Value on input
67 | output reg o_pck_stb,
68 | output reg [33:0] o_pck_word
69 | // }}}
70 | );
71 |
72 | // Local declarations
73 | // {{{
74 | reg cmd_loaded;
75 | reg [33:0] r_word;
76 | // }}}
77 |
78 | // cmd_loaded
79 | // {{{
80 | initial cmd_loaded = 1'b0;
81 | always @(posedge i_clk)
82 | if (i_reset)
83 | cmd_loaded <= 1'b0;
84 | else if ((i_stb)&&(i_bits[4:2] == 3'b100))
85 | cmd_loaded <= 1'b1;
86 | else if ((i_stb)&&(i_bits[4]))
87 | cmd_loaded <= 1'b0;
88 | // }}}
89 |
90 | // o_pck_stb
91 | // {{{
92 | initial o_pck_stb = 1'b0;
93 | always @(posedge i_clk)
94 | o_pck_stb <= (!i_reset)&&((i_stb)&&(cmd_loaded)&&(i_bits[4]));
95 | // }}}
96 |
97 | // r_word
98 | // {{{
99 | initial r_word = 0;
100 | always @(posedge i_clk)
101 | if (i_reset)
102 | r_word <= 0;
103 | else if (i_stb)
104 | begin
105 | if (i_bits[4])
106 | begin
107 | // Record the command into our buffer
108 | r_word[33:32] <= i_bits[1:0];
109 | // Clear our buffer on any new command
110 | r_word[31:0] <= 0;
111 | end else
112 | // Other wise, new hex digits just get
113 | // placed in the bottom of our shift register,
114 | // and everything quietly moves over by one
115 | r_word[31:0] <= { r_word[27:0], i_bits[3:0] };
116 | end
117 | // }}}
118 |
119 | // o_pck_word
120 | // {{{
121 | initial o_pck_word = 0;
122 | always @(posedge i_clk)
123 | if (i_reset)
124 | o_pck_word <= 0;
125 | else if (i_stb)
126 | o_pck_word <= r_word;
127 | // }}}
128 | ////////////////////////////////////////////////////////////////////////////////
129 | ////////////////////////////////////////////////////////////////////////////////
130 | ////////////////////////////////////////////////////////////////////////////////
131 | //
132 | // Formal properties
133 | // {{{
134 | ////////////////////////////////////////////////////////////////////////////////
135 | ////////////////////////////////////////////////////////////////////////////////
136 | ////////////////////////////////////////////////////////////////////////////////
137 | `ifdef FORMAL
138 | `ifdef HBPACK
139 | `define ASSUME assume
140 | `define ASSERT assesrt
141 | `else
142 | `define ASSUME assert
143 | `define ASSERT assert
144 | `endif
145 | reg f_past_valid;
146 | initial f_past_valid = 1'b0;
147 | always @(posedge i_clk)
148 | f_past_valid = 1'b1;
149 |
150 | always @(posedge i_clk)
151 | if ((!f_past_valid)||($past(i_reset)))
152 | begin
153 | `ASSERT(cmd_loaded == 1'b0);
154 | `ASSERT(r_word == 0);
155 | `ASSERT(o_pck_word == 0);
156 | `ASSERT(o_pck_stb == 0);
157 | end
158 |
159 | always @(posedge i_clk)
160 | if ((f_past_valid)&&(!$past(i_reset))
161 | &&($past(i_stb))&&($past(i_bits[4:2])==3'b100))
162 | `ASSERT(cmd_loaded);
163 | `endif
164 | // }}}
165 | endmodule
166 |
--------------------------------------------------------------------------------
/hexbus/sw/hexbus.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: hexbus.h
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This is the C++ program on the command side that will interact
8 | // with a UART on an FPGA, to command the WISHBONE on that same
9 | // FPGA to ... whatever we wish to command it to do.
10 | //
11 | // This code does not run on an FPGA, is not a test bench, neither
12 | // is it a simulator. It is a portion of a command program
13 | // for commanding an FPGA.
14 | //
15 | // Creator: Dan Gisselquist, Ph.D.
16 | // Gisselquist Technology, LLC
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // }}}
20 | // Copyright (C) 20172-2024, Gisselquist Technology, LLC
21 | // {{{
22 | // This file is part of the hexbus debugging interface.
23 | //
24 | // The hexbus interface is free software (firmware): you can redistribute it
25 | // and/or modify it under the terms of the GNU Lesser General Public License
26 | // as published by the Free Software Foundation, either version 3 of the
27 | // License, or (at your option) any later version.
28 | //
29 | // The hexbus interface is distributed in the hope that it will be useful, but
30 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
31 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
32 | // for more details.
33 | //
34 | // You should have received a copy of the GNU Lesser General Public License
35 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
36 | // with no target there if the PDF file isn't present.) If not, see
37 | // for a copy.
38 | // }}}
39 | // License: LGPL, v3, as defined and found on www.gnu.org,
40 | // {{{
41 | // http://www.gnu.org/licenses/lgpl.html
42 | //
43 | ////////////////////////////////////////////////////////////////////////////////
44 | //
45 | // }}}
46 | #ifndef HEXBUS_H
47 | #define HEXBUS_H
48 |
49 | #include "llcomms.h"
50 | #include "devbus.h"
51 |
52 | extern bool gbl_last_readidle;
53 |
54 | class HEXBUS : public DEVBUS {
55 | public:
56 | unsigned long m_total_nread;
57 | private:
58 | LLCOMMSI *m_dev;
59 |
60 | bool m_interrupt_flag, m_addr_set, m_bus_err;
61 | unsigned int m_lastaddr, m_nacks;
62 | bool m_inc, m_isspace;
63 |
64 | int m_buflen;
65 | char *m_buf, m_cmd;
66 |
67 | void init(void) {
68 | m_total_nread = 0;
69 | m_interrupt_flag = false;
70 | m_buflen = 0; m_buf = NULL;
71 | m_addr_set = false;
72 | bufalloc(64);
73 | m_bus_err = false;
74 | m_cmd = 0;
75 | m_nacks = 0;
76 | gbl_last_readidle = true;
77 | }
78 |
79 | void bufalloc(int len);
80 | BUSW readword(void); // Reads a word value from the bus
81 | void readv(const BUSW a, const int inc, const int len, BUSW *buf);
82 | void writev(const BUSW a, const int p, const int len, const BUSW *buf);
83 | void readidle(void);
84 |
85 | int lclreadcode(char *buf, int len);
86 | char *encode_address(const BUSW a);
87 | public:
88 | HEXBUS(LLCOMMSI *comms) : m_dev(comms) { init(); }
89 | virtual ~HEXBUS(void) {
90 | m_dev->close();
91 | if (m_buf)
92 | delete[] m_buf;
93 | m_buf = NULL;
94 | delete m_dev;
95 | }
96 |
97 | void kill(void) { m_dev->close(); }
98 | void close(void) { m_dev->close(); }
99 | void writeio(const BUSW a, const BUSW v);
100 | BUSW readio(const BUSW a);
101 | void readi( const BUSW a, const int len, BUSW *buf);
102 | void readz( const BUSW a, const int len, BUSW *buf);
103 | void writei(const BUSW a, const int len, const BUSW *buf);
104 | void writez(const BUSW a, const int len, const BUSW *buf);
105 | bool poll(void) { return m_interrupt_flag; };
106 | void usleep(unsigned msec); // Sleep until interrupt
107 | void wait(void); // Sleep until interrupt
108 | bool bus_err(void) const { return m_bus_err; };
109 | void reset_err(void) { m_bus_err = false; }
110 | void clear(void) { m_interrupt_flag = false; }
111 | };
112 |
113 | typedef HEXBUS FPGA;
114 |
115 | #endif
116 |
--------------------------------------------------------------------------------
/sw/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ##
3 | ## Filename: Makefile
4 | ## {{{
5 | ## Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | ##
7 | ## Purpose:
8 | ## Targets:
9 | ##
10 | ## Creator: Dan Gisselquist, Ph.D.
11 | ## Gisselquist Technology, LLC
12 | ##
13 | ################################################################################
14 | ## }}}
15 | ## Copyright (C) 2015-2024, Gisselquist Technology, LLC
16 | ## {{{
17 | ## This file is part of the debugging interface demonstration.
18 | ## The debugging interface demonstration is free software (firmware): you can
19 | ## redistribute it and/or modify it under the terms of the GNU Lesser General
20 | ## Public License as published
21 | ## by the Free Software Foundation, either version 3 of the License, or (at
22 | ## your option) any later version.
23 | ##
24 | ## This debugging interface demonstration is distributed in the hope that it
25 | ## will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
26 | ## of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
27 | ## General Public License for more details.
28 | ##
29 | ## You should have received a copy of the GNU Lesser General Public License
30 | ## along with this program. (It's in the $(ROOT)/doc directory. Run make
31 | ## with no target there if the PDF file isn't present.) If not, see
32 | ## for a copy.
33 | ## }}}
34 | ## License: LGPL, v3, as defined and found on www.gnu.org,
35 | ## {{{
36 | ## http://www.gnu.org/licenses/lgpl.html
37 | ##
38 | ##
39 | ################################################################################
40 | ##
41 | .PHONY: all
42 | ## }}}
43 | PROGRAMS := wbregs netuart
44 | SCOPES :=
45 | all: $(PROGRAMS) $(SCOPES)
46 | ## Definitions
47 | ## {{{
48 | CXX := g++
49 | OBJDIR := obj-pc
50 | BUS := hexbus
51 | EXTSRCS := $(BUS).cpp
52 | LCLSRCS := llcomms.cpp regdefs.cpp
53 | BUSSRCS := $(LCLSRCS) $(addprefix ../$(BUS)/sw/,$(EXTSRCS))
54 | DEPSRCS := wbregs.cpp netuart.cpp $(BUSSRCS)
55 | HEADERS := llcomms.h port.h scopecls.h devbus.h $(wildcard ../$(BUS)/sw/*.h)
56 | BUSOBJS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(LCLSRCS) $(EXTSRCS)))
57 | CFLAGS := -g -Wall -I. -I../../rtl -I../$(BUS)/sw
58 | LIBS :=
59 | SUBMAKE := $(MAKE) --no-print-directory -C
60 | ## }}}
61 |
62 | ## Generic targets
63 | ## {{{
64 | .PHONY: objects
65 | objects:
66 | echo $(BUSOBJS)
67 |
68 | %.o: $(OBJDIR)/%.o
69 | $(OBJDIR)/%.o: %.cpp
70 | $(mk-objdir)
71 | $(CXX) $(CFLAGS) -c $< -o $@
72 | $(OBJDIR)/%.o: %.c
73 | $(mk-objdir)
74 | $(CXX) $(CFLAGS) -c $< -o $@
75 | $(OBJDIR)/%.o: ../hexbus/sw/%.cpp
76 | $(mk-objdir)
77 | $(CXX) $(CFLAGS) -c $< -o $@
78 |
79 | $(OBJDIR)/hexbus.o: ../hexbus/sw/hexbus.cpp
80 | $(mk-objdir)
81 | $(CXX) $(CFLAGS) -c $< -o $@
82 | ## }}}
83 |
84 | $(OBJDIR)/dumpflash.o: dumpflash.cpp regdefs.h
85 |
86 | netuart: $(OBJDIR)/netuart.o
87 | $(CXX) $(CFLAGS) $^ -o $@
88 | #
89 | # Some simple programs that just depend upon the ability to talk to the FPGA,
90 | # and little more.
91 | #
92 | wbregs: $(OBJDIR)/wbregs.o $(BUSOBJS)
93 | $(CXX) $(CFLAGS) $^ $(LIBS) -o $@
94 |
95 | ## SCOPES
96 | # These depend upon the scopecls.o, the bus objects, as well as their
97 | # main file(s).
98 | memscope: $(OBJDIR)/memscope.o $(OBJDIR)/scopecls.o $(BUSOBJS)
99 | $(CXX) $(CFLAGS) $^ $(LIBS) -o $@
100 |
101 | define mk-objdir
102 | @bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
103 | endef
104 |
105 | tags: $(DEPSRCS) $(HEADERS)
106 | @echo "Generating tags"
107 | @ctags $(DEPSRCS) $(HEADERS)
108 |
109 | .PHONY: depends
110 | ## {{{
111 | define build-depends
112 | @echo "Building dependency file(s)"
113 | $(mk-objdir)
114 | $(CXX) $(CFLAGS) -MM $(DEPSRCS) > $(OBJDIR)/xdepends.txt
115 | @sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
116 | @rm $(OBJDIR)/xdepends.txt
117 | endef
118 |
119 | depends: $(OBJDIR)/depends.txt
120 |
121 | $(OBJDIR)/depends.txt: $(DEPSRCS) $(HEADERS)
122 | $(build-depends)
123 | ## }}}
124 |
125 | .PHONY: clean
126 | ## {{{
127 | clean:
128 | rm -rf $(OBJDIR)/ $(PROGRAMS) a.out tags *.o
129 | ## }}}
130 |
131 | -include $(OBJDIR)/depends.txt
132 |
--------------------------------------------------------------------------------
/sw/devbus.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: devbus.h
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: The purpose of this file is to document an interface which
8 | // any device with a bus, whether it be implemented over a UART,
9 | // an ethernet, or a PCI express bus, must implement. This describes
10 | // only an interface, and not how that interface is to be accomplished.
11 | //
12 | // The neat part of this interface is that, if programs are designed to
13 | // work with it, than the implementation details may be changed later
14 | // and any program that once worked with the interface should be able
15 | // to continue to do so. (i.e., switch from a UART controlled bus to a
16 | // PCI express controlled bus, with minimal change to the software of
17 | // interest.)
18 | //
19 | //
20 | // Creator: Dan Gisselquist, Ph.D.
21 | // Gisselquist Technology, LLC
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 | // }}}
25 | // Copyright (C) 2015-2024, Gisselquist Technology, LLC
26 | // {{{
27 | // This file is part of the debugging interface demonstration.
28 | //
29 | // The debugging interface demonstration is free software (firmware): you can
30 | // redistribute it and/or modify it under the terms of the GNU Lesser General
31 | // Public License as published by the Free Software Foundation, either version
32 | // 3 of the License, or (at your option) any later version.
33 | //
34 | // This debugging interface demonstration is distributed in the hope that it
35 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
36 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
37 | // General Public License for more details.
38 | //
39 | // You should have received a copy of the GNU Lesser General Public License
40 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
41 | // with no target there if the PDF file isn't present.) If not, see
42 | // for a copy.
43 | // }}}
44 | // License: LGPL, v3, as defined and found on www.gnu.org,
45 | // {{{
46 | // http://www.gnu.org/licenses/lgpl.html
47 | //
48 | ////////////////////////////////////////////////////////////////////////////////
49 | //
50 | // }}}
51 | #ifndef DEVBUS_H
52 | #define DEVBUS_H
53 |
54 | #include
55 | #include
56 |
57 | typedef unsigned int uint32;
58 |
59 | class BUSERR {
60 | public:
61 | uint32 addr;
62 | BUSERR(const uint32 a) : addr(a) {};
63 | };
64 |
65 | class DEVBUS {
66 | public:
67 | typedef uint32 BUSW;
68 |
69 | virtual void kill(void) = 0;
70 | virtual void close(void) = 0;
71 |
72 | // Write a single value to a single address
73 | // a is the address of the value to be read as it exists on the
74 | // wishbone bus within the FPGA.
75 | // v is the singular value to write to this address
76 | virtual void writeio(const BUSW a, const BUSW v) = 0;
77 |
78 | // Read a single value to a single address
79 | // a is the address of the value to be read as it exists on the
80 | // wishbone bus within the FPGA.
81 | // This function returns the value read from the device wishbone
82 | // at address a.
83 | virtual BUSW readio(const BUSW a) = 0;
84 |
85 | // Read a series of values from values from a block of memory
86 | // a is the address of the value to be read as it exists on the
87 | // wishbone bus within the FPGA.
88 | // len is the number of words to read
89 | // buf is a pointer to a place to store the words once read.
90 | // This is equivalent to:
91 | // for(int i=0; i for a copy.
36 | // }}}
37 | // License: LGPL, v3, as defined and found on www.gnu.org,
38 | // {{{
39 | // http://www.gnu.org/licenses/lgpl.html
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 | //
43 | // }}}
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 |
62 | #include "llcomms.h"
63 |
64 | LLCOMMSI::LLCOMMSI(void) {
65 | m_fdw = -1;
66 | m_fdr = -1;
67 | m_total_nread = 0l;
68 | m_total_nwrit = 0l;
69 | }
70 |
71 | void LLCOMMSI::write(char *buf, int len) {
72 | int nw;
73 | nw = ::write(m_fdw, buf, len);
74 | if (nw <= 0) {
75 | throw "Write-Failure";
76 | } else if (nw != len) {
77 | fprintf(stderr, "LLCOMMSI::ERR: %d byte write request, only %d written\n", len, nw);
78 | assert(nw == len);
79 | }
80 | m_total_nwrit += nw;
81 | assert(nw == len);
82 | }
83 |
84 | int LLCOMMSI::read(char *buf, int len) {
85 | int nr;
86 | nr = ::read(m_fdr, buf, len);
87 | if (nr <= 0) {
88 | throw "Read-Failure";
89 | }
90 | m_total_nread += nr;
91 | return nr;
92 | }
93 |
94 | void LLCOMMSI::close(void) {
95 | if(m_fdw>=0)
96 | ::close(m_fdw);
97 | if((m_fdr>=0)&&(m_fdr != m_fdw))
98 | ::close(m_fdr);
99 | m_fdw = m_fdr = -1;
100 | }
101 |
102 | bool LLCOMMSI::poll(unsigned ms) {
103 | struct pollfd fds;
104 |
105 | fds.fd = m_fdr;
106 | fds.events = POLLIN;
107 | ::poll(&fds, 1, ms);
108 |
109 | if (fds.revents & POLLIN) {
110 | return true;
111 | } else return false;
112 | }
113 |
114 | int LLCOMMSI::available(void) {
115 | return poll(0)?1:0;
116 | }
117 |
118 | TTYCOMMS::TTYCOMMS(const char *dev) {
119 | m_fdr = ::open(dev, O_RDWR | O_NONBLOCK);
120 | if (m_fdr < 0) {
121 | printf("\n Error : Could not open %s\n", dev);
122 | perror("O/S Err:");
123 | exit(-1);
124 | }
125 |
126 | if (isatty(m_fdr)) {
127 | struct termios tb;
128 | tcgetattr(m_fdr, &tb);
129 | cfmakeraw(&tb);
130 | // tb.c_iflag &= (~(IXON|IXOFF));
131 | tb.c_cflag &= (~(CRTSCTS));
132 | tcsetattr(m_fdr, TCSANOW, &tb);
133 | tcflow(m_fdr, TCOON);
134 | }
135 |
136 | m_fdw = m_fdr;
137 | }
138 |
139 | NETCOMMS::NETCOMMS(const char *host, const int port) {
140 | struct sockaddr_in serv_addr;
141 | struct hostent *hp;
142 |
143 | if ((m_fdr = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
144 | printf("\n Error : Could not create socket \n");
145 | exit(-1);
146 | }
147 |
148 | memset(&serv_addr, '0', sizeof(serv_addr));
149 |
150 | hp = gethostbyname(host);
151 | if (hp == NULL) {
152 | printf("Could not get host entity for %s\n", host);
153 | perror("O/S Err:");
154 | exit(-1);
155 | }
156 | bcopy(hp->h_addr, &serv_addr.sin_addr.s_addr, hp->h_length);
157 |
158 | serv_addr.sin_family = AF_INET;
159 | serv_addr.sin_port = htons(port);
160 |
161 | if (connect(m_fdr,(struct sockaddr *)&serv_addr, sizeof(serv_addr))< 0){
162 | perror("Connect Failed Err");
163 | exit(-1);
164 | }
165 |
166 | m_fdw = m_fdr;
167 | }
168 |
169 | void NETCOMMS::close(void) {
170 | int nr;
171 | char buf[256];
172 |
173 | shutdown(m_fdw, SHUT_WR);
174 | while(1) {
175 | nr = ::read(m_fdr, buf, sizeof(buf));
176 | if (nr <= 0)
177 | break;
178 | }
179 | ::close(m_fdw);
180 | }
181 |
--------------------------------------------------------------------------------
/sw/llcomms.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: llcomms.h
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: This is the C++ program on the command side that will interact
8 | // with a UART on an FPGA, both sending and receiving characters.
9 | // Any bus interaction will call routines from this lower level library to
10 | // accomplish the actual connection to and transmission to/from the board.
11 | //
12 | // Creator: Dan Gisselquist, Ph.D.
13 | // Gisselquist Technology, LLC
14 | //
15 | ////////////////////////////////////////////////////////////////////////////////
16 | // }}}
17 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
18 | // {{{
19 | // This file is part of the debugging interface demonstration.
20 | //
21 | // The debugging interface demonstration is free software (firmware): you can
22 | // redistribute it and/or modify it under the terms of the GNU Lesser General
23 | // Public License as published by the Free Software Foundation, either version
24 | // 3 of the License, or (at your option) any later version.
25 | //
26 | // This debugging interface demonstration is distributed in the hope that it
27 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
28 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
29 | // General Public License for more details.
30 | //
31 | // You should have received a copy of the GNU Lesser General Public License
32 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | // with no target there if the PDF file isn't present.) If not, see
34 | // for a copy.
35 | // }}}
36 | // License: LGPL, v3, as defined and found on www.gnu.org,
37 | // {{{
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 | //
42 | // }}}
43 | #ifndef LLCOMMS_H
44 | #define LLCOMMS_H
45 |
46 | class LLCOMMSI {
47 | protected:
48 | int m_fdw, m_fdr;
49 | LLCOMMSI(void);
50 | public:
51 | unsigned long m_total_nread, m_total_nwrit;
52 |
53 | virtual ~LLCOMMSI(void) { close(); }
54 | virtual void kill(void) { this->close(); };
55 | virtual void close(void);
56 | virtual void write(char *buf, int len);
57 | virtual int read(char *buf, int len);
58 | virtual bool poll(unsigned ms);
59 |
60 | // Tests whether or not bytes are available to be read, returns a
61 | // count of the bytes that may be immediately read
62 | virtual int available(void); // { return 0; };
63 | };
64 |
65 | class TTYCOMMS : public LLCOMMSI {
66 | public:
67 | TTYCOMMS(const char *dev);
68 | };
69 |
70 | class NETCOMMS : public LLCOMMSI {
71 | public:
72 | NETCOMMS(const char *dev, const int port);
73 | virtual void close(void);
74 | };
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/sw/memscope.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: memscope.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the debugging interface demonstration.
17 | //
18 | // The debugging interface demonstration is free software (firmware): you can
19 | // redistribute it and/or modify it under the terms of the GNU Lesser General
20 | // Public License as published by the Free Software Foundation, either version
21 | // 3 of the License, or (at your option) any later version.
22 | //
23 | // This debugging interface demonstration is distributed in the hope that it
24 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
26 | // General Public License for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 |
49 | #include "port.h"
50 | #include "regdefs.h"
51 | #include "scopecls.h"
52 | #include "hexbus.h"
53 |
54 | #define WBSCOPE R_SCOPE
55 | #define WBSCOPEDATA R_SCOPD
56 |
57 | FPGA *m_fpga;
58 |
59 | class MEMSCOPE : public SCOPE {
60 | public:
61 | MEMSCOPE(FPGA *fpga, unsigned addr) : SCOPE(fpga, addr) {};
62 | ~MEMSCOPE(void) {}
63 |
64 | virtual void define_traces(void) {
65 | //
66 | register_trace("wb_cyc", 1, 31);
67 | register_trace("wb_stb", 1, 30);
68 | register_trace("wb_we", 1, 29);
69 | register_trace("wb_ack", 1, 28);
70 | register_trace("wb_stall", 1, 27);
71 | register_trace("wb_addr", 6, 21);
72 | register_trace("wb_odata", 10, 10);
73 | register_trace("wb_idata", 10, 0);
74 | }
75 |
76 | virtual void decode(DEVBUS::BUSW val) const {
77 | int cyc, stb, we, ack, stall, addr, odata, idata;
78 |
79 | cyc = (val >> 31)&1;
80 | stb = (val >> 30)&1;
81 | we = (val >> 29)&1;
82 | ack = (val >> 28)&1;
83 | stall = (val >> 27)&1;
84 | addr = (val >> 21)&0x3f;
85 | odata = (val >> 10)&0x3ff;
86 | idata = (val )&0x3ff;
87 |
88 | printf("%s", (cyc)?"CYC":" ");
89 | printf(" %s", (stb)?"STB":" ");
90 | printf(" %s", (we) ?"W" :"R");
91 | printf("[@....%02x]...%03x->...%03x", addr, odata, idata);
92 | printf(" %s", (ack)?"ACK":" ");
93 | printf(" %s", (stall)?"(STALL)":" ");
94 | }
95 | };
96 |
97 | int main(int argc, char **argv) {
98 | // Open and connect to our FPGA. This macro needs to be defined in the
99 | // include files above.
100 | FPGAOPEN(m_fpga);
101 |
102 | // Here, we open a scope. An MEMSCOPE specifically. The difference
103 | // between an MEMSCOPE and any other scope is ... that the
104 | // MEMSCOPE has particular things wired to particular bits, whereas
105 | // a generic scope ... just has data.
106 | MEMSCOPE *scope = new MEMSCOPE(m_fpga, WBSCOPE);
107 |
108 | if (!scope->ready()) {
109 | // If we get here, then ... nothing started the scope.
110 | // It either hasn't primed, hasn't triggered, or hasn't finished
111 | // recording yet. Trying to read data would do nothing but
112 | // read garbage, so we don't try.
113 | printf("Scope is not yet ready:\n");
114 | scope->decode_control();
115 | } else {
116 | // The scope has been primed, triggered, the holdoff wait
117 | // period has passed, and the scope has now stopped.
118 | //
119 | // Hence we can read from our scope the values we need.
120 | scope->print();
121 | // If we want, we can also write out a VCD file with the data
122 | // we just read.
123 | scope->writevcd("scopd.vcd");
124 | }
125 |
126 | // Now, we're all done. Let's be nice to our interface and shut it
127 | // down gracefully, rather than letting the O/S do it in ... whatever
128 | // manner it chooses.
129 | delete m_fpga;
130 | }
131 |
--------------------------------------------------------------------------------
/sw/port.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: port.h
4 | // {{{
5 | // Project: dbgbus, a collection of channel to 8-bit bus debugging protocols
6 | //
7 | // Purpose: Defines the communication parameters necessary for communicating
8 | // both with our actual hardware device, as well as with our Verilator
9 | // simulation. The result is that whatever communicates with the other may
10 | // not know the difference (as desired).
11 | //
12 | //
13 | // Creator: Dan Gisselquist, Ph.D.
14 | // Gisselquist Technology, LLC
15 | //
16 | ////////////////////////////////////////////////////////////////////////////////
17 | // }}}
18 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
19 | // {{{
20 | // This file is part of the debugging interface demonstration.
21 | //
22 | // The debugging interface demonstration is free software (firmware): you can
23 | // redistribute it and/or modify it under the terms of the GNU Lesser General
24 | // Public License as published by the Free Software Foundation, either version
25 | // 3 of the License, or (at your option) any later version.
26 | //
27 | // This debugging interface demonstration is distributed in the hope that it
28 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
30 | // General Public License for more details.
31 | //
32 | // You should have received a copy of the GNU Lesser General Public License
33 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
34 | // with no target there if the PDF file isn't present.) If not, see
35 | // for a copy.
36 | // }}}
37 | // License: LGPL, v3, as defined and found on www.gnu.org,
38 | // {{{
39 | // http://www.gnu.org/licenses/lgpl.html
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 | //
43 | // }}}
44 | #ifndef PORT_H
45 | #define PORT_H
46 |
47 | // There are two ways to connect: via a serial port, and via a TCP socket
48 | // connected to a serial port. This way, we can connect the device on one
49 | // computer, test it, and when/if it doesn't work we can replace the device
50 | // with the test-bench. Across the network, no one will know any better that
51 | // anything had changed.
52 | #define FPGAHOST "localhost" // Whatever computer is used to run this
53 | #define FPGAPORT 9401 // A somewhat random port number--CHANGEME
54 |
55 | #define FPGAOPEN(V) V= new FPGA(new NETCOMMS(FPGAHOST, FPGAPORT))
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/sw/regdefs.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: regdefs.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose:
8 | //
9 | // Creator: Dan Gisselquist, Ph.D.
10 | // Gisselquist Technology, LLC
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////
13 | // }}}
14 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
15 | // {{{
16 | // This file is part of the debugging interface demonstration.
17 | //
18 | // The debugging interface demonstration is free software (firmware): you can
19 | // redistribute it and/or modify it under the terms of the GNU Lesser General
20 | // Public License as published by the Free Software Foundation, either version
21 | // 3 of the License, or (at your option) any later version.
22 | //
23 | // This debugging interface demonstration is distributed in the hope that it
24 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
26 | // General Public License for more details.
27 | //
28 | // You should have received a copy of the GNU Lesser General Public License
29 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
30 | // with no target there if the PDF file isn't present.) If not, see
31 | // for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include "regdefs.h"
45 |
46 | const REGNAME raw_bregs[] = {
47 | { R_VERSION , "VERSION" },
48 | { R_BUSERR , "BUSERR" },
49 | { R_PWRCOUNT , "PWRCOUNT" },
50 | { R_INT , "int" },
51 | { R_HALT , "halt" },
52 | { R_SCOPE , "SCOPE" },
53 | { R_SCOPD , "SCOPD" },
54 | { R_MEM , "MEM" },
55 | { R_MEM , "RAM" }
56 | };
57 |
58 | // REGSDEFS.CPP.INSERT for any bus masters
59 | // And then from the peripherals
60 | // And finally any master REGS.CPP.INSERT tags
61 | #define RAW_NREGS (sizeof(raw_bregs)/sizeof(bregs[0]))
62 |
63 | const REGNAME *bregs = raw_bregs;
64 | const int NREGS = RAW_NREGS;
65 |
66 | unsigned addrdecode(const char *v) {
67 | if (isalpha(v[0])) {
68 | for(int i=0; i for a copy.
32 | // }}}
33 | // License: LGPL, v3, as defined and found on www.gnu.org,
34 | // {{{
35 | // http://www.gnu.org/licenses/lgpl.html
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 | //
39 | // }}}
40 | #ifndef REGDEFS_H
41 | #define REGDEFS_H
42 |
43 | #define R_VERSION 0x00002040
44 | #define R_SOMETHING 0x00002044
45 | #define R_BUSERR 0x00002048
46 | #define R_PWRCOUNT 0x0000204c
47 | #define R_INT 0x00002050
48 | #define R_HALT 0x00002054
49 |
50 | #define R_SCOPE 0x00002080
51 | #define R_SCOPD 0x00002084
52 |
53 | #define R_MEM 0x00004000
54 |
55 | static const int BAUDRATE=4000000;
56 |
57 | typedef struct {
58 | unsigned m_addr;
59 | const char *m_name;
60 | } REGNAME;
61 |
62 | extern const REGNAME *bregs;
63 | extern const int NREGS;
64 | // #define NREGS (sizeof(bregs)/sizeof(bregs[0]))
65 |
66 | extern unsigned addrdecode(const char *v);
67 | extern const char *addrname(const unsigned v);
68 |
69 | #endif // REGDEFS_H
70 |
--------------------------------------------------------------------------------
/sw/scopecls.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: scopecls.h
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: After rebuilding the same code over and over again for every
8 | // "scope" I tried to interact with, I thought it would be simpler
9 | // to try to make a more generic interface, that other things could plug
10 | // into. This file defines and describes that more generic interface.
11 | //
12 | // More recent updates have added to this interface those things necessary
13 | // to create a .VCD file for viewing in GTKWave.
14 | //
15 | // Creator: Dan Gisselquist, Ph.D.
16 | // Gisselquist Technology, LLC
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // }}}
20 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
21 | // {{{
22 | // This file is part of the debugging interface demonstration.
23 | //
24 | // The debugging interface demonstration is free software (firmware): you can
25 | // redistribute it and/or modify it under the terms of the GNU Lesser General
26 | // Public License as published by the Free Software Foundation, either version
27 | // 3 of the License, or (at your option) any later version.
28 | //
29 | // This debugging interface demonstration is distributed in the hope that it
30 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
31 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
32 | // General Public License for more details.
33 | //
34 | // You should have received a copy of the GNU Lesser General Public License
35 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
36 | // with no target there if the PDF file isn't present.) If not, see
37 | // for a copy.
38 | // }}}
39 | // License: LGPL, v3, as defined and found on www.gnu.org,
40 | // {{{
41 | // http://www.gnu.org/licenses/lgpl.html
42 | //
43 | ////////////////////////////////////////////////////////////////////////////////
44 | //
45 | // }}}
46 | #ifndef SCOPECLS_H
47 | #define SCOPECLS_H
48 |
49 | #include
50 | #include "devbus.h"
51 |
52 |
53 | /*
54 | * TRACEINFO
55 | * {{{
56 | * The TRACEINFO class describes a wire (or set of wires) internal to the
57 | * scope data word. These wires are assumed to be contiguous, and given by:
58 | * ((data_word>>m_nshift)&((1< m_traces;
99 |
100 | public:
101 | SCOPE(DEVBUS *fpga, unsigned addr,
102 | bool compressed=false, bool vecread=true)
103 | : m_fpga(fpga), m_addr(addr),
104 | m_compressed(compressed), m_vector_read(vecread),
105 | m_scoplen(0), m_data(NULL) {
106 | //
107 | // First thing we want to do upon allocating a scope, is to
108 | // define the traces for that scope. Sad thing is ... we can't
109 | // call it here, since the class inheriting from us isn't
110 | // defined yet.
111 | // define_traces();
112 |
113 |
114 | // Default clock frequency: 100MHz.
115 | m_clkfreq_hz = 100000000;
116 | }
117 |
118 | // Free up any of our allocated memory.
119 | ~SCOPE(void) {
120 | for(unsigned i=0; i 0))
227 | return m_data[(addr)&(m_scoplen-1)];
228 | return 0;
229 | }
230 | };
231 |
232 | #endif // SCOPECLS_H
233 |
--------------------------------------------------------------------------------
/sw/wbregs.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Filename: wbregs.cpp
4 | // {{{
5 | // Project: dbgbus, a collection of 8b channel to WB bus debugging protocols
6 | //
7 | // Purpose: To give a user access, via a command line program, to read
8 | // and write wishbone registers one at a time. Thus this program
9 | // implements readio() and writeio() but nothing more.
10 | //
11 | //
12 | // Creator: Dan Gisselquist, Ph.D.
13 | // Gisselquist Technology, LLC
14 | //
15 | ////////////////////////////////////////////////////////////////////////////////
16 | // }}}
17 | // Copyright (C) 2017-2024, Gisselquist Technology, LLC
18 | // {{{
19 | // This file is part of the debugging interface demonstration.
20 | //
21 | // The debugging interface demonstration is free software (firmware): you can
22 | // redistribute it and/or modify it under the terms of the GNU Lesser General
23 | // Public License as published by the Free Software Foundation, either version
24 | // 3 of the License, or (at your option) any later version.
25 | //
26 | // This debugging interface demonstration is distributed in the hope that it
27 | // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
28 | // of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
29 | // General Public License for more details.
30 | //
31 | // You should have received a copy of the GNU Lesser General Public License
32 | // along with this program. (It's in the $(ROOT)/doc directory. Run make
33 | // with no target there if the PDF file isn't present.) If not, see
34 | // for a copy.
35 | // }}}
36 | // License: LGPL, v3, as defined and found on www.gnu.org,
37 | // {{{
38 | // http://www.gnu.org/licenses/lgpl.html
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 | //
42 | // }}}
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 |
52 | #include "port.h"
53 | #include "regdefs.h"
54 | #include "hexbus.h"
55 |
56 | FPGA *m_fpga;
57 | void closeup(int v) {
58 | m_fpga->kill();
59 | exit(0);
60 | }
61 |
62 | bool isvalue(const char *v) {
63 | const char *ptr = v;
64 |
65 | while(isspace(*ptr))
66 | ptr++;
67 |
68 | if ((*ptr == '+')||(*ptr == '-'))
69 | ptr++;
70 | if (*ptr == '+')
71 | ptr++;
72 | if (*ptr == '0') {
73 | ptr++;
74 | if (tolower(*ptr) == 'x')
75 | ptr++;
76 | }
77 |
78 | return (isdigit(*ptr));
79 | }
80 |
81 | void usage(void) {
82 | printf("USAGE: wbregs [-d] address [value]\n"
83 | "\n"
84 | "\tWBREGS stands for Wishbone registers. It is designed to allow a\n"
85 | "\tuser to peek and poke at registers within a given FPGA design, so\n"
86 | "\tlong as those registers have addresses on the wishbone bus. The\n"
87 | "\taddress may reference peripherals or memory, depending upon how the\n"
88 | "\tbus is configured.\n"
89 | "\n"
90 | "\t-d\tIf given, specifies the value returned should be in decimal,\n"
91 | "\t\trather than hexadecimal.\n"
92 | "\n"
93 | "\t-n [host]\tAttempt to connect, via TCP/IP, to host named [host].\n"
94 | "\t\tThe default host is \'%s\'\n"
95 | "\n"
96 | "\t-p [port]\tAttempt to connect, via TCP/IP, to port number [port].\n"
97 | "\t\tThe default port is \'%d\'\n"
98 | "\n"
99 | "\tAddress is either a 32-bit value with the syntax of strtoul, or a\n"
100 | "\tregister name. Register names can be found in regdefs.cpp\n"
101 | "\n"
102 | "\tIf a value is given, that value will be written to the indicated\n"
103 | "\taddress, otherwise the result from reading the address will be \n"
104 | "\twritten to the screen.\n", FPGAHOST, FPGAPORT);
105 | }
106 |
107 | int main(int argc, char **argv) {
108 | int skp=0;
109 | bool use_decimal = false;
110 | const char *host = FPGAHOST;
111 | int port=FPGAPORT;
112 |
113 | skp=1;
114 | for(int argn=0; argn= argc) {
120 | fprintf(stderr, "ERR: No network host given\n");
121 | exit(EXIT_SUCCESS);
122 | }
123 | host = argv[argn+skp+1];
124 | skp++; argn--;
125 | } else if (argv[argn+skp][1] == 'p') {
126 | if (argn+skp+1 >= argc) {
127 | fprintf(stderr, "ERR: No network port # given\n");
128 | exit(EXIT_SUCCESS);
129 | }
130 | port = strtoul(argv[argn+skp+1], NULL, 0);
131 | skp++; argn--;
132 | } else {
133 | usage();
134 | exit(EXIT_SUCCESS);
135 | }
136 | skp++; argn--;
137 | } else
138 | argv[argn] = argv[argn+skp];
139 | } argc -= skp;
140 |
141 | m_fpga = new FPGA(new NETCOMMS(host, port));
142 |
143 | signal(SIGSTOP, closeup);
144 | signal(SIGHUP, closeup);
145 |
146 | if ((argc < 1)||(argc > 2)) {
147 | // usage();
148 | printf("USAGE: wbregs address [value]\n");
149 | exit(-1);
150 | }
151 |
152 | const char *nm = NULL, *named_address = argv[0];
153 | unsigned address, value;
154 |
155 | if (isvalue(named_address)) {
156 | address = strtoul(named_address, NULL, 0);
157 | nm = addrname(address);
158 | } else {
159 | address = addrdecode(named_address);
160 | nm = addrname(address);
161 | }
162 |
163 | if (NULL == nm)
164 | nm = "";
165 |
166 | if (argc < 2) {
167 | FPGA::BUSW v;
168 | try {
169 | unsigned char a, b, c, d;
170 | v = m_fpga->readio(address);
171 | a = (v>>24)&0x0ff;
172 | b = (v>>16)&0x0ff;
173 | c = (v>> 8)&0x0ff;
174 | d = (v )&0x0ff;
175 | if (use_decimal)
176 | printf("%d\n", v);
177 | else
178 | printf("%08x (%8s) : [%c%c%c%c] %08x\n", address, nm,
179 | isgraph(a)?a:'.', isgraph(b)?b:'.',
180 | isgraph(c)?c:'.', isgraph(d)?d:'.', v);
181 | } catch(BUSERR b) {
182 | printf("%08x (%8s) : BUS-ERROR\n", address, nm);
183 | } catch(const char *er) {
184 | printf("Caught bug: %s\n", er);
185 | exit(EXIT_FAILURE);
186 | }
187 | } else {
188 | try {
189 | value = strtoul(argv[1], NULL, 0);
190 | m_fpga->writeio(address, value);
191 | printf("%08x (%8s)-> %08x\n", address, nm, value);
192 | } catch(BUSERR b) {
193 | printf("%08x (%8s) : BUS-ERR)R\n", address, nm);
194 | exit(EXIT_FAILURE);
195 | } catch(const char *er) {
196 | printf("Caught bug on write: %s\n", er);
197 | exit(EXIT_FAILURE);
198 | }
199 | }
200 |
201 | if (m_fpga->poll())
202 | printf("FPGA was interrupted\n");
203 | delete m_fpga;
204 | }
205 |
206 |
--------------------------------------------------------------------------------