├── .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 | --------------------------------------------------------------------------------