├── README.md ├── docs ├── Manual │ ├── CAT-manual.tex │ ├── pics │ │ ├── CAT_3D.png │ │ ├── CAT_components.png │ │ ├── CAT_cover.jpg │ │ ├── CAT_gerber_bottom.png │ │ ├── CAT_gerber_gnd.png │ │ ├── CAT_gerber_pwr.png │ │ ├── CAT_gerber_top.png │ │ ├── CAT_layout.png │ │ ├── CAT_pcb.JPG │ │ ├── CAT_pcb_back.JPG │ │ └── CAT_schematic.pdf │ └── xess.sty └── readthedocs │ ├── authors.md │ ├── contributing.md │ ├── history.md │ ├── index.md │ ├── installation.md │ ├── licenses.md │ ├── usage.md │ ├── xess.ico │ └── xess.png ├── mkdocs.yml ├── pcb ├── CAT-cache.lib ├── CAT-rescue.lib ├── CAT.kicad_pcb ├── CAT.pro ├── CAT.sch ├── Compute_Module.sch ├── FPGA.sch ├── FPGA_CFG.sch ├── FPGA_IO.sch ├── FPGA_PWR.sch ├── Memory.sch ├── assembly_order.txt ├── pcb_art.svg ├── rookie_head.png └── sym-lib-table └── tests ├── README.md ├── RNG_with_MyHDL.ipynb ├── SDRAM_Controller ├── Clk.py ├── Conversion.py ├── SdramCntl.py ├── __init__.py ├── host_intf.py ├── sd_intf.py ├── sdram.py ├── test_controller.py └── test_sdram.py ├── __init__.py ├── buttons_display.py ├── config_cat ├── ex_catboard_buttons.py ├── ex_catboard_leddisp.py ├── ex_catboard_sdram.py ├── ice40_primitives.py ├── lattice_sdram_test └── sdram_test │ ├── sdram_test_Implmnt │ └── sbt │ │ └── constraint │ │ └── sdram_test_pcf_sbt.pcf │ ├── sdram_test_sbt.project │ └── sdram_test_syn.prj ├── led_digits_display.py ├── rand_gen.py ├── reset_cat ├── sdram_test.py └── sdram_test.v /README.md: -------------------------------------------------------------------------------- 1 | # CAT 2 | 3 | 4 | # Description 5 | 6 | The CAT Board is a Raspberry Pi HAT with a Lattice iCE40HX FPGA. 7 | 8 | * License: [CC BY 4.0](http://creativecommons.org/licenses/by/4.0/legalcode) 9 | * Documentation: [CAT-Board.readthedocs.org](https://CAT-Board.readthedocs.org) 10 | 11 | 12 | # Features 13 | 14 | * Lattice iCE40-HX8K FPGA in 256-pin BGA. 15 | * 32 MByte SDRAM (16M x 16). 16 | * Serial configuration flash (at least 2 Mbit). 17 | * Three Grove connectors. 18 | * Two PMOD connectors. 19 | * One 20x2 header with 3.3V, ground and 18 FPGA I/Os. 20 | * Two SATA headers (for differential signals; don't know if they would work with SATA HDDs.) 21 | * DIP switch with four SPST switches. 22 | * Two momentary pushbuttons. 23 | * Four LEDs. 24 | * 100 MHz oscillator. 25 | * 5.0 V jack for external power supply. 26 | * 3.3 V and 1.2 V regulators. 27 | * Adjustable voltage on one bank of FPGA I/O pins. 28 | * 32 KByte HAT EEPROM. 29 | * 40-pin RPi GPIO header. 30 | 31 | 32 | [ CAT Schematic ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_schematic.pdf) 33 | 34 | [![Click to watch YouTube Video](http://img.youtube.com/vi/EHtcOrdl9Xw/0.jpg)](http://www.youtube.com/watch?v=EHtcOrdl9Xw "CAT Board: First Look") 35 | 36 | ![ CAT Picture ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_cover.jpg) 37 | ![ CAT PCB ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_pcb.JPG) 38 | -------------------------------------------------------------------------------- /docs/Manual/CAT-manual.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % THIS IS NOT THE MANUAL! 4 | % It's just a manual from another project that I'll edit/fill-in later. 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | 8 | 9 | \documentclass[letterpaper,11pt,oneside]{memoir} 10 | 11 | \usepackage{xess} 12 | 13 | \product[CAT] 14 | \manualnum{XXX} 15 | \manualversion{0.1} 16 | \newcommand{\copyrightyear}{2015} 17 | \newcommand{\xula}{XuLA Board} 18 | 19 | % Turn off pictures for now. 20 | \renewcommand{\fixedpic}[1]{} 21 | 22 | 23 | \begin{document} 24 | 25 | \frontmatter 26 | 27 | \makexessmanualtitlepage{CAT_cover.jpg}{0.7} 28 | 29 | \makexesslegal{\copyrightyear} 30 | 31 | \begin{xessrevisiontbl} 32 | 2015-10-07 & \manualversion & Initial release for \product\ \manualversion.\\ 33 | \hline 34 | \end{xessrevisiontbl} 35 | 36 | \makexesstoc 37 | 38 | \mainmatter 39 | 40 | \chapter{Preliminaries} 41 | 42 | Here's some helpful information before getting started. 43 | 44 | 45 | \section{Getting Help!} 46 | 47 | Here are some places to get help if you encounter problems: 48 | 49 | \begin{itemize} 50 | \item If you can't get the \product\ to work, send an e-mail message 51 | describing your problem to \href{mailto:\helpemail}{\helpemail}. 52 | \item Or submit a problem report at \url{\helppage}. 53 | \item \href{http://www.xess.com}{Our web site} also has 54 | \begin{itemize} 55 | \item \href{http://www.xess.com/projects/}{example designs}, 56 | \item \href{http://www.xess.com/appnotes/}{application notes}, and 57 | \item \href{http://www.xess.com/tutorials/}{tutorials}. 58 | % \item answers to frequently-asked-questions, 59 | % \item \href{}{a forum where you can post questions}. 60 | \end{itemize} 61 | \end{itemize} 62 | 63 | 64 | \section{Take Notice!} 65 | 66 | \begin{itemize} 67 | \item The \xula\ is not 5V-tolerant. \warning{Do not connect 5V logic signals 68 | to the \digpmod\ sockets of the \product.} 69 | \item \warning{Only power the \product\ with a regulated 5 VDC, 70 | center-positive power supply.} 71 | \end{itemize} 72 | 73 | 74 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 | 76 | \section{Packing List} 77 | 78 | Here is what you should have received in your package: 79 | 80 | \begin{itemize} 81 | \item a \product. 82 | \item a 20\by 2 socket. 83 | \item a 20\by 2 header. 84 | \end{itemize} 85 | 86 | 87 | \chapter{Setup} 88 | 89 | The \product\ accepts a \xula\ and provides it with connections to 90 | separate StickIt! modules such as LED displays, buttons, audio I/O, etc. 91 | 92 | \section{Inserting a XuLA Board into Your \texorpdfstring{\product}{StickIt! Board}} 93 | 94 | You insert a \xula\ into the central row of sockets on the \product\ as 95 | shown below. Make sure the \xula\ prototyping header pins line-up with the sockets 96 | and that the USB connector is oriented towards the \product\ RESET button. 97 | 98 | \fixedpic{\includegraphics[width=0.7\textwidth]{stickit_with_xula.jpg}} 99 | 100 | To insure a stable connection with the \product, the \xula\ should 101 | have 0.025'' square posts soldered into its prototyping header. 102 | \warning{The 0.019'' round posts used for mounting a \xula\ into a solderless 103 | breadboard should not be used or else intermittent connections will occur!} 104 | 105 | \section{Applying Power to Your \texorpdfstring{\product}{StickIt! Board}} 106 | 107 | There are several ways to power the combination of your \xula\ and \product. 108 | Each of these will be discussed below. 109 | 110 | \subsection{Applying Power Through the USB Port} 111 | 112 | Connecting the \xula\ to a USB port provides it with a 5V supply capable of 113 | delivering up to 500 mA of current. 114 | The 5V supply can also power the \product\ and any attached StickIt! modules by 115 | placing a shunt on the XULA-PWR jumper as shown below. 116 | 117 | \fixedpic{\includegraphics[width=0.7\textwidth]{XULA_PWR.jpg}} 118 | 119 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 120 | 121 | \subsection{Applying Power Though the Power Jack} 122 | 123 | For applications that require more power than the USB port can provide, you can 124 | attach a regulated, 5 VDC center-positive power adapter to the 5VDC jack on the 125 | \product. 126 | In this case, the shunt should be removed from the XULA-PWR 127 | jumper and placed on the 5V-PWR jumper as shown below. 128 | In this configuration, the USB port powers the \xula\ while the adapter powers 129 | the \product\ and any attached StickIt! modules. 130 | 131 | \fixedpic{\includegraphics[width=0.7\textwidth]{5V_PWR.jpg}} 132 | 133 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 134 | 135 | \subsection{Applying Power to Stand-Alone Applications} 136 | 137 | For applications that operate stand-alone with no connection to a USB port, you 138 | can attach a regulated, 5 VDC center-positive power adapter to the 5VDC jack on 139 | the \product. 140 | In addition, shunts should be placed on both the XULA-PWR 141 | and 5V-PWR jumpers as shown below. 142 | This will transfer power from the adapter through the \product\ to the \xula. 143 | 144 | \fixedpic{\includegraphics[width=0.7\textwidth]{Standalone_PWR.jpg}} 145 | 146 | \warning{A USB cable should not be attached to the \xula\ in this 147 | configuration or damage may result from the direct connection of the power 148 | adapter to the 5V supply pin of the USB port!} 149 | 150 | In order to prevent inadvertent damage, you can remove the shunt on 5V jumper of the 151 | \xula\ to disconnect the USB 5V supply as shown below. Note that doing this will 152 | prevent you from powering the \xula\ through the USB port until the 5V shunt is 153 | restored. 154 | \warning{By default, the 5V jumper is closed by a wire trace on the underside 155 | of the \xula! You will need to cut this trace to open the jumper.} 156 | 157 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 158 | 159 | \subsection{Applying Power from a \rpi} 160 | 161 | The \product\ can get power through the GPIO connector of a \rpi\ 162 | by placing a shunt on the GPIO-5V jumper. 163 | This connects the 5V supply from the \rpi\ to the same power rail as the 5V power jack. 164 | Because of this, \warning{a power adapter should not be connected to the 5V jack in this 165 | configuration or damage may result from the direct connection of the power 166 | adapter to the 5V supply of the \rpi!} 167 | A power adapter \emphasis{can} be used to power the \product\ when it is attached 168 | to a \rpi\ only if the shunt is removed from the GPIO-5V jumper. 169 | In addition, \warning{a shunt should \emphasis{never} be placed on the GPIO-3.3V jumper 170 | when the \product\ is attached to the \rpi.} 171 | 172 | \fixedpic{\includegraphics[width=0.7\textwidth]{RPI_PWR.jpg}} 173 | 174 | 175 | \chapter{Connections} 176 | 177 | This chapter describes the various sections of the \product\ and shows how 178 | the \xula\ I/O connects to them. 179 | In addition to the partial schematics that follow, you can find a 180 | complete schematic at the end of this manual. 181 | 182 | 183 | \section{XuLA Board Socket} 184 | 185 | A \xula\ connects to the \product\ through the J1 socket. 186 | 187 | \fixedpic{\includegraphics[width=0.5\textwidth]{XuLA_socket.png}} 188 | 189 | Please note the following: 190 | 191 | \begin{itemize} 192 | \item The \xula\ 5V pin is connected to the +5V-XULA signal on the \product. 193 | This allows the \xula\ to send power to or receive power from the \product. 194 | This is the only voltage supply shared by both the \xula\ and the \product. 195 | \item The \xula\ 3.3V and 1.2V pins do not connect to anything else on the \product. 196 | \item The \xula\ ground is connected to the \product\ ground. 197 | \item The reset pin of the \xula\ connects to the to the RESET button 198 | on the \product. Pushing this button resets the \xula. 199 | \item The analog I/O pins of the \xula\ do not connect to anything else 200 | on the \product. 201 | \end{itemize} 202 | 203 | Here are the FPGA pins connected to each channel for both the XuLA and XuLA2 Boards: 204 | 205 | \begin{center} 206 | \renewcommand{\arraystretch}{1.3} 207 | \begin{tabu}{|l|l|l|c||c|l|l|l|} 208 | \hline 209 | \xesstblhdr 210 | XuLA & XuLA2 & J1 & \multicolumn{2}{c|}{Pin\#} & J1 & XuLA2 & XuLA\\ 211 | \hline\hline 212 | AN1 & AN1 & & 1 & 21 & RESET & RESET & RESET \\\hline 213 | AN0 & AN0 & & 2 & 22 & & +1.2V & +1.2V \\\hline 214 | +5V & +5V & +5V & 3 & 23 & GND & GND & GND \\\hline 215 | P88 & A2 & CH31 & 4 & 24 & & +3.3V & +3.3V \\\hline 216 | P89 & B2 & CH30 & 5 & 25 & CH14 & B15 & P84 \\\hline 217 | P93 & B1 & CH29 & 6 & 26 & CH13 & B16 & P83 \\\hline 218 | P94 & C1 & CH28 & 7 & 27 & CH12 & C15 & P82 \\\hline 219 | P97 & E2 & CH27 & 8 & 28 & CH11 & C16 & P73 \\\hline 220 | P3 & E1 & CH26 & 9 & 29 & CH10 & F16 & P72 \\\hline 221 | P4 & F2 & CH25 & 10 & 30 & CH9 & F15 & P68 \\\hline 222 | P7 & F1 & CH24 & 11 & 31 & CH8 & J14 & P62 \\\hline 223 | P12 & H2 & CH23 & 12 & 32 & CH7 & J16 & P61 \\\hline 224 | P13 & H1 & CH22 & 13 & 33 & CH6 & K16 & P57 \\\hline 225 | P19 & J4 & CH21 & 14 & 34 & CH5 & K15 & P56 \\\hline 226 | P20 & K3 & CH20 & 15 & 35 & CH4 & M16 & P52 \\\hline 227 | P21 & M1 & CH19 & 16 & 36 & CH3 & M15 & P50 \\\hline 228 | P32 & M2 & CH18 & 17 & 37 & CH2 & R16 & P39 \\\hline 229 | P33 & R1 & CH17 & 18 & 38 & CH1 & R15 & P37 \\\hline 230 | P34 & R2 & CH16 & 19 & 39 & CH0 & R7 & P36 \\\hline 231 | P35 & T4 & CH15 & 20 & 40 & CHCLK & T7 & P44 \\\hline 232 | \end{tabu} 233 | \label{tab:ChanneltoFPGAConnections} 234 | \end{center} 235 | 236 | 237 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 238 | 239 | \section{Power Circuitry} 240 | 241 | The \product\ accepts +5V from either 242 | \begin{itemize} 243 | \item a \xula\ (when there is a shunt on the XULA-PWR jumper), 244 | \item an external power adapter (when there is a shunt on the 5V-PWR jumper), or 245 | \item a \rpi (when there is a shunt on the GPIO-5V jumper). 246 | \end{itemize} 247 | 248 | The \product\ voltage regulator creates the +3.3V supply. 249 | 250 | \fixedpic{\includegraphics[width=0.7\textwidth]{pwr_circuit.png}} 251 | 252 | Be aware that placing shunts on both the XULA-PWR and 5V-PWR jumpers will 253 | connect the external power adapter to the \xula\ power supply. 254 | \warning{This will cause damage} unless 1) the USB cable is removed from the \xula, 255 | or 2) the 5V jumper on the \xula\ is open. 256 | (Note that in its factory-original 257 | configuration, the 5V jumper on the \xula\ is shorted by a wiring trace on 258 | the bottom of the PCB which must be cut to disconnect the 5V supply from the 259 | USB port.) 260 | 261 | Also be aware that placing shunts on both the XuLA-PWR and GPIO-5V jumpers 262 | when the \product\ is attached to a \rpi\ 263 | will connect the external power adapter to the \rpi\ 5V supply. 264 | \warning{This will cause damage!} 265 | There must \emphasis{never} be a shunt on both the XuLA-PWR and GPIO-5V jumpers 266 | when the \product\ is attached to a \rpi. 267 | 268 | 269 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 270 | 271 | \section{\digpmod\ Sockets} 272 | 273 | There are three sockets (PM1\textendash PM3) for connecting external \digpmod\ modules 274 | to the \product. 275 | All of these sockets accept either four-bit or eight-bit \digpmod\ modules. 276 | (There are also five sockets for connecting 277 | \href{http://www.seeedstudio.com/wiki/Category:Grove}{Grove boards}, 278 | but these are covered by the \digpmod\ sockets and can't be used. 279 | Just ignore them. 280 | Really, act like they're not even there.) 281 | 282 | \fixedpic{\includegraphics[width=0.5\textwidth]{pmod_sockets.png}} 283 | 284 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 285 | 286 | A total of 24 channels connect from the \xula\ to the \digpmod\ 287 | sockets, so you can use any combination of modules that require 24 total I/Os or less. 288 | The channel connections to each of the \digpmod\ sockets are shown in the 289 | following table: 290 | 291 | \begin{center} 292 | \renewcommand{\arraystretch}{1.3} 293 | \begin{tabu}{|l|l|c||c|l|l|} 294 | \hline 295 | \xesstblhdr 296 | Chan & \digpmod\ I/O & \multicolumn{2}{c|}{Pin\#} & \digpmod\ I/O & Chan\\ 297 | \hline\hline 298 | \multicolumn{6}{|c|}{\cellcolor[gray]{0.7} PM1}\\ 299 | \hline 300 | CH0 & D0 & 1 & 7 & D1 & CHCLK \\\hline 301 | CH2 & D2 & 2 & 8 & D3 & CH1 \\\hline 302 | CH4 & D4 & 3 & 9 & D5 & CH3 \\\hline 303 | CH6 & D6 & 4 & 10 & D7 & CH5 \\\hline 304 | & GND & 5 & 11 & GND & \\\hline 305 | & VCC & 6 & 12 & VCC & \\\hline 306 | \hline 307 | \multicolumn{6}{|c|}{\cellcolor[gray]{0.7} PM2}\\ 308 | \hline 309 | CH15 & D0 & 1 & 7 & D1 & CH16 \\\hline 310 | CH17 & D2 & 2 & 8 & D3 & CH18 \\\hline 311 | CH19 & D4 & 3 & 9 & D5 & CH20 \\\hline 312 | CH21 & D6 & 4 & 10 & D7 & CH22 \\\hline 313 | & GND & 5 & 11 & GND & \\\hline 314 | & VCC & 6 & 12 & VCC & \\\hline 315 | \hline 316 | \multicolumn{6}{|c|}{\cellcolor[gray]{0.7} PM3}\\ 317 | \hline 318 | CH23 & D0 & 1 & 7 & D1 & CH24 \\\hline 319 | CH25 & D2 & 2 & 8 & D3 & CH26 \\\hline 320 | CH27 & D4 & 3 & 9 & D5 & CH28 \\\hline 321 | CH29 & D6 & 4 & 10 & D7 & CH30 \\\hline 322 | & GND & 5 & 11 & GND & \\\hline 323 | & VCC & 6 & 12 & VCC & \\\hline 324 | \end{tabu} 325 | \label{tab:ChanneltoPMODConnections} 326 | \end{center} 327 | 328 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 329 | 330 | The physical arrangement of the \digpmod\ I/O signals is shown below. 331 | 332 | \fixedpic{\includegraphics[width=0.7\textwidth]{PMOD_socket.jpg}} 333 | 334 | Each \digpmod\ socket has an associated jumper to connect either the 3.3V or 5V power 335 | supply to the attached module. 336 | In their factory-original configuration, each of these jumpers is set to 3.3V 337 | by a shorting trace on the bottom of the \product\ PCB. 338 | You must cut this trace and install a jumper and shunt if you want to use a 5V module. 339 | 340 | \fixedpic{\includegraphics[width=0.7\textwidth]{shorting_traces.jpg}} 341 | 342 | 343 | \section{\rpi\ GPIO Connector} 344 | 345 | You can solder a 20\by 2 socket to the GPIO port of the \product\ 346 | so it can be connected to a \rpi. 347 | The GPIO port provides 26 general-purpose I/O pins (the rest are for power, ground, 348 | and access to the serial EEPROM on the \product.) 349 | 350 | \fixedpic{\includegraphics[width=0.5\textwidth]{rpi_socket.png}} 351 | 352 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353 | 354 | The channel connections to the GPIO are shown in the following table: 355 | 356 | \begin{center} 357 | \renewcommand{\arraystretch}{1.3} 358 | \begin{tabu}{|l|l|c||c|l|l|} 359 | \hline 360 | \xesstblhdr 361 | Chan & RPi I/O & \multicolumn{2}{c|}{Pin\#} & RPi I/O & Chan\\\hline 362 | \hline 363 | & +3.3V & 1 & 2 & +5V & \\\hline 364 | CH31 & BCM2\_SDA & 3 & 4 & +5V & \\\hline 365 | CH30 & BCM2\_SCL & 5 & 6 & GND & \\\hline 366 | CH29 & BCM4\_GPCLK0 & 7 & 8 & BCM14\_TXD & CH14 \\\hline 367 | & GND & 9 & 10 & BCM15\_RXD & CH13 \\\hline 368 | CH28 & BCM17 & 11 & 12 & BCM18\_PCM\_C & CH12 \\\hline 369 | CH27 & BCM27\_PCM\_D & 13 & 14 & GND & \\\hline 370 | CH26 & BCM22 & 15 & 16 & BCM23 & CH11 \\\hline 371 | & +3.3V & 17 & 18 & BCM24 & CH10 \\\hline 372 | CH25 & BCM10\_MOSI & 19 & 20 & GND & \\\hline 373 | CH24 & BCM9\_MISO & 21 & 22 & BCM25 & CH9 \\\hline 374 | CH23 & BCM11\_SCLK & 23 & 24 & BCM8\_CE0 & CH8 \\\hline 375 | & GND & 25 & 26 & BCM7\_CE1 & CH7 \\\hline 376 | & BCM0\_ID\_SD & 27 & 28 & BCM1\_ID\_SC & \\\hline 377 | CH22 & BCM5 & 29 & 30 & GND & \\\hline 378 | CH5 & BCM6 & 31 & 32 & BCM12 & CH6 \\\hline 379 | CH4 & BCM13 & 33 & 34 & GND & \\\hline 380 | CH2 & BCM19\_MISO & 35 & 36 & BCM16 & CH3 \\\hline 381 | CH0 & BCM26 & 37 & 38 & BCM20\_MOSI & CH1 \\\hline 382 | & GND & 39 & 40 & BCM21\_SCLK & CHCLK \\\hline 383 | \end{tabu} 384 | \label{tab:ChanneltoGPIOConnections} 385 | \end{center} 386 | 387 | You can also use the GPIO port to connect the \product\ to other pieces of 388 | external circuitry. 389 | When doing this, you can place shunts on the GPIO-5V and GPIO-3.3V jumpers to 390 | provide power to the external circuitry if needed. 391 | However, \warning{never place a shunt on the GPIO-3.3V jumper if the external 392 | circuitry is generating its own 3.3V supply voltage!} 393 | The \product\ is able to supply 3.3V to other circuitry, but it cannot accept it. 394 | 395 | 396 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 397 | 398 | \section{HAT EEPROM} 399 | 400 | In accordance with the 401 | \href{https://github.com/raspberrypi/hats}{\rpi\ HAT (Hardware Attached on Top) requirements}, 402 | the \product\ has an EEPROM that stores information about the device and how it 403 | connects to the \rpi. 404 | 405 | \fixedpic{\includegraphics[width=0.5\textwidth]{eeprom.png}} 406 | 407 | During normal operation, the EEPROM contents are read by the \rpi\ so that it can see 408 | what GPIO pins are used by the \xula\ inserted in the \product. 409 | In order to program the EEPROM with that information, you must place a shunt on 410 | the WP jumper to disable the write-protect function. 411 | The \rpi\ can then load the EEPROM through the ID\_SC and ID\_SD pins of the 412 | GPIO header. 413 | (Read more about this process on page~\pageref{sec:GPIOConfig}.) 414 | 415 | The EEPROM can also be loaded by the \xula\ (if programmed appropriately) by placing shunts 416 | on the ID\_SC and ID\_SD jumpers as well as the WP jumper. 417 | 418 | 419 | \chapter{Using Modules} 420 | 421 | The \product\ serves as a means of connecting a \xula\ to various pieces of 422 | electronics, be they \digpmod s, a \rpi, or just some generic circuitry. 423 | The details of how this is done are presented below. 424 | 425 | \section{Using \digpmod s} 426 | 427 | To use the functions of a particular \digpmod, you have to determine which 428 | I/O signals of the module are connected to which pins of the FPGA. 429 | This is complicated by the fact the module could be plugged into any of the 430 | \digpmod\ sockets. 431 | As with many things in life, there's a hard way to figure this out, and an easy way. 432 | 433 | \subsection{The Hard Way} 434 | 435 | You can manually trace the connection of a \digpmod's I/O signals to the 436 | FPGA pins using the following procedure: 437 | 438 | \begin{itemize} 439 | \item Select a \digpmod\ socket to attach the module to. 440 | \item Use the \hyperref[tab:ChanneltoPMODConnections]{table} on page~\pageref{tab:ChanneltoPMODConnections} to determine 441 | which module I/O signal terminates on each channel of the \digpmod\ socket. 442 | \item Find which FPGA pin of the \xula\ connects to each channel using the 443 | \hyperref[tab:ChanneltoFPGAConnections]{table} on page~\pageref{tab:ChanneltoFPGAConnections}. 444 | \item Make a UCF file associating each FPGA pin with each I/O of the module. 445 | \item Include the UCF file in your Xilinx ISE FPGA project. 446 | \end{itemize} 447 | 448 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 449 | 450 | As an example, consider a simple \digpmod\ with four LEDs, each 451 | connected to one of the I/O signals like so: 452 | 453 | \fixedpic{\includegraphics[width=0.5\textwidth]{pmod_example_schematic.png}} 454 | 455 | The PCB wiring associated with this module looks like so: 456 | 457 | \fixedpic{\includegraphics[width=0.5\textwidth]{pmod_example_pcb.png}} 458 | 459 | From this, you can determine the following connections of the LEDs to the pins 460 | of the \digpmod\ socket: 461 | 462 | \begin{lstlisting} 463 | LED1 D0 464 | LED2 D1 465 | LED3 D2 466 | LED4 D3 467 | \end{lstlisting} 468 | 469 | If this module is attached to \digpmod\ socket PM3 on the \product, 470 | then the channel connections are: 471 | 472 | \begin{lstlisting} 473 | LED1 CH23 # PM3 D0 474 | LED2 CH24 # PM3 D1 475 | LED3 CH25 # PM3 D2 476 | LED4 CH26 # PM3 D3 477 | \end{lstlisting} 478 | 479 | Now, assuming a XuLA2 Board is plugged into the \product, the mapping of 480 | the channels to the FPGA pins is: 481 | 482 | \begin{lstlisting} 483 | CH23 H2 # PM3 D0 484 | CH24 F1 # PM3 D1 485 | CH25 F2 # PM3 D2 486 | CH26 E1 # PM3 D3 487 | \end{lstlisting} 488 | 489 | From this, you can store the following pin assignments in a UCF file: 490 | 491 | \begin{lstlisting} 492 | NET LED1 LOC = H2; # LED1 -> PM3-D0 -> CH23 -> H2 493 | NET LED2 LOC = F1; # LED2 -> PM3-D1 -> CH24 -> F1 494 | NET LED3 LOC = F2; # LED3 -> PM3-D2 -> CH25 -> F2 495 | NET LED4 LOC = E1; # LED4 -> PM3-D3 -> CH26 -> E1 496 | \end{lstlisting} 497 | 498 | Then include this UCF file in your ISE project. 499 | 500 | 501 | \subsection{The Easy Way} 502 | 503 | Tracing the paths a module's I/O signals take through a particular \digpmod\ 504 | socket to a channel which then connects to an FPGA pin is a tedious, error-prone process. 505 | The \pgm{xsconnect}\ Python package (\url{https://pypi.python.org/pypi/xsconnect}) 506 | provides two scripts to make the process easier. 507 | 508 | \pgm{xsconn} is the command-line script for generating pin assignments: 509 | 510 | \begin{lstlisting} 511 | usage: xsconn.py [-h] [-v] [-p [PERIPHERALBOARD]] [-m [MOTHERBOARD]] 512 | [-d [DAUGHTERBOARD]] [-n [PORTNAME]] [-l] 513 | 514 | optional arguments: 515 | -h, --help show this help message and exit 516 | -v, --version show program's version number and exit 517 | -p [PERIPHERALBOARD], --peripheralboard [PERIPHERALBOARD] 518 | -m [MOTHERBOARD], --motherboard [MOTHERBOARD] 519 | -d [DAUGHTERBOARD], --daughterboard [DAUGHTERBOARD] 520 | -n [PORTNAME], --portname [PORTNAME] 521 | -l, --list 522 | \end{lstlisting} 523 | 524 | For example, if a StickIt! LEDDigits peripheral board is connected to 525 | the PM3 port of the \product\ which in turn holds a XuLA2 FPGA board, 526 | then the command: 527 | 528 | \begin{lstlisting} 529 | xsconn -p leddigits -m stickit4 -n pm3 -d xula2 530 | \end{lstlisting} 531 | 532 | will generate the output: 533 | 534 | \begin{lstlisting} 535 | ######################################################################## 536 | # StickIt! LED Digits V2 ==[pm3]==> StickIt! V4 ==> XuLA2 537 | net s0 loc = h2; 538 | net s1 loc = f1; 539 | net s2 loc = f2; 540 | net s3 loc = e1; 541 | net s4 loc = e2; 542 | net s5 loc = c1; 543 | net s6 loc = b1; 544 | net s7 loc = b2; 545 | ######################################################################## 546 | \end{lstlisting} 547 | 548 | \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 549 | 550 | The \pgm{gxsconn}\ script does the same thing as \pgm{xsconn}, but with a GUI: 551 | 552 | \fixedpic{\includegraphics[width=0.7\textwidth]{gxsconn.png}} 553 | 554 | The output from \pgm{xsconn}\ and \pgm{gxsconn}\ is formatted for use 555 | as a UCF file in your ISE project. 556 | 557 | 558 | \section{Using the \rpi} 559 | 560 | Just as with the \digpmod s, connecting the \product\ to a \rpi\ requires 561 | you to determine the connections of the I/O signals to the pins of the FPGA. 562 | And, once again, there's a hard way and an easy way to do that. 563 | 564 | \subsection{The Hard Way} 565 | 566 | Manually tracing the connections of the \rpi\ I/O signals to the pins of the FPGA 567 | is done as follows: 568 | 569 | \begin{itemize} 570 | \item Use the \hyperref[tab:ChanneltoGPIOConnections]{table} on page~\pageref{tab:ChanneltoGPIOConnections} to determine 571 | which \rpi\ I/O signal terminates on each channel of the \xula\ socket. 572 | \item Find which FPGA pin of the \xula\ connects to each channel using the 573 | \hyperref[tab:ChanneltoFPGAConnections]{table} on page~\pageref{tab:ChanneltoFPGAConnections}. 574 | \item Make a UCF file associating each FPGA pin with each \rpi\ I/O. 575 | \item Include the UCF file in your Xilinx ISE FPGA project. 576 | \end{itemize} 577 | 578 | \subsection{The Easy Way} 579 | 580 | Use |xsconn| or |gxsconn| just like with the \digpmod s. 581 | Set the \rpi\ as the peripheral board and select GPIO as the port 582 | and you'll get a complete list of the connections to the FPGA. 583 | 584 | \subsection{Configuring the \rpi\ GPIO \label{sec:GPIOConfig}} 585 | 586 | Most HATs perform a specific function that requires communicating with the \rpi\ 587 | through a fixed set of GPIO pins. 588 | The \rpi\ reads the list of pins from the EEPROM on the HAT and configures 589 | its I/O pins appropriately. 590 | 591 | But the \xula\ and \product\ do not perform one fixed function: they can be 592 | programmed for many types of applications. 593 | Therefore, the list of GPIO pins used by a particular application has to be written 594 | into the EEPROM on the \product. 595 | This is done as follows: 596 | 597 | \begin{enumerate} 598 | \item Create your FPGA application for the \xula\ along with the 599 | required pin assignments for communicating through the GPIO connector. 600 | \item Attach the \product\ to the GPIO connector and place a shunt on 601 | the WP jumper to enable writing to the EEPROM. 602 | (A \xula\ can be inserted into the J1 socket at this point, but it 603 | should not have a bitstream loaded into its flash memory that might 604 | cause the FPGA to drive the pins of the GPIO connector.) 605 | \item Download the code from 606 | \url{https://github.com/raspberrypi/hats/tree/master/eepromutils} 607 | onto your \rpi. 608 | \item Edit the \filename{eeprom\_settings.txt}\ file to reflect how the GPIO 609 | pins are used by your application. 610 | \item Compile the \filename{eepmake.c}\ program and then run it to create 611 | a binary data file that stores your GPIO pin settings: 612 | \begin{lstlisting} 613 | eepmake eeprom_settings.txt eeprom_settings.bin 614 | \end{lstlisting} 615 | \item Execute the \filename{eepflash.sh}\ shell program to write the 616 | binary data file to the EEPROM: 617 | \begin{lstlisting} 618 | eepflash -w -f=eeprom_settings.bin -t=-24c32 619 | \end{lstlisting} 620 | \item Remove the shunt from the WP jumper and reboot the \rpi. 621 | \end{enumerate} 622 | 623 | After the above procedure is completed, you can load the \xula\ with the 624 | bitstream for the application. 625 | You can change the application as long as you don't 626 | change how it drives the GPIO pins. 627 | (For example, don't take a GPIO pin that was previously driving the 628 | FPGA and reverse it so that the FPGA now drives the \rpi.) 629 | If you do change how the GPIO pins are used, you will need to update 630 | the \product\ EEPROM again to reflect those changes before changing the 631 | FPGA bitstream. 632 | 633 | 634 | \section{Using Generic Circuitry} 635 | 636 | Instead of an \rpi, you can connect generic digital circuitry to the GPIO port. 637 | \warning{The circuitry must interface using 3.3V logic levels. The \xula\ 638 | will not tolerate 5V logic levels.} 639 | 640 | \subsection{The Hard Way} 641 | 642 | Use the following procedure to determine the connections of the I/O signals 643 | from your circuitry to the pins of the FPGA: 644 | 645 | \begin{itemize} 646 | \item Attach the I/O signals from the generic circuitry to pins 647 | 1--40 of the GPIO connector. There are 26 usable I/O pins; the rest 648 | are mostly power and ground pins that you can use to provide 649 | power to the external circuitry if desired. 650 | \item Use the \hyperref[tab:ChanneltoGPIOConnections]{table} on 651 | page~\pageref{tab:ChanneltoGPIOConnections} to determine 652 | which GPIO pin connects to each channel of the \xula\ socket. 653 | \item Find which FPGA pin of the \xula\ connects to each channel using the 654 | \hyperref[tab:ChanneltoFPGAConnections]{table} on 655 | page~\pageref{tab:ChanneltoFPGAConnections}. 656 | \item Make a UCF file associating each FPGA pin with an I/O signal. 657 | \item Include the UCF file in your Xilinx ISE FPGA project. 658 | \end{itemize} 659 | 660 | \subsection{The Easy Way} 661 | 662 | For generic circuitry, |xsconn| or |gxsconn| can still make the pin-tracing 663 | process a little easier. 664 | Just set the peripheral board to be Generic and select GPIO as the port. 665 | Then you'll get a complete list of connections between GPIO pins 1--40 and the FPGA. 666 | You will have to manually substitute your I/O signal names for the pin numbers in 667 | the list to create the final UCF file for your ISE project. 668 | 669 | 670 | 671 | \appendix 672 | 673 | 674 | \chapter{I/O Locations} 675 | 676 | The connections of the \xula\ I/O channels to the \digpmod\ and \rpi\ 677 | sockets of the \product\ are shown below. 678 | 679 | \fixedpic{\includegraphics[width=0.7\textwidth]{channel_connects.png}} 680 | 681 | 682 | 683 | \chapter{\ Schematic} 684 | 685 | \pagebreak 686 | \makebox[\textwidth][r]{\hss\includegraphics[width=\textheight, angle=90]{StickIt-Hat_sch.png}} 687 | %\includegraphics[width=\textheight, angle=90]{StickIt-Hat_sch.png} 688 | 689 | \end{document} 690 | -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_3D.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_components.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_cover.jpg -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_gerber_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_gerber_bottom.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_gerber_gnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_gerber_gnd.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_gerber_pwr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_gerber_pwr.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_gerber_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_gerber_top.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_layout.png -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_pcb.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_pcb.JPG -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_pcb_back.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_pcb_back.JPG -------------------------------------------------------------------------------- /docs/Manual/pics/CAT_schematic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/Manual/pics/CAT_schematic.pdf -------------------------------------------------------------------------------- /docs/Manual/xess.sty: -------------------------------------------------------------------------------- 1 | % Required packages. 2 | \usepackage[ascii]{inputenc} 3 | \usepackage[T1]{fontenc} 4 | \usepackage[english]{babel} 5 | \usepackage{amsmath} 6 | \usepackage{amssymb,amsfonts,textcomp} 7 | \usepackage{tabu} % For tables with colored headers. 8 | \usepackage{array} % For tables. 9 | \usepackage{hhline} % For table cell borders. 10 | \usepackage{graphicx} 11 | \usepackage{calc} % For calculating dimensions 12 | \usepackage[dvipsnames,svgnames,x11names,table]{xcolor} % For coloring page objects. 13 | \usepackage{geometry} % For sizing page areas. 14 | \usepackage{fontspec} % For loading fonts. 15 | \usepackage{anyfontsize} % For scaling fonts. 16 | \usepackage{textcomp} % For copyright, trademark symbols. 17 | \usepackage{wrapfig} % For wrapping text around figures. 18 | \usepackage{tikz} % For overlaying graphics on pages. 19 | \usepackage{tikzpagenodes} % TikZ anchor points for a page. 20 | \usepackage{etoolbox} % For conditionals. 21 | \usepackage{listings} % For program/code listings. 22 | \usepackage{hyperref} % For hyperlinks. 23 | \usepackage{bookmark} % For PDF bookmarks. Must come after hyperref package. 24 | 25 | 26 | % Commonly-used substitutions. 27 | \newcommand{\warning}[1]{\textbf{#1}} 28 | \newcommand{\emphasis}[1]{\textit{#1}} 29 | \newcommand{\regtmark}[1]{{#1}\textsuperscript{\textregistered}} 30 | \newcommand{\xess}{XESS} 31 | \newcommand{\xesslogo}{xess-logo.png} % Just "XESS". 32 | \newcommand{\xesscorplogo}{xesscorp-logo.png} % "XESS Corporation". 33 | \newcommand{\helpemail}{help@xess.com} 34 | \newcommand{\helppage}{www.xess.com/interact/contact/} 35 | \newcommand{\by}{$\times$} 36 | % Place text between || to make inline listing. 37 | \lstMakeShortInline[columns=fixed]| 38 | \newcommand{\pgm}[1]{\lstinline{#1}} % inline listing mode for programs, keywords, etc. 39 | \newcommand{\filename}[1]{\lstinline{#1}} 40 | 41 | \newcommand{\digpmod}{PMOD} 42 | \newcommand{\digpmodtm}{\regtmark{\digpmod}} 43 | \newcommand{\rpi}{Raspberry Pi} 44 | 45 | \defaultfontfeatures{Ligatures=TeX} % Enable dash conversions: -- is \textendash 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | % Itemized list bullets. 49 | \renewcommand{\labelitemi}{\fontsize{8pt}{13pt}$\blacksquare$} 50 | \renewcommand{\labelitemii}{\fontsize{10pt}{13pt}$\bullet$} 51 | \renewcommand{\labelitemiii}{\fontsize{9pt}{13pt}$\blacklozenge$} 52 | \renewcommand{\labelitemiv}{\fontsize{9pt}{13pt}$\blacktriangle$} 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 | 55 | 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 | % Code listing style. 58 | \lstset{ 59 | tabsize=4, 60 | xleftmargin=0.0\textwidth, 61 | basicstyle=\small\ttfamily, 62 | commentstyle=\itshape\color{purple!40!black}, 63 | } 64 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 65 | 66 | 67 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 68 | % Image/picture stuff. 69 | \graphicspath{{./}{./figures/}{./images/}{./pics/}{C:/xesscorp/LOGOS/}} 70 | \newcommand{\fixedpic}[1]{\begin{center} #1 \end{center}} 71 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72 | 73 | 74 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 | % Main fonts for documents. 76 | \setmainfont{Arial} 77 | \newfontfamily{\footerfont}{Verdana} 78 | \newcommand{\usefooterfont}[1]{\fontsize{9pt}{11pt}\footerfont #1} 79 | \newfontfamily{\headerfont}{Verdana} 80 | \newcommand{\useheaderfont}[1]{\fontsize{9pt}{11pt}\headerfont #1} 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 | 83 | 84 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85 | % Page layout. 86 | 87 | % Page margins. 88 | \settrims{0in}{0in} % Page size is the same as the stock size. 89 | \setlrmarginsandblock{1.75in}{0.75in}{*} % Sets the textbody width. 90 | \setulmarginsandblock{1.1in}{1.03in}{*} % Sets the textbody height. 91 | \setheadfoot{0.60in}{0.63in} % Set the header height and the dist to the footer bottom. 92 | \setheaderspaces{*}{0.50in}{*} % Set separation between textbody top and header bottom. 93 | \setmarginnotes{0.1in}{0.9in}{0.1in} % Sep from textbody, note width, min vert separation. 94 | 95 | % Page headers. 96 | \def\headfootrulethickness{1.0pt} 97 | \renewcommand{\chaptermark}[1]{\markboth{#1}{}} 98 | \makeevenhead{headings} 99 | {\useheaderfont\bfseries\leftmark} 100 | {} 101 | {\includegraphics[width=1.5in]{\xesslogo}} 102 | \makeoddhead{headings} 103 | {\useheaderfont\bfseries\leftmark} 104 | {} 105 | {\includegraphics[width=1.5in]{\xesslogo}} 106 | 107 | % Page footers. 108 | \makeevenfoot{headings} 109 | {\usefooterfont\docversion, \today} 110 | {\usefooterfont\@title} 111 | {\usefooterfont\thepage} 112 | \makeoddfoot{headings} 113 | {\usefooterfont\docversion, \today} 114 | {\usefooterfont\@title} 115 | {\usefooterfont\thepage} 116 | \makefootrule{headings}{\textwidth}{\headfootrulethickness}{1pt} 117 | 118 | % Finalize the page layout. 119 | \setlength\parindent{0pt} 120 | %\setlength\parskip{1em} 121 | \setlength\parskip{\baselineskip} 122 | \raggedbottom 123 | \checkandfixthelayout 124 | 125 | % Make the header/footer wider than the textbody width. 126 | \def\hdrwd{\dimexpr\textwidth+1.0in} 127 | \makerunningwidth{headings}{\hdrwd} 128 | \makeheadposition{headings}{flushleft}{flushright}{flushleft}{flushright} 129 | \makeheadrule{headings}{\hdrwd}{\headfootrulethickness} 130 | \makefootrule{headings}{\hdrwd}{\headfootrulethickness}{1pt} 131 | 132 | % Page style for frontmatter. 133 | \copypagestyle{frontmatterpagestyle}{headings} 134 | \makeevenhead{frontmatterpagestyle} 135 | {} 136 | {} 137 | {\includegraphics[width=1.5in]{\xesslogo}} 138 | \makeoddhead{frontmatterpagestyle} 139 | {} 140 | {} 141 | {\includegraphics[width=1.5in]{\xesslogo}} 142 | \makeevenfoot{frontmatterpagestyle} 143 | {\usefooterfont\docversion, \today} 144 | {} 145 | {\usefooterfont\doctitle} 146 | \makeoddfoot{frontmatterpagestyle} 147 | {\usefooterfont\docversion, \today} 148 | {} 149 | {\usefooterfont\doctitle} 150 | 151 | % Page style for first page of chapter. 152 | \copypagestyle{startchapterpagestyle}{headings} 153 | \makeheadrule{startchapterpagestyle}{0pt}{0pt} % Remove header on starting page of chapter. 154 | \makeevenhead{startchapterpagestyle} 155 | {} 156 | {} 157 | {\includegraphics[width=1.5in]{\xesslogo}} 158 | \makeoddhead{startchapterpagestyle} 159 | {} 160 | {} 161 | {\includegraphics[width=1.5in]{\xesslogo}} 162 | \copypagestyle{chapter}{startchapterpagestyle} 163 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 164 | 165 | 166 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 167 | % Define a new XESS variable: 168 | % \defxsvar{myvar} 169 | % Now you can set it like this: \myvar{whatever} 170 | % and use it like this: Here's some text with \myvar\ in it. 171 | % This doesn't currently work! 172 | %\newcommand{\defxsvar}[1]{ 173 | % \newcommand{#1}[1][] 174 | % { 175 | % %\expandafter\def\csname @xsvar\the\xsvarnum\endcsname{##1} 176 | % \ifstrempty{##1}{% 177 | % \csname #1v\endcsname 178 | % }{% 179 | % \expandafter\def\csname #1v\endcsname\##1 180 | % } 181 | % } 182 | %} 183 | 184 | % Define identifiers for documentation. 185 | \newcommand{\doctitle}[1][]{\ifstrempty{#1}{\@doctitle}{\def\@doctitle{#1}}} 186 | \newcommand{\docsubtitle}[1][]{\ifstrempty{#1}{\@docsubtitle}{\def\@docsubtitle{#1}}} 187 | \newcommand{\docnum}[1][]{\ifstrempty{#1}{\@docnum}{\def\@docnum{#1}}} 188 | \newcommand{\docversion}[1][]{\ifstrempty{#1}{\@docversion}{\def\@docversion{#1}}} 189 | % Define identifiers for product manual. 190 | \newcommand{\manualtitle}[1]{\title{{#1} Manual}\doctitle[\@title]} 191 | \newcommand{\manualsubtitle}[1]{\docsubtitle[How to install and use\\your new {#1}]} 192 | \newcommand{\manualnum}[1]{\docnum[MAN{#1}]} 193 | \newcommand{\manualversion}[1]{\docversion[V{#1}]} 194 | 195 | % Define a product name. 196 | \newcommand{\product}[1][]{% 197 | \ifstrempty{#1}{\@product}{ 198 | \def\@product{#1} 199 | \manualtitle{\product} 200 | \manualsubtitle{\product} 201 | }% 202 | } 203 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 204 | 205 | 206 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 207 | % Table formating commands. 208 | \newcommand{\xesstblhdr}{\rowfont{\color{white}\bfseries}\rowcolor{black}} 209 | \newcommand{\xesstblsubhdr}{\rowfont{\color{white}\bfseries}\rowcolor{gray}} 210 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 211 | 212 | 213 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 214 | % Make chapter heading with chapter number in solid-color box. 215 | \makechapterstyle{XessChpStyle} 216 | { 217 | %\renewcommand{\chapnamefont}{\large\scshape} 218 | %\renewcommand{\chapnumfont}{\Huge\bfseries} 219 | %\renewcommand{\chaptitlefont}{\raggedright\Huge\bfseries} 220 | \setlength{\beforechapskip}{1.35in} 221 | \setlength{\midchapskip}{0pt} 222 | \setlength{\afterchapskip}{\baselineskip} 223 | \renewcommand{\printchaptername}{} 224 | \renewcommand{\chapternamenum}{} 225 | \renewcommand{\printchapternum}{} 226 | \renewcommand{\printchapternonum}{} 227 | \renewcommand{\afterchapternum}{} 228 | \renewcommand{\printchaptertitle}[1] 229 | { 230 | \thispagestyle{startchapterpagestyle} % Override normal page style on chapter start. 231 | 232 | \def\chapboxht{0.7in} % Height of box enclosing chapter number and title. 233 | \def\stickout{1.0in} % How much the chapter box pokes into left margin. 234 | \def\chapboxwd{\textwidth+\stickout} % Width of chapter box. 235 | \def\chapnumwd{1.0in} % Width of box containing chapter number. 236 | \def\chaptitlepad{0.2in} % Space between title text and left/right ends of its box. 237 | \def\chapfntsz{36pt} % Chapter font size. 238 | \def\chaplinespc{1.2\chapfntsz} % Chapter line spacing. 239 | \setlength{\arrayrulewidth}{.1em} % Width of lines making box. 240 | \setlength{\tabcolsep}{0pt} 241 | \fontsize{\chapfntsz}{\chaplinespc}\bfseries\itshape\raggedright 242 | % Make a box of width equal to the text body in which a table with a width of 243 | % the text body + stickout will be placed. By right-justifying the table, its 244 | % left side will poke into the left margin. 245 | \makebox[\textwidth][r] 246 | {% 247 | \hss% Infinitely stretchable glue on the left so it can stretch into left margin. 248 | % The table has three columns: one for the chapter number, the next for the 249 | % chapter title, and the last containing a rule that pads the title and sets 250 | % the height of the chapter box. 251 | \begin{tabular}{m{\chapnumwd} 252 | m{\chapboxwd-\chapnumwd-\chaptitlepad-6\tabcolsep} 253 | m{\chaptitlepad}|} 254 | \hline % Top side of chapter box. 255 | % Chapter number cell of table. 256 | \cellcolor{black}\color{white}% Reverse coloring for chapter number. 257 | \hspace*{\fill}\cellcolor{black}\color{white}\thechapter\hspace*{\fill} & 258 | % Chapter title cell of table. 259 | \makebox[\chaptitlepad]{}% Left-side padding of chapter title. 260 | \color{black}{##1} & 261 | % Right-side padding and chapter box height cell of table. 262 | \rule{0pt}{\chapboxht} % Pad the right side of title and set box height. 263 | \\ 264 | \hline % Bottom side of chapter box 265 | \end{tabular}% 266 | }% 267 | } 268 | } 269 | \chapterstyle{XessChpStyle} 270 | 271 | \setsecnumdepth{chapter} % Don't number any sections below the chapters. 272 | \setsecnumformat{\rule{0pt}{0pt}} % This keeps \quad from being injected before section title. 273 | 274 | % Section formating. 275 | \setsecindent{0.0in} % Keeps section title from being indented. Actual indent is applied below. 276 | \setbeforesecskip{2\baselineskip} 277 | \setaftersecskip{\baselineskip} 278 | \newcommand{\xssecstyle}[1] 279 | {% 280 | \def\secboxht{0.3in} % Height of box enclosing section title. 281 | \def\stickout{1.0in} % How much the section box pokes into left margin. 282 | \def\secboxwd{\textwidth+\stickout} % Width of section box. 283 | \def\sectitlepad{0.13in} % Space between title text and left/right ends of its box. 284 | \def\secfntsz{15pt} % Section font size. 285 | \def\seclinespc{1.2\secfntsz} % Section title line spacing. 286 | \setlength{\tabcolsep}{0pt} 287 | \fontsize{\secfntsz}{\seclinespc}\bfseries\raggedright 288 | \makebox[\textwidth][r] 289 | {% 290 | \hss% Infinitely stretchable glue on the left so it can stretch into left margin. 291 | \begin{tabular}{m{\secboxwd-\sectitlepad-4\tabcolsep} 292 | m{\sectitlepad}} 293 | %\cellcolor{black}\color{red}{#1}\rule[-12pt]{0pt}{36pt}\\% 294 | %\rule{0pt}{12pt}\\% 295 | % Section title cell of table. 296 | \cellcolor{black}% 297 | \makebox[\sectitlepad]{}% Left-side padding of section title. 298 | \color{white}{#1} & 299 | % Right-side padding and chapter box height cell of table. 300 | \cellcolor{black}% 301 | \rule{0pt}{\secboxht} % Pad the right side of title and set box height. 302 | \\ 303 | \end{tabular}% 304 | }% 305 | } 306 | \setsecheadstyle{\xssecstyle} 307 | 308 | % Subsection formating. 309 | \setsubsecindent{-0.5in} % Subsection title sticks out into left margin. 310 | \setbeforesubsecskip{\baselineskip} 311 | \setaftersubsecskip{1pt} 312 | \newfontfamily{\subsecfont}{Arial Narrow} 313 | \def\subsecfntsz{14pt} 314 | \def\subseclinespc{1.2\subsecfntsz} % Section title line spacing. 315 | \setsubsecheadstyle{\fontsize{\subsecfntsz}{\subseclinespc}\subsecfont\bfseries\raggedright} 316 | 317 | % Subsubsection formating. 318 | \setsubsubsecindent{0.0in} 319 | \setbeforesubsubsecskip{\baselineskip} 320 | \setaftersubsubsecskip{1pt} 321 | \newfontfamily{\subsubsecfont}{Arial Narrow} 322 | \def\subsubsecfntsz{12pt} 323 | \def\subsubseclinespc{1.2\subsubsecfntsz} % Section title line spacing. 324 | \setsubsubsecheadstyle{\fontsize{\subsubsecfntsz}{\subsubseclinespc}\subsubsecfont\bfseries\itshape\raggedright} 325 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 326 | 327 | 328 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 329 | % Environment for the XESS document title page. 330 | \newenvironment{xesstitlepage} 331 | { 332 | \newcommand{\pushright}{\hspace*{\fill}} % Pushes other stuff to the right. 333 | 334 | % Thick rule below XESS logo going across top of title page. 335 | \renewcommand{\toprule}{\noindent\makebox[\linewidth]{\rule{\textwidth}{5pt}}} 336 | 337 | % Title and subtitle fonts. 338 | \newfontfamily{\titlefont}{Arial} 339 | \newcommand{\usetitlefont}[1]{\fontsize{36pt}{43pt}\bfseries\titlefont ##1} 340 | \newfontfamily{\subtitlefont}{Gentium Book Basic} 341 | \newcommand{\usesubtitlefont}[1]{\fontsize{20pt}{24pt}\itshape\subtitlefont ##1} 342 | 343 | % Create the title. 344 | \renewcommand{\maketitle} 345 | { 346 | \pushright\parbox[t]{\textwidth}% 347 | { 348 | \begin{flushright}% 349 | \usetitlefont{\doctitle}% 350 | \end{flushright}% 351 | } 352 | } 353 | 354 | % Create the subtitle. 355 | \newcommand{\makesubtitle} 356 | { 357 | \pushright\parbox[t]{\textwidth}% 358 | { 359 | \begin{flushright}% 360 | \usesubtitlefont{\docsubtitle}% 361 | \end{flushright}% 362 | } 363 | } 364 | 365 | % Define the title page layout. 366 | \newgeometry 367 | { 368 | includeall, 369 | headheight=0in, headsep=0in, 370 | marginparsep=0in, marginparwidth=0in, 371 | margin=0.75in, top=0.3in, bottom=0.5in 372 | } 373 | 374 | % Define and activate the title page style, particularly the footer. 375 | \makepagestyle{titlepage} % Start with empty page style. 376 | \makefootrule{titlepage}{\textwidth}{\headfootrulethickness}{0pt} 377 | \makeoddfoot{titlepage} 378 | {} 379 | {} 380 | {\usefooterfont\docnum, \docversion, \today} 381 | \thispagestyle{titlepage} 382 | 383 | % Paragraphs on title page have no indentation. 384 | \setlength\parindent{0pt} 385 | \noindent\ignorespaces 386 | } 387 | { 388 | \restoregeometry % Restore the page layout in effect before the title page. 389 | \clearpage % Start new page after title page. 390 | \setcounter{page}{1} % Reset page numbering. 391 | \ignorespacesafterend 392 | } 393 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 394 | 395 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 396 | % Command for instantiating an XESS manual title page. 397 | % Arg #1: product image file name. 398 | % Arg #2: image scaling factor with relation to \textwidth. 399 | \newcommand{\makexessmanualtitlepage}[2] 400 | { 401 | \begin{xesstitlepage} 402 | 403 | \includegraphics[width=2in]{\xesscorplogo}\\ % XESS logo. 404 | \toprule\\ % Rule across page. 405 | \vspace{0.0in}\\ 406 | \maketitle\\ % Title. 407 | \vspace{0.0in}\\ 408 | \makesubtitle\\ % Subtitle. 409 | \vspace*{\fill}\\ 410 | 411 | % Title page product picture in lower-left corner. 412 | \begin{tikzpicture}[remember picture, overlay] 413 | \node[anchor=south west] at (current page text area.south west) { 414 | \includegraphics[width=#2\textwidth]{#1} 415 | }; 416 | \end{tikzpicture} 417 | 418 | \end{xesstitlepage} 419 | } 420 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 421 | 422 | 423 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 424 | % Front matter page style. 425 | \newenvironment{xessfrontmatter} 426 | { 427 | \thispagestyle{frontmatterpagestyle} 428 | \noindent\ignorespaces% 429 | } 430 | { 431 | \clearpage 432 | \setcounter{page}{1} 433 | \ignorespacesafterend 434 | } 435 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 436 | 437 | 438 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 439 | % Legal: disclaimers, copyright, etc. 440 | 441 | % Arg #1: year of copyright. 442 | \newcommand{\xesslegaltext}[1]{% 443 | XESS is disclosing this Document and Intellectual Property 444 | (hereinafter “the Design”) to you for use in the development 445 | of designs to operate on, or interface with XESS hardware devices. 446 | XESS expressly disclaims any liability arising out of the application 447 | or use of the Design. XESS reserves the right to make changes, 448 | at any time, to the Design as deemed desirable in the sole discretion 449 | of XESS. XESS assumes no obligation to correct any errors contained 450 | herein or to advise you of any correction if such be made. XESS will 451 | not assume any liability for the accuracy or correctness of any 452 | engineering or technical support or assistance provided to you 453 | in connection with the Design. 454 | 455 | THE DESIGN IS PROVIDED “AS IS” WITH ALL FAULTS, AND THE ENTIRE RISK 456 | AS TO ITS FUNCTION AND IMPLEMENTATION IS WITH YOU. YOU ACKNOWLEDGE 457 | AND AGREE THAT YOU HAVE NOT RELIED ON ANY ORAL OR WRITTEN INFORMATION 458 | OR ADVICE, WHETHER GIVEN BY XESS, OR ITS AGENTS OR EMPLOYEES. 459 | XESS MAKES NO OTHER WARRANTIES, WHETHER EXPRESS, IMPLIED, OR STATUTORY, 460 | REGARDING THE DESIGN, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, 461 | FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NONINFRINGEMENT OF 462 | THIRD-PARTY RIGHTS. 463 | 464 | IN NO EVENT WILL XESS BE LIABLE FOR ANY CONSEQUENTIAL, INDIRECT, 465 | EXEMPLARY, SPECIAL, OR INCIDENTAL DAMAGES, INCLUDING ANY LOST DATA 466 | AND LOST PROFITS, ARISING FROM OR RELATING TO YOUR USE OF THE DESIGN, 467 | EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 468 | THE TOTAL CUMULATIVE LIABILITY OF XESS IN CONNECTION WITH YOUR USE 469 | OF THE DESIGN, WHETHER IN CONTRACT OR TORT OR OTHERWISE, WILL IN NO 470 | EVENT EXCEED THE AMOUNT OF FEES PAID BY YOU TO XESS HEREUNDER FOR 471 | USE OF THE DESIGN. YOU ACKNOWLEDGE THAT THE FEES, IF ANY, REFLECT 472 | THE ALLOCATION OF RISK SET FORTH IN THIS AGREEMENT AND THAT XESS 473 | WOULD NOT MAKE AVAILABLE THE DESIGN TO YOU WITHOUT THESE LIMITATIONS 474 | OF LIABILITY. 475 | 476 | The Design is not designed or intended for use in the development 477 | of on-line control equipment in hazardous environments requiring 478 | fail-safe controls, such as in the operation of nuclear facilities, 479 | aircraft navigation or communications systems, air traffic control, 480 | life support, or weapons systems (“High-Risk Applications”). 481 | XESS specifically disclaims any express or implied warranties of 482 | fitness for such High-Risk Applications. You represent that use 483 | of the Design in such High-Risk Applications is fully at your risk. 484 | 485 | \textcopyright #1 XESS, Inc. XESS, the XESS logo, and other 486 | designated brands included herein are trademarks of XESS Corporation. 487 | \digpmodtm\ is a trademark of Digilent Inc. 488 | All other trademarks are the property of their respective owners. 489 | 490 | \parbox[t]{1.3in}{ 491 | \hrule height 0pt width 0pt 492 | \includegraphics[width=1.3in]{CC-BY-SA_icon.png}} 493 | \hfill 494 | \parbox[t]{1.0\textwidth - 1.5in}{ 495 | \hrule height 0pt width 0pt 496 | This document is licensed under the Attribution-ShareAlike 3.0 497 | Unported license, available at http://creativecommons.org/licenses/by-sa/3.0/.} 498 | } 499 | 500 | \newenvironment{xesslegal} 501 | { 502 | \begin{xessfrontmatter} 503 | \newfontfamily{\legalfont}{Arial Narrow}% 504 | \fontsize{10pt}{12pt}\legalfont 505 | } 506 | { 507 | \end{xessfrontmatter} 508 | } 509 | 510 | % Arg #1: year of copyright. 511 | \newcommand{\makexesslegal}[1]{\begin{xesslegal}\xesslegaltext{#1}\end{xesslegal}} 512 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 513 | 514 | 515 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 516 | % Revision table. 517 | 518 | % Environment for a document revision table 519 | \newenvironment{xessrevisiontbl} 520 | { 521 | \begin{xessfrontmatter} 522 | \newfontfamily{\revtblfont}{Arial}% 523 | \fontsize{12pt}{14pt}\revtblfont% 524 | {\large\bfseries Document Revision History} 525 | 526 | \begin{flushleft} 527 | \renewcommand\arraystretch{1.3} 528 | \setlength{\tabcolsep}{0.0in} 529 | \begin{tabu}{>{\centering}m{0.15\textwidth}>{\centering}m{0.15\textwidth}m{0.70\textwidth}} 530 | \hline 531 | \xesstblhdr 532 | Date & Version & Revision \\ 533 | \hline 534 | } 535 | { 536 | \hline 537 | \end{tabu} 538 | \end{flushleft} 539 | \end{xessfrontmatter} 540 | } 541 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 542 | 543 | 544 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 545 | % Table of contents. 546 | 547 | \newenvironment{xesstoc} 548 | { 549 | \begin{xessfrontmatter} 550 | \setcounter{tocdepth}{10} 551 | \renewcommand\contentsname{Contents} 552 | } 553 | { 554 | \end{xessfrontmatter} 555 | } 556 | 557 | \newcommand{\makexesstoc}% 558 | {% 559 | \begin{xesstoc} 560 | \tableofcontents* 561 | \end{xesstoc} 562 | } 563 | 564 | 565 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 566 | % Hyperlink setup. 567 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 568 | \hypersetup 569 | { 570 | colorlinks=true, 571 | linkcolor=blue, 572 | citecolor=blue, 573 | filecolor=blue, 574 | urlcolor=blue 575 | } 576 | \urlstyle{same} % URLs printed in same font as the rest of document. 577 | -------------------------------------------------------------------------------- /docs/readthedocs/authors.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Development Lead 4 | 5 | * Dave Vandenbout () 6 | 7 | ## Contributors 8 | 9 | None yet. Why not be the first? 10 | -------------------------------------------------------------------------------- /docs/readthedocs/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are welcome, and they are greatly appreciated! Every 4 | little bit helps, and credit will always be given. 5 | 6 | You can contribute in many ways: 7 | 8 | ## Types of Contributions 9 | 10 | ### Report Bugs 11 | 12 | Report bugs at https://github.com/xesscorp/CAT/issues. 13 | 14 | If you are reporting a bug, please include: 15 | 16 | * Your operating system name and version. 17 | * Any details about your local setup that might be helpful in troubleshooting. 18 | * Detailed steps to reproduce the bug. 19 | 20 | ### Fix Bugs 21 | 22 | Look through the GitHub issues for bugs. Anything tagged with "bug" 23 | is open to whoever wants to implement it. 24 | 25 | ### Implement Features 26 | 27 | Look through the GitHub issues for features. Anything tagged with "feature" 28 | is open to whoever wants to implement it. 29 | 30 | ### Write Documentation 31 | 32 | CAT could always use more documentation, whether as part of the 33 | official CAT docs or even on the web in blog posts, 34 | articles, and such. 35 | 36 | ### Submit Feedback 37 | 38 | The best way to send feedback is to file an issue at https://github.com/xesscorp/CAT/issues. 39 | 40 | If you are proposing a feature: 41 | 42 | * Explain in detail how it would work. 43 | * Keep the scope as narrow as possible, to make it easier to implement. 44 | 45 | ### Get Started! 46 | 47 | Ready to contribute? Here's how to set up `CAT` for local development. 48 | 49 | 1. Fork the `CAT` repo on GitHub. 50 | 2. Clone your fork locally: 51 | 52 | $ git clone git@github.com:your_name_here/CAT.git 53 | 54 | 3. Create a branch for local development: 55 | 56 | $ git checkout -b name-of-your-bugfix-or-feature 57 | 58 | Now you can make your changes locally. 59 | 60 | 4. Commit your changes and push your branch to GitHub: 61 | 62 | $ git add . 63 | $ git commit -m "Your detailed description of your changes." 64 | $ git push origin name-of-your-bugfix-or-feature 65 | 66 | 5. Submit a pull request through the GitHub website. 67 | 68 | -------------------------------------------------------------------------------- /docs/readthedocs/history.md: -------------------------------------------------------------------------------- 1 | # History 2 | 3 | ## 0.1 (2015-10-07) 4 | 5 | * First release. 6 | -------------------------------------------------------------------------------- /docs/readthedocs/index.md: -------------------------------------------------------------------------------- 1 | # CAT 2 | 3 | 4 | # Description 5 | 6 | The CAT Board is a Raspberry Pi HAT with a Lattice iCE40HX FPGA. 7 | 8 | * License: [CC BY 4.0](http://creativecommons.org/licenses/by/4.0/legalcode) 9 | * Documentation: [CAT-Board.readthedocs.org](https://CAT-Board.readthedocs.org) 10 | 11 | 12 | # Features 13 | 14 | * Lattice iCE40-HX8K FPGA in 256-pin BGA. 15 | * 32 MByte SDRAM (16M x 16). 16 | * Serial configuration flash (at least 2 Mbit). 17 | * Three Grove connectors. 18 | * Two PMOD connectors. 19 | * One 20x2 header with 3.3V, ground and 18 FPGA I/Os. 20 | * Two SATA headers (for differential signals; don't know if they would work with SATA HDDs.) 21 | * DIP switch with four SPST switches. 22 | * Two momentary pushbuttons. 23 | * Four LEDs. 24 | * 100 MHz oscillator. 25 | * 5.0 V jack for external power supply. 26 | * 3.3 V and 1.2 V regulators. 27 | * Adjustable voltage on one bank of FPGA I/O pins. 28 | * 32 KByte HAT EEPROM. 29 | * 40-pin RPi GPIO header. 30 | 31 | [ CAT Schematic ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_schematic.pdf) 32 | 33 | [![Click to watch YouTube Video](http://img.youtube.com/vi/EHtcOrdl9Xw/0.jpg)](http://www.youtube.com/watch?v=EHtcOrdl9Xw "CAT Board: First Look") 34 | 35 | ![ CAT Picture ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_cover.jpg) 36 | ![ CAT PCB ](https://raw.githubusercontent.com/xesscorp/CAT-Board/master/docs/Manual/pics/CAT_pcb.JPG) 37 | -------------------------------------------------------------------------------- /docs/readthedocs/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Just clone this project from Github: 4 | 5 | $ git clone https://github.com/xesscorp/CAT.git 6 | -------------------------------------------------------------------------------- /docs/readthedocs/licenses.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | All software source files, all hardware design files (e.g., schematics and PCB layouts), and all 4 | documentation is covered by the 5 | [CC BY 4.0 license]( http://creativecommons.org/licenses/by/4.0/legalcode ). 6 | 7 | ![]( https://i.creativecommons.org/l/by/4.0/88x31.png ) 8 | -------------------------------------------------------------------------------- /docs/readthedocs/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | To use CAT, just clone it and modify it to your heart's content: 4 | 5 | $ git clone https://github.com/xesscorp/CAT.git 6 | -------------------------------------------------------------------------------- /docs/readthedocs/xess.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/readthedocs/xess.ico -------------------------------------------------------------------------------- /docs/readthedocs/xess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/docs/readthedocs/xess.png -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: 'CAT-Board' 2 | repo_name: 'CAT-Board' 3 | site_description: 'The CAT Board is a Raspberry Pi HAT with a Lattice iCE40HX FPGA.' 4 | site_author: 'XESS Corp.' 5 | site_favicon: 'readthedocs/xess.ico' 6 | copyright: '(c) 2015 by XESS Corp.' 7 | 8 | pages: 9 | - 'Introduction': 'index.md' 10 | - 'Installation': 'installation.md' 11 | - 'Usage': 'usage.md' 12 | - 'License': 'licenses.md' 13 | - 'History': 'history.md' 14 | - 'Authors': 'authors.md' 15 | - 'Contributing': 'contributing.md' 16 | 17 | theme: 'readthedocs' 18 | docs_dir: 'docs/readthedocs' 19 | site_dir: 'site' 20 | -------------------------------------------------------------------------------- /pcb/CAT-rescue.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.4 2 | #encoding utf-8 3 | # 4 | # BARREL_JACK-RESCUE-CAT 5 | # 6 | DEF BARREL_JACK-RESCUE-CAT CON 0 40 Y Y 1 F N 7 | F0 "CON" 0 250 50 H V C CNN 8 | F1 "BARREL_JACK-RESCUE-CAT" 0 -200 50 H V C CNN 9 | F2 "" 0 0 50 H V C CNN 10 | F3 "" 0 0 50 H V C CNN 11 | DRAW 12 | A -300 99 49 -900 1788 0 1 0 N -300 50 -350 100 13 | A -300 101 49 900 -1788 0 1 0 N -300 150 -350 100 14 | S 100 150 0 50 0 1 0 N 15 | P 2 0 1 0 -300 50 0 50 N 16 | P 2 0 1 0 0 150 -300 150 N 17 | P 3 0 1 0 100 0 -50 0 -50 -100 N 18 | P 5 0 1 0 100 -100 -150 -100 -200 -50 -250 -100 -350 -100 N 19 | X ~ 1 300 100 200 L 50 50 1 1 P 20 | X ~ 2 300 -100 200 L 50 50 1 1 P 21 | X ~ 3 300 0 200 L 50 50 1 1 P 22 | ENDDRAW 23 | ENDDEF 24 | # 25 | # DIPSW4-RESCUE-CAT 26 | # 27 | DEF ~DIPSW4-RESCUE-CAT SW 0 0 N N 4 F N 28 | F0 "SW" 0 100 50 H V C CNN 29 | F1 "DIPSW4-RESCUE-CAT" 0 -100 50 H I C CNN 30 | F2 "" 0 0 50 H V C CNN 31 | F3 "" 0 0 50 H V C CNN 32 | DRAW 33 | P 2 0 1 0 -51 11 49 61 N 34 | X ~ 1 -150 0 100 R 50 50 1 1 P I 35 | X ~ 8 150 0 100 L 50 50 1 1 P I 36 | X ~ 2 -150 0 100 R 50 50 2 1 P I 37 | X ~ 7 150 0 100 L 50 50 2 1 P I 38 | X ~ 3 -150 0 100 R 50 50 3 1 P I 39 | X ~ 6 150 0 100 L 50 50 3 1 P I 40 | X ~ 4 -150 0 100 R 50 50 4 1 P I 41 | X ~ 5 150 0 100 L 50 50 4 1 P I 42 | ENDDRAW 43 | ENDDEF 44 | # 45 | # JUMPER-RESCUE-CAT 46 | # 47 | DEF JUMPER-RESCUE-CAT JP 0 30 Y N 1 F N 48 | F0 "JP" 0 150 50 H V C CNN 49 | F1 "JUMPER-RESCUE-CAT" 0 -80 50 H V C CNN 50 | F2 "" 0 0 50 H V C CNN 51 | F3 "" 0 0 50 H V C CNN 52 | DRAW 53 | A 0 -26 125 1426 373 0 1 0 N -98 50 99 50 54 | C -100 0 35 0 1 0 N 55 | C 100 0 35 0 1 0 N 56 | X 1 1 -300 0 165 R 50 50 0 1 P 57 | X 2 2 300 0 165 L 50 50 0 1 P 58 | ENDDRAW 59 | ENDDEF 60 | # 61 | # JUMPER3-RESCUE-CAT 62 | # 63 | DEF JUMPER3-RESCUE-CAT JP 0 30 Y N 1 F N 64 | F0 "JP" 50 -100 50 H V L CNN 65 | F1 "JUMPER3-RESCUE-CAT" 0 100 50 H V C BNN 66 | F2 "" 0 0 50 H V C CNN 67 | F3 "" 0 0 50 H V C CNN 68 | DRAW 69 | A -60 10 64 386 1413 0 1 0 N -10 50 -110 50 70 | A 60 10 64 386 1413 0 1 0 N 110 50 10 50 71 | C -120 0 35 0 1 0 N 72 | C 0 0 36 0 1 0 N 73 | C 120 0 35 0 1 0 N 74 | X 1 1 -250 0 95 R 40 40 0 1 P 75 | X 2 2 0 -100 60 U 40 40 0 1 P 76 | X 3 3 250 0 95 L 40 40 0 1 P 77 | ENDDRAW 78 | ENDDEF 79 | # 80 | # LED-RESCUE-CAT 81 | # 82 | DEF LED-RESCUE-CAT D 0 40 Y N 1 F N 83 | F0 "D" 0 100 50 H V C CNN 84 | F1 "LED-RESCUE-CAT" 0 -100 50 H V C CNN 85 | F2 "" 0 0 50 H V C CNN 86 | F3 "" 0 0 50 H V C CNN 87 | $FPLIST 88 | LED-* 89 | LED_* 90 | $ENDFPLIST 91 | DRAW 92 | P 2 0 1 0 -50 50 -50 -50 N 93 | P 3 0 1 0 -80 -25 -125 -65 -120 -40 N 94 | P 3 0 1 0 -65 -40 -110 -80 -105 -55 N 95 | P 3 0 1 0 50 50 -50 0 50 -50 F 96 | X K 1 -200 0 150 R 40 40 1 1 P 97 | X A 2 200 0 150 L 40 40 1 1 P 98 | ENDDRAW 99 | ENDDEF 100 | # 101 | # SDRAM-RESCUE-CAT 102 | # 103 | DEF SDRAM-RESCUE-CAT U 0 40 Y Y 1 L N 104 | F0 "U" 200 250 60 H V L CNN 105 | F1 "SDRAM-RESCUE-CAT" 200 150 60 H V L CNN 106 | F2 "" 0 0 50 H I C CNN 107 | F3 "" 0 0 50 H I C CNN 108 | DRAW 109 | S 200 100 900 -2700 1 1 12 N 110 | X VDD 1 0 0 200 R 50 50 1 1 W 111 | X DQ5 10 0 -900 200 R 50 50 1 1 B 112 | X DQ6 11 0 -1000 200 R 50 50 1 1 B 113 | X VSSQ 12 0 -1100 200 R 50 50 1 1 W 114 | X DQ7 13 0 -1200 200 R 50 50 1 1 B 115 | X VDD 14 0 -1300 200 R 50 50 1 1 W 116 | X LDQM 15 0 -1400 200 R 50 50 1 1 I 117 | X ~WE 16 0 -1500 200 R 50 50 1 1 I 118 | X ~CAS 17 0 -1600 200 R 50 50 1 1 I 119 | X ~RAS 18 0 -1700 200 R 50 50 1 1 I 120 | X ~CS 19 0 -1800 200 R 50 50 1 1 I 121 | X DQ0 2 0 -100 200 R 50 50 1 1 B 122 | X BS0 20 0 -1900 200 R 50 50 1 1 I 123 | X BS1 21 0 -2000 200 R 50 50 1 1 I 124 | X A10/AP 22 0 -2100 200 R 50 50 1 1 I 125 | X A0 23 0 -2200 200 R 50 50 1 1 I 126 | X A1 24 0 -2300 200 R 50 50 1 1 I 127 | X A2 25 0 -2400 200 R 50 50 1 1 I 128 | X A3 26 0 -2500 200 R 50 50 1 1 I 129 | X VDD 27 0 -2600 200 R 50 50 1 1 W 130 | X VSS 28 1100 -2600 200 L 50 50 1 1 W 131 | X A4 29 1100 -2500 200 L 50 50 1 1 I 132 | X VDDQ 3 0 -200 200 R 50 50 1 1 W 133 | X A5 30 1100 -2400 200 L 50 50 1 1 I 134 | X A6 31 1100 -2300 200 L 50 50 1 1 I 135 | X A7 32 1100 -2200 200 L 50 50 1 1 I 136 | X A8 33 1100 -2100 200 L 50 50 1 1 I 137 | X A9 34 1100 -2000 200 L 50 50 1 1 I 138 | X A11 35 1100 -1900 200 L 50 50 1 1 I 139 | X A12 36 1100 -1800 200 L 50 50 1 1 I 140 | X CKE 37 1100 -1700 200 L 50 50 1 1 I 141 | X CLK 38 1100 -1600 200 L 50 50 1 1 I 142 | X UDQM 39 1100 -1500 200 L 50 50 1 1 I 143 | X DQ1 4 0 -300 200 R 50 50 1 1 B 144 | X NC 40 1100 -1400 200 L 50 50 1 1 N 145 | X VSS 41 1100 -1300 200 L 50 50 1 1 W 146 | X DQ8 42 1100 -1200 200 L 50 50 1 1 B 147 | X VDDQ 43 1100 -1100 200 L 50 50 1 1 W 148 | X DQ9 44 1100 -1000 200 L 50 50 1 1 B 149 | X DQ10 45 1100 -900 200 L 50 50 1 1 B 150 | X VSSQ 46 1100 -800 200 L 50 50 1 1 W 151 | X DQ11 47 1100 -700 200 L 50 50 1 1 B 152 | X DQ12 48 1100 -600 200 L 50 50 1 1 B 153 | X VDDQ 49 1100 -500 200 L 50 50 1 1 W 154 | X DQ2 5 0 -400 200 R 50 50 1 1 B 155 | X DQ13 50 1100 -400 200 L 50 50 1 1 B 156 | X DQ14 51 1100 -300 200 L 50 50 1 1 B 157 | X VSSQ 52 1100 -200 200 L 50 50 1 1 W 158 | X DQ15 53 1100 -100 200 L 50 50 1 1 B 159 | X VSS 54 1100 0 200 L 50 50 1 1 W 160 | X VSSQ 6 0 -500 200 R 50 50 1 1 W 161 | X DQ3 7 0 -600 200 R 50 50 1 1 B 162 | X DQ4 8 0 -700 200 R 50 50 1 1 B 163 | X VDDQ 9 0 -800 200 R 50 50 1 1 W 164 | ENDDRAW 165 | ENDDEF 166 | # 167 | # SERIAL_FLASH-RESCUE-CAT 168 | # 169 | DEF SERIAL_FLASH-RESCUE-CAT U 0 40 Y Y 1 L N 170 | F0 "U" 200 250 60 H V L CNN 171 | F1 "SERIAL_FLASH-RESCUE-CAT" 200 150 60 H V L CNN 172 | F2 "" 0 0 50 H I C CNN 173 | F3 "" 0 0 50 H I C CNN 174 | DRAW 175 | S 200 100 900 -400 1 1 12 N 176 | X ~CS 1 0 0 200 R 50 50 1 1 I 177 | X SO 2 0 -100 200 R 50 50 1 1 O 178 | X ~WP 3 0 -200 200 R 50 50 1 1 I 179 | X GND 4 0 -300 200 R 50 50 1 1 W 180 | X SI 5 1100 -300 200 L 50 50 1 1 I 181 | X SCK 6 1100 -200 200 L 50 50 1 1 I 182 | X ~HOLD 7 1100 -100 200 L 50 50 1 1 I 183 | X VCC 8 1100 0 200 L 50 50 1 1 W 184 | ENDDRAW 185 | ENDDEF 186 | # 187 | # SW_PUSH-RESCUE-CAT 188 | # 189 | DEF SW_PUSH-RESCUE-CAT SW 0 40 N N 1 F N 190 | F0 "SW" 150 110 50 H V C CNN 191 | F1 "SW_PUSH-RESCUE-CAT" 0 -80 50 H V C CNN 192 | F2 "" 0 0 50 H V C CNN 193 | F3 "" 0 0 50 H V C CNN 194 | DRAW 195 | S -170 50 170 60 0 1 0 N 196 | P 4 0 1 0 -40 60 -30 90 30 90 40 60 N 197 | X 1 1 -300 0 200 R 50 50 0 1 P I 198 | X 2 2 300 0 200 L 50 50 0 1 P I 199 | ENDDRAW 200 | ENDDEF 201 | # 202 | #End Library 203 | -------------------------------------------------------------------------------- /pcb/CAT.pro: -------------------------------------------------------------------------------- 1 | update=10/06/2016 1:45:15 PM 2 | version=1 3 | last_client=kicad 4 | [cvpcb] 5 | version=1 6 | NetIExt=net 7 | [pcbnew] 8 | version=1 9 | PageLayoutDescrFile=C:/xesscorp/KiCad/page_layouts/title_block_only.kicad_wks 10 | LastNetListRead= 11 | UseCmpFile=1 12 | PadDrill=1.016 13 | PadDrillOvalY=1.016 14 | PadSizeH=1.7272 15 | PadSizeV=1.7272 16 | PcbTextSizeV=1.5 17 | PcbTextSizeH=1.5 18 | PcbTextThickness=0.3 19 | ModuleTextSizeV=1 20 | ModuleTextSizeH=1 21 | ModuleTextSizeThickness=0.15 22 | SolderMaskClearance=0 23 | SolderMaskMinWidth=0 24 | DrawSegmentWidth=0.2 25 | BoardOutlineThickness=0.09999999999999999 26 | ModuleOutlineThickness=0.15 27 | [general] 28 | version=1 29 | [schematic_editor] 30 | version=1 31 | PageLayoutDescrFile= 32 | PlotDirectoryName= 33 | SubpartIdSeparator=0 34 | SubpartFirstId=65 35 | NetFmtName= 36 | SpiceForceRefPrefix=0 37 | SpiceUseNetNumbers=0 38 | LabSize=50 39 | ERC_TestSimilarLabels=1 40 | [eeschema] 41 | version=1 42 | LibDir=C:/xesscorp/KiCad/libraries 43 | [eeschema/libraries] 44 | LibName1=CAT-rescue 45 | LibName2=power 46 | LibName3=device 47 | LibName4=transistors 48 | LibName5=conn 49 | LibName6=linear 50 | LibName7=regul 51 | LibName8=74xx 52 | LibName9=cmos4000 53 | LibName10=adc-dac 54 | LibName11=memory 55 | LibName12=xilinx 56 | LibName13=microcontrollers 57 | LibName14=dsp 58 | LibName15=microchip 59 | LibName16=analog_switches 60 | LibName17=motorola 61 | LibName18=texas 62 | LibName19=intel 63 | LibName20=audio 64 | LibName21=interface 65 | LibName22=digital-audio 66 | LibName23=philips 67 | LibName24=display 68 | LibName25=cypress 69 | LibName26=siliconi 70 | LibName27=opto 71 | LibName28=atmel 72 | LibName29=contrib 73 | LibName30=valves 74 | LibName31=xess 75 | LibName32=Cypress_PSoC 76 | LibName33=Cypress_cy8c5xlp 77 | LibName34=Lattice_iCE_FPGA 78 | LibName35=xilinx7 79 | LibName36=xilinx6v 80 | LibName37=xilinx6s 81 | LibName38=xula 82 | LibName39=espressif-xess/espressif-xess 83 | -------------------------------------------------------------------------------- /pcb/assembly_order.txt: -------------------------------------------------------------------------------- 1 | Assemble CAT Board parts in this order: 2 | 3 | Frontside: 4 | U4 - FPGA 5 | 6 | Backside: Frontside: 7 | R6 - 100 ohm C48 - 0.1 uF 8 | C44 - 0.1 uF U7 - Oscillator 9 | C46 - 0.01 uF LED1 - LED 10 | C38 - 1.0 uF LED2 - LED 11 | C40 - 0.1 uF LED3 - LED 12 | C33 - 10 uF LED4 - LED 13 | C42 - 0.1 uF RN5 - 100 ohm x 4 14 | C17 - 0.1 uF RN9 - 4.7 Kohm x 2 15 | C34 - 0.1 uF RN10 - 4.7 Kohm x 2 16 | C25 - 0.1 uF RN11 - 4.7 Kohm x 2 17 | C35 - 0.1 uF RN1 - 4.7 Kohm x 2 18 | C21 - 1.0 uF RN4 - 4.7 Kohm x 2 19 | C32 - 10 uF RN2 - 100 ohm x 2 20 | C23 - 1.0 uF Q1 - MOSFET 21 | C19 - 0.1 uF C2 - 10 uF 22 | C31 - 1.0 uF C3 - 10 uF 23 | C27 - 0.1 uF C4 - 10 uF 24 | C43 - 0.01 uF U1 - AZ1117EH-3.3 25 | C41 - 0.1 uF U3 - AZ1117EH-1.2 26 | C39 - 1.0 uF U5 - SDRAM 27 | C28 - 1.0 uF RESET - Pushbutton 28 | C24 - 0.1 uF SW1 - Pushbutton 29 | C20 - 1.0 uF SW2 - Pushbutton 30 | C16 - 0.1 uF U2 - I2C Serial Flash 31 | D1 - Diode U6 - SPI Serial Flash 32 | R1 - 100 ohm C1 - 100 uF 33 | C29 - 1.0 uF 34 | C45 - 0.1 uF 35 | C26 - 0.1 uF 36 | C18 - 0.1 uF 37 | C22 - 1.0 uF 38 | C47 - 0.1 uF 39 | C30 - 1.0 uF 40 | C5 - 0.1 uF 41 | C8 - 0.1 uF 42 | C10 - 0.1 uF 43 | C12 - 0.1 uF 44 | C14 - 0.1 uF 45 | C9 - 1.0 uF 46 | C11 - 1.0 uF 47 | C13 - 1.0 uF 48 | C6 - 10 uF 49 | R7 - 100 ohm 50 | RN6 - 100 ohm x 4 51 | RN3 - 4.7K ohm x 2 52 | R10 - 787 ohm 53 | R9 - 1.87K ohm 54 | R11 - 475 ohm 55 | R8 - 768 ohm 56 | U8 - AZ1117EH-ADJ 57 | -------------------------------------------------------------------------------- /pcb/pcb_art.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | CAT in the HAT Board 69 | CAT Board 83 | Don't Mistake Being humorlessFor Being Serious 113 | 114 | 115 | -------------------------------------------------------------------------------- /pcb/rookie_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devbisme/CAT-Board/250d8926a5e68af80773cd633ed1ca4ee47c2e05/pcb/rookie_head.png -------------------------------------------------------------------------------- /pcb/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (lib (name CAT-rescue)(type Legacy)(uri ${KIPRJMOD}/CAT-rescue.lib)(options "")(descr "")) 3 | (lib (name power)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/power.lib)(options "")(descr "")) 4 | (lib (name device)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/device.lib)(options "")(descr "")) 5 | (lib (name transistors)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/transistors.lib)(options "")(descr "")) 6 | (lib (name conn)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/conn.lib)(options "")(descr "")) 7 | (lib (name linear)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/linear.lib)(options "")(descr "")) 8 | (lib (name regul)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/regul.lib)(options "")(descr "")) 9 | (lib (name 74xx)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/74xx.lib)(options "")(descr "")) 10 | (lib (name cmos4000)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/cmos4000.lib)(options "")(descr "")) 11 | (lib (name adc-dac)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/adc-dac.lib)(options "")(descr "")) 12 | (lib (name memory)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/memory.lib)(options "")(descr "")) 13 | (lib (name xilinx)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/xilinx.lib)(options "")(descr "")) 14 | (lib (name microcontrollers)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/microcontrollers.lib)(options "")(descr "")) 15 | (lib (name dsp)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/dsp.lib)(options "")(descr "")) 16 | (lib (name microchip)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/microchip.lib)(options "")(descr "")) 17 | (lib (name analog_switches)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/analog_switches.lib)(options "")(descr "")) 18 | (lib (name motorola)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/motorola.lib)(options "")(descr "")) 19 | (lib (name texas)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/texas.lib)(options "")(descr "")) 20 | (lib (name intel)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/intel.lib)(options "")(descr "")) 21 | (lib (name audio)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/audio.lib)(options "")(descr "")) 22 | (lib (name interface)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/interface.lib)(options "")(descr "")) 23 | (lib (name digital-audio)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/digital-audio.lib)(options "")(descr "")) 24 | (lib (name philips)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/philips.lib)(options "")(descr "")) 25 | (lib (name display)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/display.lib)(options "")(descr "")) 26 | (lib (name cypress)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/cypress.lib)(options "")(descr "")) 27 | (lib (name siliconi)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/siliconi.lib)(options "")(descr "")) 28 | (lib (name opto)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/opto.lib)(options "")(descr "")) 29 | (lib (name atmel)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/atmel.lib)(options "")(descr "")) 30 | (lib (name contrib)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/contrib.lib)(options "")(descr "")) 31 | (lib (name valves)(type Legacy)(uri C:/msys64/mingw64/share/kicad/library/valves.lib)(options "")(descr "")) 32 | (lib (name xess)(type Legacy)(uri C:/xesscorp/KiCad/libraries/xess.lib)(options "")(descr "")) 33 | (lib (name Cypress_PSoC)(type Legacy)(uri C:/xesscorp/KiCad/libraries/Cypress_PSoC.lib)(options "")(descr "")) 34 | (lib (name Cypress_cy8c5xlp)(type Legacy)(uri C:/xesscorp/KiCad/libraries/Cypress_cy8c5xlp.lib)(options "")(descr "")) 35 | (lib (name Lattice_iCE_FPGA)(type Legacy)(uri C:/xesscorp/KiCad/libraries/Lattice_iCE_FPGA.lib)(options "")(descr "")) 36 | (lib (name xilinx7)(type Legacy)(uri C:/xesscorp/KiCad/libraries/xilinx7.lib)(options "")(descr "")) 37 | (lib (name xilinx6v)(type Legacy)(uri C:/xesscorp/KiCad/libraries/xilinx6v.lib)(options "")(descr "")) 38 | (lib (name xilinx6s)(type Legacy)(uri C:/xesscorp/KiCad/libraries/xilinx6s.lib)(options "")(descr "")) 39 | (lib (name espressif-xess)(type Legacy)(uri C:/xesscorp/KiCad/libraries/espressif-xess/espressif-xess.lib)(options "")(descr "")) 40 | ) 41 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # CAT Board Tests 2 | 3 | 4 | # Description 5 | 6 | These are some simple test designs for the CAT Board: 7 | 8 | * Display a counter or a scrolling pattern of characters on a StickIt! LEDDigits display. 9 | * Display the hex value of the four-bit `SW3` DIP switch on first and last digits of the LEDDigits display and blank them if pushbuttons `SW1` or `SW2` are pressed. 10 | 11 | 12 | # Test Procedures 13 | 14 | ## LED Digits Test 15 | 16 | 1. Attach the CAT Board to the Raspberry Pi (RPi) GPIO header. 17 | 1. Connect the RPi to an HDMI display, mouse, keyboard and power supply. 18 | 1. Attach the StickIt! LEDDigits board to the `PM3` PMOD socket on the CAT Board. 19 | 1. Compile the led\_digits\_display.py test design: 20 | 21 | python led_digits_display.py 22 | 23 | 1. Download the bitstream to the CAT Board: 24 | 25 | sudo bash config_cat iceriver/catboard.bin 26 | 27 | 1. Sit back and watch the digits roll by... 28 | 29 | ## Buttons Test 30 | 31 | 1. Attach the CAT Board to the Raspberry Pi (RPi) GPIO header. 32 | 1. Connect the RPi to an HDMI display, mouse, keyboard and power supply. 33 | 1. Attach the StickIt! LEDDigits board to the `PM3` PMOD socket on the CAT Board. 34 | 1. Compile the buttons_display.py test design: 35 | 36 | python buttons_display.py 37 | 38 | 1. Download the bitstream to the CAT Board: 39 | 40 | sudo bash config_cat iceriver/catboard.bin 41 | 42 | 1. The digits on the far left and right of the LEDDigits display should both come on and display the digit representing the hex value of DIP switch `SW3`. Changing the DIP switches should change the displayed value. 43 | 1. Pressing `SW1` should turn off digit `LED1` for as long as the button is held down. 44 | 1. Pressing `SW2` should turn off digit `LED8` for as long as the button is held down. 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/Clk.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | 3 | def clkDriver(clk): 4 | 5 | halfPeriod = delay(1) 6 | 7 | @always(halfPeriod) 8 | def driveClk(): 9 | clk.next = not clk 10 | 11 | return driveClk 12 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/Conversion.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | from SdramCntl import * 3 | from Clk import * 4 | from sdram import * 5 | from host_intf import * 6 | from sd_intf import * 7 | 8 | clk_i = Signal(bool(0)) 9 | rst_i = ResetSignal(0,active=1,isasync=True) 10 | 11 | clkDriver_Inst = clkDriver(clk_i) 12 | sd_intf_Inst = sd_intf() 13 | host_intf_Inst = host_intf() 14 | 15 | sdramCntl_Inst = MySdramCntl(clk_i,host_intf_Inst,sd_intf_Inst) 16 | 17 | toVerilog(MySdramCntl,clk_i,host_intf_Inst,sd_intf_Inst) 18 | toVHDL(MySdramCntl,clk_i,host_intf_Inst,sd_intf_Inst) 19 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/SdramCntl.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | from math import ceil,log 3 | from .sd_intf import * 4 | from .host_intf import * 5 | 6 | def MySdramCntl(clk_i,host_intf, sd_intf): 7 | 8 | # commands to SDRAM ce ras cas we dqml dqmh 9 | NOP_CMD_C = int(sd_intf.SDRAM_NOP_CMD_C) #intbv("011100")[6:] #0,1,1,1,0,0 10 | ACTIVE_CMD_C = int(sd_intf.SDRAM_ACTIVE_CMD_C) #intbv("001100")[6:] #0,0,1,1,0,0 11 | READ_CMD_C = int(sd_intf.SDRAM_READ_CMD_C) #intbv("010100")[6:] # 0,1,0,1,0,0 12 | WRITE_CMD_C = int(sd_intf.SDRAM_WRITE_CMD_C) #intbv("010000")[6:] # 0,1,0,0,0,0 13 | PCHG_CMD_C = int(sd_intf.SDRAM_PCHG_CMD_C) #intbv("001000")[6:] # 0,0,1,0,0,0 14 | MODE_CMD_C = int(sd_intf.SDRAM_MODE_CMD_C) #intbv("000000")[6:] # 0,0,0,0,0,0 15 | RFSH_CMD_C = int(sd_intf.SDRAM_RFSH_CMD_C) #intbv("000100")[6:] # 0,0,0,1,0,0 16 | MODE_C = int(sd_intf.SDRAM_MODE_C) #intbv("00_0_00_011_0_000")[12:] # mode command for set_mode command 17 | 18 | # generic parameters 19 | FREQ_GHZ_G = sd_intf.SDRAM_FREQ_C / 1000 20 | #ENABLE_REFRESH_G = True 21 | NROWS_G = sd_intf.SDRAM_NROWS_C 22 | T_REF_G = sd_intf.SDRAM_T_REF_C 23 | T_INIT_G = sd_intf.SDRAM_T_INIT_C # min initialization interval (ns). 24 | T_RAS_G = sd_intf.SDRAM_T_RAS_C # min interval between active to precharge commands (ns). 25 | T_RCD_G = sd_intf.SDRAM_T_RCD_C # min interval between active and R/W commands (ns). 26 | T_REF_G = sd_intf.SDRAM_T_REF_C # maximum refresh interval (ns). 27 | T_RFC_G = sd_intf.SDRAM_T_RFC_C # duration of refresh operation (ns). 28 | T_RP_G = sd_intf.SDRAM_T_RP_C # min precharge command duration (ns). 29 | T_XSR_G = sd_intf.SDRAM_T_XSR_C # exit self-refresh time (ns). 30 | 31 | # delay constants 32 | INIT_CYCLES_C = int(ceil(T_INIT_G * FREQ_GHZ_G)) 33 | RP_CYCLES_C = int(ceil(T_RP_G * FREQ_GHZ_G)) 34 | RFC_CYCLES_C = int(ceil(T_RFC_G * FREQ_GHZ_G)) 35 | REF_CYCLES_C = int(ceil(T_REF_G * FREQ_GHZ_G / NROWS_G)) 36 | RCD_CYCLES_C = int(ceil(T_RCD_G * FREQ_GHZ_G)) 37 | RAS_CYCLES_C = int(ceil(T_RAS_G * FREQ_GHZ_G)) 38 | MODE_CYCLES_C = 2 39 | CAS_CYCLES_C = 3 40 | WR_CYCLES_C = 2 41 | RFSH_OPS_C = 8 # number of refresh operations needed to init SDRAM. 42 | 43 | # constant values 44 | ALL_BANKS_C = int(sd_intf.SDRAM_ALL_BANKS_C) # value of CMDBIT to select all banks 45 | ONE_BANK_C = int(sd_intf.SDRAM_ONE_BANK_C) 46 | INPUT_C = bool(0) # sDataDir_r bit 0 for INPUT 47 | OUTPUT_C = bool(1) # sDataDir_r bit 1 for OUTPUT 48 | NOP_C = bool(0) 49 | READ_C = bool(1) 50 | WRITE_C = bool(1) 51 | BA_LEN_C = 2 52 | COL_LEN_C = int(log(sd_intf.SDRAM_NCOLS_C,2)) 53 | ROW_LEN_C = int(log(sd_intf.SDRAM_NROWS_C,2)) 54 | 55 | # states of the SDRAM controller state machine 56 | CntlStateType = enum( 57 | 'INITWAIT', # initialization - waiting for power-on initialization to complete. 58 | 'INITPCHG', # initialization - initial precharge of SDRAM banks. 59 | 'INITSETMODE', # initialization - set SDRAM mode. 60 | 'INITRFSH', # initialization - do initial refreshes. 61 | 'RW', # read/write/refresh the SDRAM. 62 | 'ACTIVATE', # open a row of the SDRAM for reading/writing. 63 | 'REFRESHROW', # refresh a row of the SDRAM. 64 | #'SELFREFRESH' # keep SDRAM in self-refresh mode with CKE low. 65 | ); 66 | 67 | # state register and next state 68 | state_r = Signal(CntlStateType.INITWAIT) 69 | state_x = Signal(CntlStateType.INITWAIT) 70 | 71 | # timer registers 72 | timer_r = Signal(intbv(0,min=0,max=INIT_CYCLES_C+1)) # current sdram opt time 73 | timer_x = Signal(intbv(0,min=0,max=INIT_CYCLES_C+1)) 74 | 75 | refTimer_r = Signal(intbv(REF_CYCLES_C,min=0,max=REF_CYCLES_C+1)) # time between row refreshes 76 | refTimer_x = Signal(intbv(REF_CYCLES_C,min=0,max=REF_CYCLES_C+1)) 77 | 78 | rasTimer_r = Signal(intbv(0,min=0,max=RAS_CYCLES_C+1)) # active to precharge time 79 | rasTimer_x = Signal(intbv(0,min=0,max=RAS_CYCLES_C+1)) 80 | 81 | wrTimer_r = Signal(intbv(0,min=0,max=WR_CYCLES_C+1)) # write to precharge time 82 | wrTimer_x = Signal(intbv(0,min=0,max=WR_CYCLES_C+1)) 83 | 84 | rfshCntr_r = Signal(intbv(0,min=0,max=NROWS_G+1)) # count refreshes that are needed 85 | rfshCntr_x = Signal(intbv(0,min=0,max=NROWS_G+1)) 86 | 87 | # status signals 88 | activateInProgress_s = Signal(bool(0)) 89 | rdInProgress_s = Signal(bool(0)) 90 | writeInProgress_s = Signal(bool(0)) 91 | 92 | # command assignment 93 | cmd_r = Signal(intbv(NOP_CMD_C)[3:0]) # ideally this should be [6:] we remove last two digits and first digit since they are always zero 94 | cmd_x = Signal(intbv(NOP_CMD_C)[3:0]) 95 | 96 | sAddr_r = Signal(intbv(0)[ROW_LEN_C:]) # ideally this should be sd_intf.addr_width but we dont use upper two bits 97 | sAddr_x = Signal(intbv(0)[ROW_LEN_C:]) 98 | 99 | sData_r = Signal(intbv(0)[sd_intf.data_width:]) 100 | sData_x = Signal(intbv(0)[sd_intf.data_width:]) 101 | 102 | sDriver = sd_intf.dq.driver() 103 | 104 | sdramData_r = Signal(intbv(0)[sd_intf.data_width:]) 105 | sdramData_x = Signal(intbv(0)[sd_intf.data_width:]) 106 | 107 | sDataDir_r = Signal(INPUT_C) 108 | sDataDir_x = Signal(INPUT_C) 109 | 110 | activeRow_r = [ Signal(intbv(0)[ROW_LEN_C:]) for _ in range(2**BA_LEN_C) ] # each bank will have a active row 111 | activeRow_x = [ Signal(intbv(0)[ROW_LEN_C:]) for _ in range(2**BA_LEN_C) ] 112 | activeFlag_r = [ Signal(bool(0)) for _ in range(2**BA_LEN_C) ] 113 | activeFlag_x = [ Signal(bool(0)) for _ in range(2**BA_LEN_C) ] 114 | activeBank_r = Signal(intbv(0)[2:]) 115 | activeBank_x = Signal(intbv(0)[2:]) # banks with active rows 116 | doActivate_s = Signal(bool(0)) # request row activation if a new row is needed to activate 117 | 118 | rdPipeline_r = Signal(intbv(0)[CAS_CYCLES_C+2:]) 119 | rdPipeline_x = Signal(intbv(0)[CAS_CYCLES_C+2:]) 120 | 121 | wrPipeline_r = Signal(intbv(0)[CAS_CYCLES_C+2:]) 122 | wrPipeline_x = Signal(intbv(0)[CAS_CYCLES_C+2:]) 123 | 124 | ba_r = Signal(intbv(0)[BA_LEN_C:]) 125 | ba_x = Signal(intbv(0)[BA_LEN_C:]) 126 | 127 | bank_s = Signal(intbv(0)[BA_LEN_C:]) 128 | row_s = Signal(intbv(0)[ROW_LEN_C:]) 129 | col_s = Signal(intbv(0)[COL_LEN_C:]) 130 | 131 | # pin assignment for SDRAM 132 | @always_comb 133 | def sdram_pin_map(): 134 | sd_intf.cke.next = 1 135 | sd_intf.cs.next = 0 #cmd_r[3] 136 | sd_intf.ras.next = cmd_r[2] 137 | sd_intf.cas.next = cmd_r[1] 138 | sd_intf.we.next = cmd_r[0] 139 | sd_intf.bs.next = bank_s 140 | sd_intf.addr.next = sAddr_r 141 | #sd_intf.driver.next = sData_r if sDataDir_r == OUTPUT_C else None 142 | if sDataDir_r == OUTPUT_C : 143 | sDriver.next = sData_r 144 | else : 145 | sDriver.next = None 146 | sd_intf.dqml.next = 0 147 | sd_intf.dqmh.next = 0 148 | 149 | # pin assignment for HOST SIDE 150 | @always_comb 151 | def host_pin_map(): 152 | host_intf.done_o.next = rdPipeline_r[0] or wrPipeline_r[0] 153 | host_intf.data_o.next = sdramData_r 154 | host_intf.rdPending_o.next = rdInProgress_s 155 | sData_x.next = host_intf.data_i 156 | 157 | # extract bank, row and column from controller address 158 | @always_comb 159 | def extract_addr(): 160 | # extract bank 161 | # Multiple active rows logic has been removed for now 162 | bank_s.next = host_intf.addr_i[BA_LEN_C+ROW_LEN_C+COL_LEN_C:ROW_LEN_C+COL_LEN_C] 163 | ba_x.next = host_intf.addr_i[BA_LEN_C+ROW_LEN_C+COL_LEN_C:ROW_LEN_C+COL_LEN_C] 164 | 165 | # extract row 166 | row_s.next = host_intf.addr_i[ROW_LEN_C+COL_LEN_C:COL_LEN_C] 167 | # extract column 168 | col_s.next = host_intf.addr_i[COL_LEN_C:] 169 | 170 | 171 | @always_comb 172 | def do_active(): 173 | if bank_s != activeBank_r or row_s != activeRow_r[bank_s.val] or activeFlag_r[bank_s.val] == False : 174 | doActivate_s.next = True 175 | else : 176 | doActivate_s.next = False 177 | 178 | # rdPipeline_x.next = concat(NOP_C,rdPipeline_r[CAS_CYCLES_C+2:1]) 179 | # wrPipeline_x.next = intbv(NOP_C)[CAS_CYCLES_C+2:] 180 | 181 | if rdPipeline_r[1] == READ_C : 182 | sdramData_x.next = sd_intf.dq 183 | else : 184 | sdramData_x.next = sdramData_r 185 | 186 | # update status signals 187 | #activateInProgress_s.next = True if rasTimer_r != 0 else False 188 | if rasTimer_r != 0 : 189 | activateInProgress_s.next = True 190 | else : 191 | activateInProgress_s.next = False 192 | 193 | #writeInProgress_s.next = True if wrTimer_r != 0 else False 194 | if wrTimer_r != 0 : 195 | writeInProgress_s.next = True 196 | else : 197 | writeInProgress_s.next = False 198 | 199 | #rdInProgress_s.next = True if rdPipeline_r[CAS_CYCLES_C+2:1] != 0 else False 200 | if rdPipeline_r[CAS_CYCLES_C+2:1] != 0 : 201 | rdInProgress_s.next = True 202 | else : 203 | rdInProgress_s.next = False 204 | 205 | @always_comb 206 | def comb_func(): 207 | 208 | rdPipeline_x.next = concat(NOP_C,rdPipeline_r[CAS_CYCLES_C+2:1]) 209 | wrPipeline_x.next = intbv(NOP_C)[CAS_CYCLES_C+2:] 210 | 211 | ##################### Update the timers ########################### 212 | 213 | # row activation timer 214 | #rasTimer_x.next = rasTimer_r - 1 if rasTimer_r != 0 else rasTimer_r 215 | if rasTimer_r != 0 : 216 | rasTimer_x.next = rasTimer_r -1 217 | else : 218 | rasTimer_x.next = rasTimer_r 219 | 220 | # write operation timer 221 | #wrTimer_x.next = wrTimer_r - 1 if wrTimer_r != 0 else wrTimer_r 222 | if wrTimer_r != 0 : 223 | wrTimer_x.next = wrTimer_r - 1 224 | else : 225 | wrTimer_x.next = wrTimer_r 226 | 227 | # refresh timer 228 | #refTimer_x.next = refTimer_r - 1 if refTimer_r != 0 else REF_CYCLES_C 229 | if refTimer_r != 0 : 230 | refTimer_x.next = refTimer_r - 1 231 | rfshCntr_x.next = rfshCntr_r 232 | else : 233 | refTimer_x.next = REF_CYCLES_C 234 | #if refTimer_r == 0 : 235 | # on timeout, reload the timer with the interval between row refreshes 236 | # and increment the counter for the number of row refreshes that are needed 237 | #rfshCntr_x.next = rfshCntr_r + 1 if ENABLE_REFRESH_G else 0 238 | rfshCntr_x.next = rfshCntr_r + 1 239 | 240 | ###################################################################### 241 | 242 | ################### code to remove latches ########################### 243 | cmd_x.next = NOP_CMD_C 244 | state_x.next = state_r 245 | sAddr_x.next = sAddr_r 246 | activeBank_x.next = activeBank_r 247 | sDataDir_x.next = sDataDir_r 248 | for index in range(2**BA_LEN_C): 249 | activeFlag_x[index].next = activeFlag_r[index] 250 | activeRow_x[index].next = activeRow_r[index] 251 | ###################################################################### 252 | 253 | if timer_r != 0 : 254 | timer_x.next = timer_r - 1 255 | cmd_x.next = NOP_CMD_C 256 | else : 257 | timer_x.next = timer_r 258 | 259 | if state_r == CntlStateType.INITWAIT : 260 | # wait for SDRAM power-on initialization once the clock is stable 261 | timer_x.next = INIT_CYCLES_C # set timer for initialization duration 262 | state_x.next = CntlStateType.INITPCHG 263 | 264 | elif state_r == CntlStateType.INITPCHG : 265 | # all banks should be precharged after initialization 266 | cmd_x.next = PCHG_CMD_C 267 | timer_x.next = RP_CYCLES_C # set timer for precharge operation duration 268 | state_x.next = CntlStateType.INITRFSH 269 | sAddr_x.next = ALL_BANKS_C # select all banks precharge 270 | rfshCntr_x.next = RFSH_OPS_C 271 | ### tempory line should be change ##### 272 | #state_x.next = CntlStateType.RW 273 | ####################################### 274 | 275 | 276 | elif state_r == CntlStateType.INITRFSH : 277 | # refreshing state 278 | cmd_x.next = RFSH_CMD_C 279 | timer_x.next = RFC_CYCLES_C 280 | rfshCntr_x.next = rfshCntr_r - 1 281 | if rfshCntr_r == 1 : 282 | state_x.next = CntlStateType.INITSETMODE 283 | 284 | elif state_r == CntlStateType.INITSETMODE : 285 | cmd_x.next = MODE_CMD_C 286 | timer_x.next = MODE_CYCLES_C 287 | state_x.next = CntlStateType.RW 288 | sAddr_x.next = MODE_C 289 | 290 | elif state_r == CntlStateType.RW : 291 | 292 | if rfshCntr_r != 0 : 293 | # wait for any activation, read or write before precharge 294 | if activateInProgress_s == False and writeInProgress_s == False and rdInProgress_s == False : 295 | cmd_x.next = PCHG_CMD_C 296 | timer_x.next = RP_CYCLES_C 297 | state_x.next = CntlStateType.REFRESHROW 298 | sAddr_x.next = ALL_BANKS_C 299 | for index in range(2**BA_LEN_C): 300 | activeFlag_x[index].next = False 301 | 302 | # for now leave row refresh need.. IT SHOULD COME HERE 303 | elif host_intf.rd_i == True : 304 | if ba_x == ba_r : 305 | if doActivate_s == True : # A new row need to be activated. PRECHARGE The bank 306 | # activate new row only if all previous activations, writes, reads are done 307 | if activateInProgress_s == False and writeInProgress_s == False and rdInProgress_s == False : 308 | cmd_x.next = PCHG_CMD_C 309 | timer_x.next = RP_CYCLES_C 310 | state_x.next = CntlStateType.ACTIVATE 311 | sAddr_x.next = ONE_BANK_C 312 | activeFlag_x[bank_s].next = False 313 | elif rdInProgress_s == False: 314 | cmd_x.next = READ_CMD_C 315 | sDataDir_x.next = INPUT_C 316 | sAddr_x.next = col_s 317 | rdPipeline_x.next = concat(READ_C,rdPipeline_r[CAS_CYCLES_C+2:1]) 318 | 319 | elif host_intf.wr_i == True : 320 | if ba_x == ba_r : 321 | if doActivate_s == True : 322 | # activate new row only if all previous activations, writes, reads are done 323 | if activateInProgress_s == False and writeInProgress_s == False and rdInProgress_s == False : 324 | cmd_x.next = PCHG_CMD_C 325 | timer_x.next = RP_CYCLES_C 326 | state_x.next = CntlStateType.ACTIVATE 327 | sAddr_x.next = ONE_BANK_C 328 | activeFlag_x[bank_s].next = False 329 | 330 | elif rdInProgress_s == False : 331 | cmd_x.next = WRITE_CMD_C 332 | sDataDir_x.next = OUTPUT_C 333 | sAddr_x.next = col_s 334 | wrPipeline_x.next = intbv(1)[CAS_CYCLES_C+2:] 335 | wrTimer_x.next = WR_CYCLES_C 336 | 337 | else : 338 | cmd_x.next = NOP_CMD_C 339 | state_x.next = CntlStateType.RW 340 | 341 | 342 | elif state_r == CntlStateType.ACTIVATE : 343 | cmd_x.next = ACTIVE_CMD_C 344 | timer_x.next = RCD_CYCLES_C 345 | state_x.next = CntlStateType.RW 346 | rasTimer_x.next = RAS_CYCLES_C 347 | sAddr_x.next = row_s 348 | activeBank_x.next = bank_s 349 | activeRow_x[bank_s].next = row_s 350 | activeFlag_x[bank_s].next = True 351 | 352 | elif state_r == CntlStateType.REFRESHROW : 353 | cmd_x.next = RFSH_CMD_C 354 | timer_x.next = RFC_CYCLES_C 355 | state_x.next = CntlStateType.RW 356 | rfshCntr_x.next = rfshCntr_r - 1 357 | 358 | else : 359 | state_x.next = CntlStateType.INITWAIT 360 | 361 | @always_seq(clk_i.posedge, host_intf.rst_i) 362 | def seq_func(): 363 | 364 | state_r.next = state_x 365 | cmd_r.next = cmd_x 366 | 367 | sAddr_r.next = sAddr_x 368 | sData_r.next = sData_x 369 | sDataDir_r.next = sDataDir_x 370 | activeBank_r.next = activeBank_x 371 | sdramData_r.next = sdramData_x 372 | wrPipeline_r.next = wrPipeline_x 373 | rdPipeline_r.next = rdPipeline_x 374 | ba_r.next = ba_x 375 | # timers 376 | timer_r.next = timer_x 377 | rasTimer_r.next = rasTimer_x 378 | refTimer_r.next = refTimer_x 379 | wrTimer_r.next = wrTimer_x 380 | rfshCntr_r.next = rfshCntr_x 381 | for index in range(2**BA_LEN_C) : 382 | activeRow_r[index].next = activeRow_x[index] 383 | activeFlag_r[index].next = activeFlag_x[index] 384 | 385 | 386 | return comb_func, seq_func, sdram_pin_map, host_pin_map, extract_addr, do_active 387 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/__init__.py: -------------------------------------------------------------------------------- 1 | from .sd_intf import * 2 | from .SdramCntl import * 3 | from .host_intf import * 4 | from .sdram import * -------------------------------------------------------------------------------- /tests/SDRAM_Controller/host_intf.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | 3 | class host_intf(object): 4 | 5 | def __init__(self): 6 | # Host side signals 7 | self.rst_i = ResetSignal(0, active=1, isasync=True) 8 | self.rd_i = Signal(bool(0)) 9 | self.wr_i = Signal(bool(0)) 10 | self.addr_i = Signal(intbv(0)[24:]) # host side address = sdram side row + col + bank 11 | self.data_i = Signal(intbv(0)[16:]) 12 | self.data_o = Signal(intbv(0)[16:]) 13 | self.done_o = Signal(bool(0)) 14 | self.rdPending_o= Signal(bool(0)) 15 | # self.status_o = Signal(bool(0)) 16 | 17 | def read(self,addr): 18 | self.addr_i.next = addr 19 | self.rd_i.next = 1 20 | yield delay(2) 21 | self.rd_i.next = 0 22 | 23 | def write(self,addr,data): 24 | self.addr_i.next = addr 25 | self.data_i.next = data 26 | yield delay(5) 27 | self.wr_i.next = 1 28 | 29 | def nop(self): 30 | self.rd_i.next = 0 31 | self.wr_i.next = 0 32 | 33 | def waitUntilDone(self): 34 | yield self.done_o.posedge 35 | 36 | def readData(self): 37 | return self.data_o.val 38 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/sd_intf.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | from math import log 3 | 4 | class sd_intf(object): 5 | 6 | addr_width = 13 7 | data_width = 16 8 | # constant for sdram 9 | SDRAM_NROWS_C = 8192 # Number of rows in SDRAM array. 10 | SDRAM_NCOLS_C = 512 # Number of columns in SDRAM array. 11 | SDRAM_DATA_WIDTH_C = 16 # Host & SDRAM data width. 12 | SDRAM_HADDR_WIDTH_C = 24 # Host-side address width. 13 | SDRAM_SADDR_WIDTH_C = 13 # SDRAM-side address width. 14 | SDRAM_T_INIT_C = 20000.0 #200000.0 # Min initialization interval (ns). 15 | SDRAM_T_RAS_C = 45.0 # Min interval between active to precharge commands (ns). 16 | SDRAM_T_RCD_C = 20.0 # Min interval between active and R/W commands (ns). 17 | SDRAM_T_REF_C = 64000000.0 # Maximum refresh interval (ns). 18 | SDRAM_T_RFC_C = 65.0 # Duration of refresh operation (ns). 19 | SDRAM_T_RP_C = 20.0 # Min precharge command duration (ns). 20 | SDRAM_T_XSR_C = 75.0 # Exit self-refresh time (ns). 21 | 22 | SDRAM_FREQ_C = 100.0 # Operating frequency in MHz. 23 | SDRAM_IN_PHASE_C = True # SDRAM and controller XESS on same or opposite clock edge. 24 | SDRAM_PIPE_EN_C = False # If true, enable pipelined read operations. 25 | SDRAM_ENABLE_REFRESH_C = True # If true, row refreshes are automatically inserted. 26 | SDRAM_MULTIPLE_ACTIVE_ROWS_C = False # If true, allow an active row in each bank. 27 | SDRAM_MAX_NOP_C = 10000 # Number of NOPs before entering self-refresh. 28 | SDRAM_BEG_ADDR_C = 16 #00_0000#; -- Beginning SDRAM address. 29 | SDRAM_END_ADDR_C = 16 #FF_FFFF#; -- Ending SDRAM address. 30 | 31 | SDRAM_NOP_CMD_C = intbv("0111")[4:] #0,1,1,1,0,0 32 | SDRAM_ACTIVE_CMD_C = intbv("0011")[4:] #0,0,1,1,0,0 33 | SDRAM_READ_CMD_C = intbv("0101")[4:] # 0,1,0,1,0,0 34 | SDRAM_WRITE_CMD_C = intbv("0100")[4:] # 0,1,0,0,0,0 35 | SDRAM_PCHG_CMD_C = intbv("0010")[4:] # 0,0,1,0,0,0 36 | SDRAM_MODE_CMD_C = intbv("0000")[4:] # 0,0,0,0,0,0 37 | SDRAM_RFSH_CMD_C = intbv("0001")[4:] # 0,0,0,1,0,0 38 | SDRAM_MODE_C = intbv("00_0_00_011_0_000")[12:] # mode command for set_mode command 39 | 40 | SDRAM_ALL_BANKS_C = intbv("001000000000")[12:] # value of CMDBIT to select all banks 41 | SDRAM_ONE_BANK_C = intbv("000000000000")[12:] 42 | 43 | timing = { # timing details refer data sheet 44 | 'init' : 100, # min init interval 45 | 'ras' : 10, # min interval between active prechargs 46 | 'rcd' : 10, # min interval between active R/W 47 | 'cas' : 20, 48 | 'ref' : 64000000, # max refresh interval 49 | 'rfc' : 65, # refresh opertaion 50 | 'rp' : 20, # min precharge 51 | 'xsr' : 75, # exit self-refresh time 52 | 'wr' : 55, # @todo ... 53 | } 54 | 55 | def __init__(self): 56 | 57 | self.cke = Signal(bool(0)) 58 | self.cs = Signal(bool(0)) 59 | self.cas = Signal(bool(0)) 60 | self.ras = Signal(bool(0)) 61 | self.we = Signal(bool(0)) 62 | self.bs = Signal(intbv(0)[2:]) 63 | self.addr = Signal(intbv(0)[self.addr_width:]) 64 | self.dqml = Signal(bool(0)) 65 | self.dqmh = Signal(bool(0)) 66 | self.dq = TristateSignal(intbv(0)[self.data_width:]) 67 | 68 | # Written below are transactors for passing commands to sdram 69 | 70 | def nop(self,clk): 71 | # [NOP] cs ras cas we : L H H H 72 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,1,1 73 | yield clk.posedge 74 | 75 | def activate(self,clk,row_addr,bank_id=0): 76 | self.bs.next = bank_id 77 | self.addr.next = row_addr 78 | # [ACTIVE] cs ras cas we : L L H H 79 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,1,1 80 | yield clk.posedge 81 | 82 | def loadMode(self,clk,mode='burst',cas=3,burst=1): 83 | addr = 0 84 | if(mode.lower() == 'single'): 85 | addr = addr + 2**9 86 | addr = addr + cas*(2**4) 87 | addr = addr + int(log(burst,2)) 88 | self.addr.next = addr 89 | # [LOAD_MODE] cs ras cas we dqm : L L L L X 90 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,0,0 91 | yield clk.posedge 92 | yield clk.posedge 93 | 94 | def precharge(self,clk,bank_id=None): 95 | if(bank_id == None): # precharge all banks 96 | self.addr.next = 2**10 # A10 is high 97 | else: 98 | self.addr.next = 0 99 | self.bs.next = bank_id 100 | # [PRECHARGE] cs ras cas we : L L H L 101 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,1,0 102 | yield clk.posedge 103 | 104 | def read(self,clk,addr,bank_id=0): 105 | self.bs.next = bank_id 106 | self.addr.next = addr 107 | # [READ] # cs ras cas we dqm : L H L H X 108 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,0,1 109 | yield clk.posedge 110 | yield clk.posedge 111 | 112 | def write(self,clk,driver,addr,value,bank_id=0): 113 | self.bs.next = bank_id 114 | self.addr.next = addr 115 | driver.next = value 116 | # [WRITE] # cs ras cas we dqm : L H L L X 117 | self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,0,0 118 | yield clk.posedge 119 | yield clk.posedge 120 | driver.next = None 121 | 122 | def getDriver(self): 123 | return self.dq.driver() 124 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/sdram.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from __future__ import print_function 3 | from __future__ import absolute_import 4 | from future import standard_library 5 | standard_library.install_aliases() 6 | from builtins import object 7 | from past.utils import old_div 8 | 9 | from myhdl import * 10 | from .sd_intf import sd_intf 11 | from math import ceil 12 | 13 | commands = enum("COM_INHIBIT","NOP","ACTIVE","READ","WRITE","BURST_TERM", \ 14 | "PRECHARGE","AUTO_REFRESH","LOAD_MODE","OUTPUT_EN","OUTPUT_Z","INVALID") 15 | 16 | states = enum("Uninitialized","Initialized","Idle","Activating","Active","Read","Reading","Read_rdy","Write","Writing") 17 | 18 | # generic parameters 19 | FREQ_GHZ_G = old_div(sd_intf.SDRAM_FREQ_C, 1000) 20 | ENABLE_REFRESH_G = True 21 | NROWS_G = sd_intf.SDRAM_NROWS_C 22 | T_REF_G = sd_intf.SDRAM_T_REF_C 23 | T_INIT_G = sd_intf.SDRAM_T_INIT_C # min initialization interval (ns). 24 | T_RAS_G = sd_intf.SDRAM_T_RAS_C # min interval between active to precharge commands (ns). 25 | T_RCD_G = sd_intf.SDRAM_T_RCD_C # min interval between active and R/W commands (ns). 26 | T_REF_G = sd_intf.SDRAM_T_REF_C # maximum refresh interval (ns). 27 | T_RFC_G = sd_intf.SDRAM_T_RFC_C # duration of refresh operation (ns). 28 | T_RP_G = sd_intf.SDRAM_T_RP_C # min precharge command duration (ns). 29 | T_XSR_G = sd_intf.SDRAM_T_XSR_C # exit self-refresh time (ns). 30 | 31 | # delay constants 32 | INIT_CYCLES_C = int(ceil(T_INIT_G * FREQ_GHZ_G)) 33 | RP_CYCLES_C = int(ceil(T_RP_G * FREQ_GHZ_G)) 34 | RFC_CYCLES_C = int(ceil(T_RFC_G * FREQ_GHZ_G)) 35 | REF_CYCLES_C = int(ceil(T_REF_G * FREQ_GHZ_G / NROWS_G)) 36 | RCD_CYCLES_C = int(ceil(T_RCD_G * FREQ_GHZ_G/10)) 37 | RAS_CYCLES_C = int(ceil(T_RAS_G * FREQ_GHZ_G)) 38 | MODE_CYCLES_C = 2 39 | CAS_CYCLES_C = 3 40 | #CAS_CYCLES_C = 4 41 | WR_CYCLES_C = 2 42 | RFSH_OPS_C = 8 # number of refresh operations needed to init SDRAM. 43 | 44 | # show_state and show_command are variables to show/hide log messages 45 | def sdram(clk,sd_intf,show_command=False): 46 | 47 | #data = sd_intf.dq.driver() # driver for bidirectional DQ port 48 | 49 | curr_command = Signal(commands.INVALID) 50 | control_logic_inst = Control_Logic(curr_command,sd_intf) 51 | 52 | curr_state = [ State(0,sd_intf), State(1,sd_intf), State(2,sd_intf), State(3,sd_intf) ] # Represents the state of eah bank 53 | 54 | # refresh variables 55 | REF_CYCLES_C = int(old_div(sd_intf.timing['ref'], sd_intf.SDRAM_FREQ_C) ) 56 | RFSH_COUNT_C = sd_intf.SDRAM_NROWS_C 57 | rfsh_timer = Signal(modbv(1,min=0,max=REF_CYCLES_C)) 58 | rfsh_count = Signal(intbv(0,min=0,max=RFSH_COUNT_C)) 59 | 60 | @always(clk.posedge) 61 | def main_function(): 62 | if(sd_intf.cke == 1): 63 | if(show_command) : 64 | print((" SDRAM : [COMMAND] ", curr_command)) 65 | 66 | #for bank_state in curr_state : 67 | # bank_state.nextState(curr_command) 68 | 69 | for i in range(len(curr_state)): 70 | curr_state[i].nextState(curr_command) 71 | 72 | if(curr_command == commands.INVALID): 73 | print(" SDRAM : [ERROR] Invalid command is given") 74 | elif(curr_command == commands.LOAD_MODE): 75 | # pass 76 | # load_mode(sd_intf.bs,sd_intf.addr) 77 | bs = sd_intf.bs 78 | addr = sd_intf.addr 79 | mode = None 80 | cas = int(addr[7:4]) 81 | burst = 2 ** int(addr[3:0]) 82 | if(addr[9] == 1): 83 | mode = "Single " 84 | else: 85 | mode = "Burst " 86 | print("--------------------------") 87 | print(" Mode | CAS | Burst ") 88 | print("--------|-------|---------") 89 | print(" %s| %i | %i " % (mode,cas,burst)) 90 | print("--------------------------") 91 | elif(curr_command == commands.ACTIVE): 92 | # activate(sd_intf.bs,sd_intf.addr) 93 | bs = sd_intf.bs 94 | addr = sd_intf.addr 95 | if(curr_state[bs.val].active_row != None): 96 | print(" SDRAM : [ERROR] A row is already activated. Bank should be precharged first") 97 | return None 98 | if(curr_state[bs.val].getState() == states.Uninitialized): 99 | print(" SDRAM : [ERROR] Bank is not in a good state. Too bad for you") 100 | return None 101 | curr_state[bs.val].active_row = addr.val 102 | print(" SDRAM : Bank {} has active row {}".format(bs.val, addr.val)) 103 | elif(curr_command == commands.READ): 104 | # read(sd_intf.bs,sd_intf.addr) 105 | bs = sd_intf.bs 106 | addr = sd_intf.addr 107 | if(curr_state[bs.val].active_row == None): 108 | print(" SDRAM : [ERROR] A row should be activated before trying to read") 109 | else: 110 | print(" SDRAM : [READ] Commnad registered ") 111 | elif(curr_command == commands.WRITE): 112 | # write(sd_intf.bs,sd_intf.addr) 113 | bs = sd_intf.bs 114 | addr = sd_intf.addr 115 | if(curr_state[bs.val].active_row == None): 116 | print(" SDRAM : [ERROR] A row should be activated before trying to write") 117 | elif(curr_command == commands.PRECHARGE): 118 | # precharge(sd_intf.bs,sd_intf.addr) 119 | bs = sd_intf.bs 120 | addr = sd_intf.addr 121 | if(addr.val[10] == 1): # Precharge all banks command 122 | # for bank_state in curr_state : 123 | # bank_state.active_row = None 124 | for i in range(len(curr_state)): 125 | curr_state[i].active_row = None 126 | else: # Precharge selected bank 127 | curr_state[bs.val].active_row = None 128 | elif(curr_command == commands.AUTO_REFRESH): 129 | rfsh_count.next = rfsh_count + 1 if rfsh_timer != 0 else 0 130 | 131 | rfsh_timer.next = (rfsh_timer + 1) 132 | if rfsh_timer == 0 : 133 | if rfsh_count < RFSH_COUNT_C : 134 | print( " SDRAM : [ERROR] Refresh requirement is not met" ) 135 | 136 | @always(clk.negedge) 137 | def read_function(): 138 | i = int(sd_intf.bs.val) 139 | if curr_state[i].state == states.Read_rdy or curr_state[i].state == states.Reading: 140 | curr_state[i].driver.next = curr_state[i].data 141 | else: 142 | curr_state[i].driver.next = None 143 | # bank_state = curr_state[sd_intf.bs.val] 144 | # if(bank_state.state == states.Read_rdy or bank_state.state == states.Reading): 145 | # bank_state.driver.next = bank_state.data 146 | # #print "debug ",bank_state.data 147 | # else: 148 | # bank_state.driver.next = None 149 | 150 | def load_mode(bs,addr): 151 | mode = None 152 | cas = int(addr[7:4]) 153 | burst = 2 ** int(addr[3:0]) 154 | if(addr[9] == 1): 155 | mode = "Single " 156 | else: 157 | mode = "Burst " 158 | print("--------------------------") 159 | print(" Mode | CAS | Burst ") 160 | print("--------|-------|---------") 161 | print(" %s| %i | %i " % (mode,cas,burst)) 162 | print("--------------------------") 163 | 164 | def activate(bs,addr): 165 | if(curr_state[bs.val].active_row != None): 166 | print(" SDRAM : [ERROR] A row is already activated. Bank should be precharged first") 167 | return None 168 | if(curr_state[bs.val].getState() == states.Uninitialized): 169 | print(" SDRAM : [ERROR] Bank is not in a good state. Too bad for you") 170 | return None 171 | curr_state[bs.val].active_row = addr.val 172 | 173 | def read(bs,addr): 174 | if(curr_state[bs.val].active_row == None): 175 | print(" SDRAM : [ERROR] A row should be activated before trying to read") 176 | else: 177 | print(" SDRAM : [READ] Commnad registered ") 178 | 179 | def write(bs,addr): 180 | if(curr_state[bs.val].active_row == None): 181 | print(" SDRAM : [ERROR] A row should be activated before trying to write") 182 | 183 | def precharge(bs,addr): 184 | if(addr.val[10] == 1): # Precharge all banks command 185 | for bank in curr_state : 186 | bank.active_row = None 187 | else: # Precharge selected bank 188 | curr_state[bs.val].active_row = None 189 | 190 | return instances() 191 | 192 | def Control_Logic(curr_command,sd_intf): 193 | 194 | @always_comb 195 | def decode(): 196 | # detect the registered command 197 | if(sd_intf.cs == 1): 198 | # cs ras cas we dqm : H X X X X 199 | curr_command.next = commands.COM_INHIBIT 200 | else: 201 | if(sd_intf.ras == 1): 202 | if(sd_intf.cas == 1): 203 | if(sd_intf.we == 1): 204 | # cs ras cas we dqm : L H H H X 205 | curr_command.next = commands.NOP 206 | else: 207 | # cs ras cas we dqm : L H H L X 208 | curr_command.next = commands.BURST_TERM 209 | else: 210 | if(sd_intf.we == 1): 211 | # cs ras cas we dqm : L H L H X 212 | curr_command.next = commands.READ 213 | else: 214 | # cs ras cas we dqm : L H L L X 215 | curr_command.next = commands.WRITE 216 | else: 217 | if(sd_intf.cas == 1): 218 | if(sd_intf.we == 1): 219 | # cs ras cas we dqm : L L H H X 220 | curr_command.next = commands.ACTIVE 221 | else: 222 | # cs ras cas we dqm : L L H L X 223 | curr_command.next = commands.PRECHARGE 224 | else: 225 | if(sd_intf.we == 1): 226 | # cs ras cas we dqm : L L L H X 227 | curr_command.next = commands.AUTO_REFRESH 228 | else: 229 | # cs ras cas we dqm : L L L L X 230 | curr_command.next = commands.LOAD_MODE 231 | 232 | return decode 233 | 234 | class State(object): 235 | 236 | def __init__(self,bank_id,sd_intf,regFile={}): 237 | self.state = states.Uninitialized 238 | self.init_time = now() 239 | self.wait = 0 240 | self.bank_id = bank_id 241 | self.memory = regFile 242 | # self.memory = {} 243 | self.sd_intf = sd_intf 244 | self.driver = sd_intf.dq.driver() 245 | self.active_row = None 246 | self.addr = None 247 | self.data = None 248 | self.tick = 0 249 | 250 | def nextState(self,curr_command): 251 | #print('{} : {} : {}'.format(self.bank_id,self.active_row,self.addr)) 252 | self.wait = self.wait + 1 253 | if(self.state == states.Uninitialized): 254 | if(self.wait >= INIT_CYCLES_C): 255 | print(" BANK",self.bank_id,"STATE : [CHANGE] Uninitialized -> Initialized @ ", now()) 256 | self.state = states.Initialized 257 | #self.init_time = now( 258 | #self.driver.next = 45 259 | self.wait = 0 260 | 261 | elif(self.state == states.Idle or self.state == states.Initialized): 262 | self.data = 0 263 | # Reading command 264 | if(curr_command == commands.READ and self.bank_id == self.sd_intf.bs.val): 265 | print(" BANK",self.bank_id,"STATE : READING @ ", now()) 266 | self.state = states.Reading 267 | #self.init_time = now() 268 | self.wait = 0 269 | if(self.sd_intf != None): 270 | self.addr = int(self.sd_intf.addr.val) 271 | # Writing command 272 | elif(curr_command == commands.WRITE and self.bank_id == self.sd_intf.bs.val): 273 | print(" BANK",self.bank_id,"STATE : WRITING @ ", now()) 274 | self.state = states.Writing 275 | #self.init_time = now() 276 | self.wait = 0 277 | if(self.sd_intf != None): 278 | self.addr = int(self.sd_intf.addr.val) 279 | self.data = int(self.sd_intf.dq.val) 280 | 281 | elif(self.state == states.Reading): 282 | #self.data = self.memory[self.active_row * 10000 + self.addr] 283 | if(self.wait >= CAS_CYCLES_C - 1): 284 | self.state = states.Read_rdy 285 | #self.init_time = now() 286 | self.wait = 0 287 | if(self.active_row != None): 288 | print(" BANK {} STATE : READING FROM {}:{}".format(self.bank_id,self.active_row,self.addr)) 289 | self.data = self.memory[self.active_row * 10000 + self.addr] 290 | print(" STATE : [READ] Data Ready @ ", now(), " value : ",self.data) 291 | 292 | elif(self.state == states.Read_rdy): 293 | self.state = states.Idle 294 | #self.init_time = now() 295 | self.wait = 0 296 | # self.driver.next = None 297 | # self.driver.next = self.data 298 | 299 | elif(self.state == states.Writing): 300 | if(self.wait >= RCD_CYCLES_C): 301 | self.state = states.Idle 302 | #self.init_time = now() 303 | self.wait = 0 304 | if(self.active_row != None): 305 | print(" DATA : [WRITE] Addr:",self.addr," Data:",self.data) 306 | print(" BANK {} STATE : WRITING TO {}:{}".format(self.bank_id,self.active_row,self.addr)) 307 | self.memory[self.active_row * 10000 + self.addr] = self.data 308 | for a,d in self.memory.items(): 309 | print('{}: {}'.format(a,d)) 310 | 311 | def getState(self): 312 | return self.state 313 | 314 | def getData(self): 315 | return self.data 316 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/test_controller.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | from SdramCntl import * 3 | from Clk import * 4 | from sdram import * 5 | from host_intf import * 6 | from sd_intf import * 7 | 8 | def test_readWrite(host_intf,sd_intf): 9 | 10 | @instance 11 | def test(): 12 | yield delay(140) 13 | yield host_intf.write(120,23) 14 | yield host_intf.done_o.posedge 15 | yield host_intf.nop() 16 | yield delay(5) 17 | yield host_intf.read(120) 18 | yield host_intf.done_o.posedge 19 | 20 | print "Data Value : ",host_intf.data_o," clk : ",now() 21 | return test 22 | 23 | clk_i = Signal(bool(0)) 24 | rst_i = ResetSignal(0,active=1,isasync=True) 25 | 26 | clkDriver_Inst = clkDriver(clk_i) 27 | sd_intf_Inst = sd_intf() 28 | host_intf_Inst = host_intf() 29 | 30 | sdram_Inst = sdram(clk_i,sd_intf_Inst,show_command=False) 31 | sdramCntl_Inst = MySdramCntl(clk_i,host_intf_Inst,sd_intf_Inst) 32 | #sdramCntl_Inst = traceSignals(MySdramCntl,host_intf_Inst,sd_intf_Inst) 33 | 34 | test_readWrite_Inst = test_readWrite(host_intf_Inst,sd_intf_Inst) 35 | 36 | sim = Simulation(clkDriver_Inst,sdram_Inst,sdramCntl_Inst,test_readWrite_Inst) 37 | sim.run(7500) 38 | -------------------------------------------------------------------------------- /tests/SDRAM_Controller/test_sdram.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | from Clk import clkDriver 3 | from sd_intf import sd_intf 4 | from sdram import sdram 5 | 6 | def test_readWrite(clk,sd_intf): 7 | 8 | driver = sd_intf.getDriver() 9 | 10 | @instance 11 | def test(): 12 | 13 | sd_intf.cke.next = 1 14 | 15 | yield sd_intf.nop(clk) 16 | yield delay(10000) 17 | yield sd_intf.loadMode(clk) 18 | yield sd_intf.nop(clk) 19 | yield sd_intf.activate(clk,17) 20 | yield sd_intf.nop(clk) 21 | yield delay(10000) 22 | 23 | yield sd_intf.write(clk,driver,20,31) 24 | 25 | #yield delay(5) 26 | yield sd_intf.nop(clk) 27 | yield delay(100) 28 | yield sd_intf.read(clk,20) 29 | #yield delay(10) 30 | yield sd_intf.nop(clk) 31 | yield delay(4) 32 | print "sd_intf dq = ",sd_intf.dq.val," @ ",now() 33 | 34 | return test 35 | 36 | clk = Signal(bool(0)) 37 | 38 | clkDriver_Inst = clkDriver(clk) 39 | sd_intf_Inst = sd_intf() 40 | sdram_Inst = sdram(clk,sd_intf_Inst) 41 | test_readWrite_Inst = test_readWrite(clk,sd_intf_Inst) 42 | 43 | sim = Simulation(clkDriver_Inst,sdram_Inst,test_readWrite_Inst) 44 | sim.run(25000) 45 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | __author__ = 'XESS Corp.' 4 | __email__ = 'info@xess.com' 5 | __version__ = '0.1.0' 6 | -------------------------------------------------------------------------------- /tests/buttons_display.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2015 by XESS Corporation 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from myhdl import * 24 | from led_digits_display import * 25 | from ice40_primitives import * 26 | 27 | 28 | def buttons_display(d0_o, d1_o, d2_o, d3_o, d4_o, d5_o, d6_o, d7_o, clk_i, 29 | sw1_i, sw2_i, sw3_i): 30 | '''Module for testing buttons and DIP switches. 31 | d0_o, ... d7_o: 3-state outputs to drive the StickIt! LEDDigits board. 32 | clk_i: Input clock. 33 | sw1_i, sw2_i: Pushbutton inputs. 34 | sw3_i: DIP switch input (4 bits). 35 | ''' 36 | 37 | # Internal versions of the switch inputs. 38 | sw1, sw2 = [Signal(bool(0)) for _ in range(2)] 39 | sw3 = Signal(intbv(0)[len(sw3_i):]) 40 | 41 | # Use input pins with pullups enabled to get the switch inputs to their internal versions. 42 | sw1_inst = input_pin(sw1_i, sw1, pullup=True) 43 | sw2_inst = input_pin(sw2_i, sw2, pullup=True) 44 | sw3_inst = input_pin(sw3_i, sw3, pullup=True) 45 | 46 | # Signals for holding 7-segment LED digit values. 47 | sw1_digit, sw2_digit = [Signal(intbv(0)[7:]) for _ in range(2)] 48 | space = 0x20 # ASCII code for a blank space. (LED digit will be OFF.) 49 | 50 | # Unpressed pushbuttons will be read as high inputs because of the pullups. 51 | # When high, the hex value of the four DIP switch inputs will be displayed. 52 | # When the pushbutton is pressed, its input pin is pulled low and the 53 | # digit will display a space. 54 | @always_comb 55 | def sw_logic(): 56 | if sw1 == 1: 57 | sw1_digit.next[4:0] = sw3 58 | sw1_digit.next[7:4] = 0 59 | else: 60 | sw1_digit.next[7:0] = space 61 | if sw2 == 1: 62 | sw2_digit.next[4:0] = sw3 63 | sw2_digit.next[7:4] = 0 64 | else: 65 | sw2_digit.next[7:0] = space 66 | 67 | # Attach the hex digit code for SW1 to the first LED digit, and the 68 | # code for SW2 to the last digit of the LED display. 69 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] 70 | display = led_digits_display(drvrs[0], drvrs[1], drvrs[2], drvrs[3], 71 | drvrs[4], drvrs[5], drvrs[6], drvrs[7], clk_i, 72 | sw1_digit, space, space, space, space, space, 73 | space, sw2_digit) 74 | 75 | # Attach the LEDDigits drivers to the output pins of this module. 76 | @always_comb 77 | def io_logic(): 78 | d0_o.next = drvrs[0] 79 | d1_o.next = drvrs[1] 80 | d2_o.next = drvrs[2] 81 | d3_o.next = drvrs[3] 82 | d4_o.next = drvrs[4] 83 | d5_o.next = drvrs[5] 84 | d6_o.next = drvrs[6] 85 | d7_o.next = drvrs[7] 86 | 87 | return instances() 88 | 89 | 90 | def buttons_display_tb(): 91 | '''Testbench for the switch tester.''' 92 | d0, d1, d2, d3, d4, d5, d6, d7 = [TristateSignal(bool(0)) 93 | for _ in range(8)] 94 | clk, sw1, sw2 = [Signal(bool(0)) for _ in range(3)] 95 | sw3 = Signal(intbv(0)[4:]) 96 | 97 | dut = buttons_display(d0.driver(), d1.driver(), d2.driver(), d3.driver(), 98 | d4.driver(), d5.driver(), d6.driver(), d7.driver(), 99 | clk, sw1, sw2, sw3) 100 | 101 | @always(delay(10)) 102 | def clk_gen(): 103 | clk.next = not clk 104 | 105 | @instance 106 | def stimulus(): 107 | sw3.next = 0xA 108 | sw1.next = 0 109 | sw2.next = 1 110 | yield delay(1000000) 111 | raise StopSimulation 112 | 113 | return instances() 114 | 115 | # Main routine that does simulation and Verilog conversion. 116 | if __name__ == '__main__': 117 | 118 | Simulation(traceSignals(buttons_display_tb)).run() 119 | 120 | d0, d1, d2, d3, d4, d5, d6, d7 = [TristateSignal(bool(0)) 121 | for _ in range(8)] 122 | clk, sw1, sw2 = [Signal(bool(0)) for _ in range(3)] 123 | sw3 = Signal(intbv(0)[4:]) 124 | toVerilog(buttons_display, d0.driver(), d1.driver(), d2.driver(), 125 | d3.driver(), d4.driver(), d5.driver(), d6.driver(), d7.driver(), 126 | clk, sw1, sw2, sw3) 127 | -------------------------------------------------------------------------------- /tests/config_cat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A script to configure Lattice iCE40 FPGA by SPI from Raspberry Pi 4 | # 5 | # Copyright (C) 2015 Jan Marjanovic 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | 21 | echo "" 22 | if [ $# -ne 1 ]; then 23 | echo "Usage: $0 FPGA-bin-file " 24 | exit 1 25 | fi 26 | 27 | if [ $EUID -ne 0 ]; then 28 | echo "This script must be run as root" 1>&2 29 | exit 1 30 | fi 31 | 32 | 33 | if [ ! -d /sys/class/gpio/gpio25 ]; then 34 | echo "GPIO 25 not exported, trying to export..." 35 | echo 25 > /sys/class/gpio/export 36 | if [ ! -d /sys/class/gpio/gpio25 ]; then 37 | echo "ERROR: directory /sys/class/gpio/gpio25 does not exist" 38 | exit 1 39 | fi 40 | else 41 | echo "OK: GPIO 25 exported" 42 | fi 43 | 44 | if [ ! -d /sys/class/gpio/gpio17 ]; then 45 | echo "GPIO 17 not exported, trying to export..." 46 | echo 17 > /sys/class/gpio/export 47 | if [ ! -d /sys/class/gpio/gpio17 ]; then 48 | echo "ERROR: directory /sys/class/gpio/gpio17 does not exist" 49 | exit 1 50 | fi 51 | else 52 | echo "OK: GPIO 17 exported" 53 | fi 54 | 55 | if [ ! -d /sys/class/gpio/gpio22 ]; then 56 | echo "GPIO 22 not exported, trying to export..." 57 | echo 22 > /sys/class/gpio/export 58 | if [ ! -d /sys/class/gpio/gpio22 ]; then 59 | echo "ERROR: directory /sys/class/gpio/gpio22 does not exist" 60 | exit 1 61 | fi 62 | else 63 | echo "OK: GPIO 22 exported" 64 | fi 65 | 66 | echo "" 67 | if [ -e /dev/spidev0.0 ]; then 68 | echo "OK: SPI driver loaded" 69 | else 70 | echo "spidev does not exist" 71 | 72 | lsmod | grep spi_bcm2708 >& /dev/null 73 | 74 | if [ $? -ne 0 ]; then 75 | echo "SPI driver not loaded, try to load it..." 76 | modprobe spi_bcm2708 77 | 78 | if [ $? -eq 0 ]; then 79 | echo "OK: SPI driver loaded" 80 | else 81 | echo "Could not load SPI driver" 82 | exit 1 83 | fi 84 | fi 85 | fi 86 | 87 | echo "" 88 | echo "Setting GPIO directions" 89 | echo out > /sys/class/gpio/gpio25/direction 90 | cat /sys/class/gpio/gpio25/direction 91 | echo out > /sys/class/gpio/gpio22/direction 92 | cat /sys/class/gpio/gpio22/direction 93 | echo in > /sys/class/gpio/gpio17/direction 94 | cat /sys/class/gpio/gpio17/direction 95 | 96 | echo "Setting output to low" 97 | echo 0 > /sys/class/gpio/gpio25/value 98 | cat /sys/class/gpio/gpio25/value 99 | 100 | #echo "" 101 | #echo "Please reset the iCE40 FPGA board" 102 | #echo "Press any key..." 103 | #read 104 | 105 | echo "Reseting FPGA" 106 | echo 0 > /sys/class/gpio/gpio22/value 107 | cat /sys/class/gpio/gpio22/value 108 | echo 1 > /sys/class/gpio/gpio22/value 109 | cat /sys/class/gpio/gpio22/value 110 | 111 | echo "Checking DONE pin" 112 | cat /sys/class/gpio/gpio17/value 113 | 114 | echo "Continuing with configuration procedure" 115 | dd if=$1 of=/dev/spidev0.0 116 | 117 | echo -e "\x0\x0\x0\x0\x0\x0\x0" > /dev/spidev0.0 118 | 119 | echo "Setting output to high" 120 | echo 1 > /sys/class/gpio/gpio25/value 121 | cat /sys/class/gpio/gpio25/value 122 | 123 | echo "Checking DONE pin" 124 | cat /sys/class/gpio/gpio17/value 125 | -------------------------------------------------------------------------------- /tests/ex_catboard_buttons.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2015 by XESS Corp. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | import rhea.build as build 24 | from rhea.build.boards import get_board 25 | from buttons_display import buttons_display 26 | 27 | 28 | def run_catboard(): 29 | # Get the CAT Board object. 30 | brd = get_board('catboard') 31 | # Add the ports and pin assignments for PMOD socket PM3. 32 | brd.add_port('d0_o', 'A11') 33 | brd.add_port('d1_o', 'B10') 34 | brd.add_port('d2_o', 'B12') 35 | brd.add_port('d3_o', 'B11') 36 | brd.add_port('d4_o', 'B14') 37 | brd.add_port('d5_o', 'B13') 38 | brd.add_port('d6_o', 'B15') 39 | brd.add_port('d7_o', 'A15') 40 | # Add the clock port to the 100 MHz on-board oscillator. 41 | brd.add_clock('clk_i', 1e8, 'C8') 42 | # Add the ports to the pushbuttons. 43 | brd.add_port('sw1_i', 'A16', PULLUP='PULLUP') 44 | brd.add_port('sw2_i', 'B9', PULLUP='PULLUP') 45 | # Add the four-bit port to the DIP switch. 46 | brd.add_port('sw3_i', ('C6', 'C5', 'C4', 'C3'), PULLUP='PULLUP') 47 | # Run the MyHDL+yosys+arachne-pnr design tools on the top-level module. 48 | flow = brd.get_flow(top=buttons_display) 49 | flow.run() 50 | 51 | 52 | if __name__ == '__main__': 53 | run_catboard() 54 | -------------------------------------------------------------------------------- /tests/ex_catboard_leddisp.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2015 by XESS Corp. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | import rhea.build as build 24 | from rhea.build.boards import get_board 25 | from led_digits_display import led_digits_cnt, led_digits_scroll 26 | 27 | 28 | def run_catboard(): 29 | # Get the CAT Board object. 30 | brd = get_board('catboard') 31 | # Add the ports and pin assignments for PMOD socket PM3. 32 | brd.add_port('d0_o', 'A11') 33 | brd.add_port('d1_o', 'B10') 34 | brd.add_port('d2_o', 'B12') 35 | brd.add_port('d3_o', 'B11') 36 | brd.add_port('d4_o', 'B14') 37 | brd.add_port('d5_o', 'B13') 38 | brd.add_port('d6_o', 'B15') 39 | brd.add_port('d7_o', 'A15') 40 | # Add the clock port to the 100 MHz on-board oscillator. 41 | brd.add_clock('clk_i', 1e8, 'C8') 42 | # Run the MyHDL+yosys+arachne-pnr design tools on the top-level module. 43 | # Use 'top = led_digits_cnt' to display a counter. 44 | # Use 'top = led_digits_scroll' to display a scrolling string of digits. 45 | flow = brd.get_flow(top=led_digits_cnt) 46 | flow.run() 47 | 48 | 49 | if __name__ == '__main__': 50 | run_catboard() 51 | -------------------------------------------------------------------------------- /tests/ex_catboard_sdram.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2016 by XESS Corp. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | import rhea.build as build 24 | from rhea.build.boards import get_board 25 | from sdram_test import sdram_test 26 | from SDRAM_Controller.sd_intf import * 27 | 28 | 29 | def run_catboard(): 30 | # Get the CAT Board object. 31 | brd = get_board('catboard') 32 | # Add the ports and pin assignments for PMOD socket PM3. 33 | brd.add_port('d0_o', 'A11') 34 | brd.add_port('d1_o', 'B10') 35 | brd.add_port('d2_o', 'B12') 36 | brd.add_port('d3_o', 'B11') 37 | brd.add_port('d4_o', 'B14') 38 | brd.add_port('d5_o', 'B13') 39 | brd.add_port('d6_o', 'B15') 40 | brd.add_port('d7_o', 'A15') 41 | # Add the clock port to the 100 MHz on-board oscillator. 42 | brd.add_clock('master_clk_i', 1e8, 'C8') 43 | # Route clocks to/from the SDRAM. 44 | brd.add_port('sdram_clk_o', 'G16') 45 | brd.add_clock('sdram_clk_i', 1e8, 'H16') 46 | # Add the ports to the pushbuttons. 47 | brd.add_port('pb_i', 'A16', PULLUP='PULLUP') 48 | # Add the connections to the SDRAM. 49 | brd.add_port('sdintf.cke', 'G15') 50 | brd.add_port('sdintf.cs', 'H13') 51 | brd.add_port('sdintf.cas', 'K15') 52 | brd.add_port('sdintf.ras', 'K16') 53 | brd.add_port('sdintf.we', 'J14') 54 | brd.add_port('sdintf.bs', ('H14','G13')) 55 | brd.add_port('sdintf.addr', ('F13','E14','E13','D14','B16','C16','D15','D16','E16','F15','F14','F16','G14')) 56 | brd.add_port('sdintf.dqml', 'J13') 57 | brd.add_port('sdintf.dqmh', 'J15') 58 | brd.add_port('sdintf.dq', ('R14','P14','M13','M14','L13','L14','K13','K14','J16','L16','M16','M15','N16','P16','P15','R15')) 59 | # Run the MyHDL+yosys+arachne-pnr design tools on the top-level module. 60 | flow = brd.get_flow(top=sdram_test) 61 | flow.run() 62 | 63 | 64 | if __name__ == '__main__': 65 | run_catboard() 66 | -------------------------------------------------------------------------------- /tests/ice40_primitives.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2015 by XESS Corporation 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from myhdl import * 24 | 25 | inst_num = 0 # Incrementing index for making unique Verilog instantiation names. 26 | 27 | 28 | def input_pin(i, o, pullup=False): 29 | '''Input pin module with integrated pullup enable. 30 | i: Input signal (either scalar or vector) from pin. 31 | o: Input signal passed to the internal LUTs of the FPGA. 32 | pullup: Set to True to turn on integrated pullups for this input 33 | ''' 34 | 35 | # Code for simulating the input pin. 36 | @always_comb 37 | def in_to_out(): 38 | o.next = i # Just pass the value on the input pin to the output. 39 | 40 | # The rest is for instantiating the synthesizable Verilog block for the input pin. 41 | 42 | # Create the Verilog vector index if a vector input is used. 43 | vector = '' 44 | if len(i) > 1: 45 | vector = '[{}:{}]'.format(len(i) - 1, 0) 46 | 47 | # Set the pullup bit. 48 | pup = 0 49 | if pullup != False: 50 | pup = 1 51 | 52 | # Tell MyHDL that the I/O pins of this module are connected since it can't interpret the verilog_code string. 53 | i.driven = True 54 | o.driven = True 55 | 56 | # Increment the Verilog instantiation index. 57 | global inst_num 58 | inst_num += 1 59 | 60 | return instances() 61 | 62 | # This is the Verilog code that gets inserted for the input pin when the MyHDL is converted to Verilog. 63 | # The values of vector, pup, inst_num, i and o are inserted into the string. 64 | input_pin.verilog_code = \ 65 | """ 66 | SB_IO #( 67 | .PIN_TYPE(6'b000001), 68 | .PULLUP(1'b$pup) 69 | ) input_pin_$inst_num $vector ( 70 | .PACKAGE_PIN($i), 71 | .D_IN_0($o) 72 | ); 73 | """ 74 | -------------------------------------------------------------------------------- /tests/lattice_sdram_test/sdram_test/sdram_test_Implmnt/sbt/constraint/sdram_test_pcf_sbt.pcf: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | 3 | # iCEcube PCF 4 | 5 | # Version: 2015.08.27744 6 | 7 | # File Generated: Feb 7 2016 11:06:54 8 | 9 | # Family & Device: iCE40HX8K 10 | 11 | # Package: CT256 12 | 13 | # ############################################################################## 14 | 15 | ###IOSet List 54 16 | set_io led_status[3] B7 17 | set_io sdramCntl_inst_sd_intf_dq[7] K14 18 | set_io sdramCntl_inst_sd_intf_addr[12] G14 19 | set_io sdramCntl_inst_sd_intf_addr[7] D16 20 | set_io sdramCntl_inst_sd_intf_cke G15 -pullup yes 21 | set_io sdramCntl_inst_sd_intf_dq[0] R14 22 | set_io sdramCntl_inst_sd_intf_dq[12] N16 23 | set_io sdram_clk_i H16 24 | set_io sdramCntl_inst_sd_intf_addr[8] E16 25 | set_io sdramCntl_inst_sd_intf_dq[15] R15 26 | set_io sdramCntl_inst_sd_intf_dq[9] L16 27 | set_io sdramCntl_inst_sd_intf_dqml J13 28 | set_io sdramCntl_inst_sd_intf_addr[1] E14 29 | set_io sdramCntl_inst_sd_intf_bs[0] H14 30 | set_io sdramCntl_inst_sd_intf_dq[2] M13 31 | set_io sdram_clk_o G16 32 | set_io sdramCntl_inst_sd_intf_addr[3] D14 33 | set_io sdramCntl_inst_sd_intf_dq[4] L13 34 | set_io sdramCntl_inst_sd_intf_we J14 35 | set_io led_disp_d1_o B10 36 | set_io led_disp_d2_o B12 37 | set_io led_disp_d3_o B11 38 | set_io led_status[1] B8 39 | set_io pb_i A16 -pullup yes 40 | set_io sdramCntl_inst_sd_intf_addr[11] F16 41 | set_io sdramCntl_inst_sd_intf_addr[4] B16 42 | set_io sdramCntl_inst_sd_intf_cas K15 43 | set_io sdramCntl_inst_sd_intf_cs H13 -pullup yes 44 | set_io sdramCntl_inst_sd_intf_dq[11] M15 45 | set_io sdramCntl_inst_sd_intf_dq[5] L14 46 | set_io sdramCntl_inst_sd_intf_dqmh J15 47 | set_io led_status[0] A9 48 | set_io sdramCntl_inst_sd_intf_addr[10] F14 49 | set_io sdramCntl_inst_sd_intf_addr[5] C16 50 | set_io sdramCntl_inst_sd_intf_dq[10] M16 51 | set_io sdramCntl_inst_sd_intf_dq[6] K13 52 | set_io led_disp_d0_o A11 53 | set_io led_disp_d4_o B14 54 | set_io led_disp_d5_o B13 55 | set_io sdramCntl_inst_sd_intf_addr[6] D15 56 | set_io sdramCntl_inst_sd_intf_dq[13] P16 57 | set_io led_status[2] A7 58 | set_io sdramCntl_inst_sd_intf_dq[8] J16 59 | set_io master_clk_i C8 60 | set_io sdramCntl_inst_sd_intf_addr[0] F13 61 | set_io sdramCntl_inst_sd_intf_dq[1] P14 62 | set_io sdramCntl_inst_sd_intf_addr[9] F15 63 | set_io sdramCntl_inst_sd_intf_dq[14] P15 64 | set_io sdramCntl_inst_sd_intf_ras K16 65 | set_io led_disp_d6_o B15 66 | set_io led_disp_d7_o A15 67 | set_io sdramCntl_inst_sd_intf_addr[2] E13 68 | set_io sdramCntl_inst_sd_intf_bs[1] G13 69 | set_io sdramCntl_inst_sd_intf_dq[3] M14 70 | 71 | -------------------------------------------------------------------------------- /tests/lattice_sdram_test/sdram_test/sdram_test_sbt.project: -------------------------------------------------------------------------------- 1 | [Project] 2 | ProjectVersion=2.0 3 | Version=Lattice Semiconductor Corporation iCEcube - Release: 2015.08.27744 - Build Date: Oct 14 2015 01:04:41 4 | ProjectName=sdram_test 5 | Vendor=SiliconBlue 6 | Synthesis=synplify 7 | ProjectVFiles=../../sdram_test.v=work 8 | ProjectCFiles= 9 | CurImplementation=sdram_test_Implmnt 10 | Implementations=sdram_test_Implmnt 11 | StartFromSynthesis=yes 12 | IPGeneration=false 13 | 14 | [lse options] 15 | CarryChain=True 16 | CarryChainLength=0 17 | CommandLineOptions= 18 | EBRUtilization=100.00 19 | FSMEncodingStyle=Auto 20 | FixGatedClocks=True 21 | I/OInsertion=True 22 | IntermediateFileDump=False 23 | LoopLimit=1950 24 | MaximalFanout=10000 25 | MemoryInitialValueFileSearchPath= 26 | NumberOfCriticalPaths=3 27 | OptimizationGoal=Area 28 | PropagateConstants=True 29 | RAMStyle=Auto 30 | ROMStyle=Auto 31 | RWCheckOnRam=False 32 | RemoveDuplicateRegisters=True 33 | ResolvedMixedDrivers=False 34 | ResourceSharing=True 35 | TargetFrequency= 36 | TopLevelUnit= 37 | UseIORegister=Auto 38 | VHDL2008=False 39 | VerilogIncludeSearchPath= 40 | 41 | [sdram_test_Implmnt] 42 | DeviceFamily=iCE40 43 | Device=HX8K 44 | DevicePackage=CT256 45 | DevicePower= 46 | NetlistFile=sdram_test_Implmnt/sdram_test.edf 47 | AdditionalEDIFFile= 48 | IPEDIFFile= 49 | DesignLib=sdram_test_Implmnt/sbt/netlist/oadb-sdram_test 50 | DesignView=_rt 51 | DesignCell=sdram_test 52 | SynthesisSDCFile=sdram_test_Implmnt/sdram_test.scf 53 | UserPinConstraintFile= 54 | UserSDCFile= 55 | PhysicalConstraintFile=sdram_test_Implmnt/sbt/constraint/sdram_test_pcf_sbt.pcf 56 | BackendImplPathName= 57 | Devicevoltage=1.14 58 | DevicevoltagePerformance=+/-5%(datasheet default) 59 | DeviceTemperature=85 60 | TimingAnalysisBasedOn=Worst 61 | OperationRange=Commercial 62 | TypicalCustomTemperature=25 63 | WorstCustomTemperature=85 64 | BestCustomTemperature=0 65 | IOBankVoltages=topBank,3.3 bottomBank,3.3 leftBank,3.3 rightBank,3.3 66 | derValue=0.701346 67 | TimingPathNumberStick=0 68 | 69 | [tool options] 70 | PlacerEffortLevel=std 71 | PlacerAutoLutCascade=yes 72 | PlacerAutoRamCascade=yes 73 | PlacerPowerDriven=no 74 | RouteWithTimingDriven=yes 75 | RouteWithPinPermutation=yes 76 | BitmapSPIFlashMode=yes 77 | BitmapRAM4KInit=yes 78 | BitmapInitRamBank=1111 79 | BitmapOscillatorFR=low 80 | BitmapEnableWarmBoot=yes 81 | BitmapDisableHeader=no 82 | BitmapSetSecurity=no 83 | BitmapSetNoUsedIONoPullup=no 84 | FloorPlannerShowFanInNets=yes 85 | FloorPlannerShowFanOutNets=yes 86 | HookTo3rdPartyTextEditor=yes 87 | 88 | -------------------------------------------------------------------------------- /tests/lattice_sdram_test/sdram_test/sdram_test_syn.prj: -------------------------------------------------------------------------------- 1 | #-- Synopsys, Inc. 2 | #-- Project file C:\xesscorp\PRODUCTS\CAT\tests\lattice_sdram_test\sdram_test\sdram_test_syn.prj 3 | #project files 4 | 5 | add_file -verilog -lib work "../../sdram_test.v" 6 | #implementation: "sdram_test_Implmnt" 7 | impl -add sdram_test_Implmnt -type fpga 8 | 9 | #implementation attributes 10 | set_option -vlog_std v2001 11 | set_option -project_relative_includes 1 12 | 13 | #device options 14 | set_option -technology SBTiCE40 15 | set_option -part iCE40HX8K 16 | set_option -package CT256 17 | set_option -speed_grade 18 | set_option -part_companion "" 19 | 20 | #compilation/mapping options 21 | 22 | # mapper_options 23 | set_option -frequency auto 24 | set_option -write_verilog 0 25 | set_option -write_vhdl 0 26 | 27 | # Silicon Blue iCE40 28 | set_option -maxfan 10000 29 | set_option -disable_io_insertion 0 30 | set_option -pipe 1 31 | set_option -retiming 0 32 | set_option -update_models_cp 0 33 | set_option -fixgatedclocks 2 34 | set_option -fixgeneratedclocks 0 35 | 36 | # NFilter 37 | set_option -popfeed 0 38 | set_option -constprop 0 39 | set_option -createhierarchy 0 40 | 41 | # sequential_optimization_options 42 | set_option -symbolic_fsm_compiler 1 43 | 44 | # Compiler Options 45 | set_option -compiler_compatible 0 46 | set_option -resource_sharing 1 47 | 48 | #automatic place and route (vendor) options 49 | set_option -write_apr_constraint 1 50 | 51 | #set result format/file last 52 | project -result_format "edif" 53 | project -result_file ./sdram_test_Implmnt/sdram_test.edf 54 | project -log_file "./sdram_test_Implmnt/sdram_test.srr" 55 | impl -active sdram_test_Implmnt 56 | project -run synthesis -clean 57 | -------------------------------------------------------------------------------- /tests/led_digits_display.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2015 by XESS Corporation 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from myhdl import * 24 | from math import ceil 25 | 26 | 27 | def ascii_to_7seg(segments_o, ascii_char_i): 28 | '''Return the segment activations to display the given ASCII character. 29 | 30 | ascii_char_i: ASCII character code. 31 | segments_o: Activation code for 7-segment LED digit. 32 | ''' 33 | 34 | @always_comb 35 | def logic(): 36 | if ascii_char_i == 0x20: 37 | segments_o.next = intbv('0000000') # Space. 38 | elif ascii_char_i == 0x2d: 39 | segments_o.next = intbv('1000000') # Minus sign (-). 40 | elif ascii_char_i == 0x00 or ascii_char_i == 0x30: 41 | segments_o.next = intbv('0111111') # Zero. 42 | elif ascii_char_i == 0x01 or ascii_char_i == 0x31: 43 | segments_o.next = intbv('0000110') # One. 44 | elif ascii_char_i == 0x02 or ascii_char_i == 0x32: 45 | segments_o.next = intbv('1011011') # Two. 46 | elif ascii_char_i == 0x03 or ascii_char_i == 0x33: 47 | segments_o.next = intbv('1001111') # Three. 48 | elif ascii_char_i == 0x04 or ascii_char_i == 0x34: 49 | segments_o.next = intbv('1100110') # Four. 50 | elif ascii_char_i == 0x05 or ascii_char_i == 0x35: 51 | segments_o.next = intbv('1101101') # Five. 52 | elif ascii_char_i == 0x06 or ascii_char_i == 0x36: 53 | segments_o.next = intbv('1111101') # Six. 54 | elif ascii_char_i == 0x07 or ascii_char_i == 0x37: 55 | segments_o.next = intbv('0000111') # Seven. 56 | elif ascii_char_i == 0x08 or ascii_char_i == 0x38: 57 | segments_o.next = intbv('1111111') # Eight. 58 | elif ascii_char_i == 0x09 or ascii_char_i == 0x39: 59 | segments_o.next = intbv('1101111') # Nine. 60 | elif ascii_char_i == 0x0a or ascii_char_i == 0x41 or ascii_char_i == 0x61: 61 | segments_o.next = intbv('1110111') # A. 62 | elif ascii_char_i == 0x0b or ascii_char_i == 0x42 or ascii_char_i == 0x62: 63 | segments_o.next = intbv('1111100') # b. 64 | elif ascii_char_i == 0x0c or ascii_char_i == 0x43 or ascii_char_i == 0x63: 65 | segments_o.next = intbv('0111001') # C. 66 | elif ascii_char_i == 0x0d or ascii_char_i == 0x44 or ascii_char_i == 0x64: 67 | segments_o.next = intbv('1011110') # d. 68 | elif ascii_char_i == 0x0e or ascii_char_i == 0x45 or ascii_char_i == 0x65: 69 | segments_o.next = intbv('1111001') # E. 70 | elif ascii_char_i == 0x0f or ascii_char_i == 0x46 or ascii_char_i == 0x66: 71 | segments_o.next = intbv('1110001') # F. 72 | elif ascii_char_i == 0x47 or ascii_char_i == 0x67: 73 | segments_o.next = intbv('0111101') # G. 74 | elif ascii_char_i == 0x48 or ascii_char_i == 0x68: 75 | segments_o.next = intbv('1110100') # h. 76 | elif ascii_char_i == 0x49 or ascii_char_i == 0x69: 77 | segments_o.next = intbv('0110000') # I. 78 | elif ascii_char_i == 0x4a or ascii_char_i == 0x6a: 79 | segments_o.next = intbv('0011110') # J. 80 | elif ascii_char_i == 0x4b or ascii_char_i == 0x6b: 81 | segments_o.next = intbv('0001000') # Blank. 82 | elif ascii_char_i == 0x4c or ascii_char_i == 0x6c: 83 | segments_o.next = intbv('0111000') # L. 84 | elif ascii_char_i == 0x4d or ascii_char_i == 0x6d: 85 | segments_o.next = intbv('0001000') # Blank. 86 | elif ascii_char_i == 0x4e or ascii_char_i == 0x6e: 87 | segments_o.next = intbv('1010100') # n. 88 | elif ascii_char_i == 0x4f or ascii_char_i == 0x6f: 89 | segments_o.next = intbv('1011100') # o. 90 | elif ascii_char_i == 0x50 or ascii_char_i == 0x70: 91 | segments_o.next = intbv('1110011') # P. 92 | elif ascii_char_i == 0x51 or ascii_char_i == 0x71: 93 | segments_o.next = intbv('0001000') # Blank. 94 | elif ascii_char_i == 0x52 or ascii_char_i == 0x72: 95 | segments_o.next = intbv('1010000') # r. 96 | elif ascii_char_i == 0x53 or ascii_char_i == 0x73: 97 | segments_o.next = intbv('1101101') # S. 98 | elif ascii_char_i == 0x54 or ascii_char_i == 0x74: 99 | segments_o.next = intbv('1111000') # t. 100 | elif ascii_char_i == 0x55 or ascii_char_i == 0x75: 101 | segments_o.next = intbv('0011100') # u. 102 | elif ascii_char_i == 0x56 or ascii_char_i == 0x76: 103 | segments_o.next = intbv('0001000') # Blank. 104 | elif ascii_char_i == 0x57 or ascii_char_i == 0x77: 105 | segments_o.next = intbv('0001000') # Blank. 106 | elif ascii_char_i == 0x58 or ascii_char_i == 0x78: 107 | segments_o.next = intbv('0001000') # Blank. 108 | elif ascii_char_i == 0x59 or ascii_char_i == 0x79: 109 | segments_o.next = intbv('1101110') # y. 110 | elif ascii_char_i == 0x5a or ascii_char_i == 0x7a: 111 | segments_o.next = intbv('0001000') # Blank. 112 | elif ascii_char_i == 0x5f: 113 | segments_o.next = intbv('0001000') # Underscore (_). 114 | else: 115 | segments_o.next = intbv('0001000') # Blank. 116 | 117 | return instances() 118 | 119 | 120 | def led_digits_display(d0_o, 121 | d1_o, 122 | d2_o, 123 | d3_o, 124 | d4_o, 125 | d5_o, 126 | d6_o, 127 | d7_o, 128 | clk_i, 129 | digit1_i=Signal(intbv(0)[7:]), 130 | digit2_i=Signal(intbv(0)[7:]), 131 | digit3_i=Signal(intbv(0)[7:]), 132 | digit4_i=Signal(intbv(0)[7:]), 133 | digit5_i=Signal(intbv(0)[7:]), 134 | digit6_i=Signal(intbv(0)[7:]), 135 | digit7_i=Signal(intbv(0)[7:]), 136 | digit8_i=Signal(intbv(0)[7:]), 137 | digit_all_i=Signal(intbv(0)[56:]), 138 | enable_ascii_to_7seg=True, 139 | freq_g=100e6, 140 | update_freq_g=1000): 141 | '''Module for displaying chars on StickIt! LEDDigits board. 142 | d0_o, ... d7_o: 3-state outputs to drive the StickIt! LEDDigits board. 143 | clk_i: Input clock. 144 | digit1_i ... digit8_i: 7-bit input for each digit on the LEDDigits board. 145 | digit_all_i: Alternate input for driving all 56 LEDs of the LEDDigits board. 146 | enable_ascii_to_7seg: Set True to interpret input digits as ASCII. 147 | freq_g: Set to frequency of input clock. 148 | update_freq_g: Set number of times the display is refreshed each second. 149 | ''' 150 | 151 | initialized = Signal(bool(0)) # Initialization flag - starts off uninitialized. 152 | 153 | # These are shift registers: one for selecting the currently-driven LED digit, 154 | # and the other for selecting the currently driven segments within that digit. 155 | digit_shf = Signal(intbv('00000001')[8:]) 156 | seg_mask = Signal(intbv('0010101')[7:]) 157 | # Counter for sequencing through the segments of a 7-segment digit. 158 | seg_cntr = Signal(intbv(0, 0, len(seg_mask))) 159 | # Compute how long each segment should be activated based on the input clock 160 | # frequency, the display refresh frequency, the number of segments in the 161 | # display, and the number of simultaneously-driven segments. 162 | num_mask_bits = bin(seg_mask).count('1') 163 | SEG_PERIOD = int(ceil((freq_g / (update_freq_g * len(digit_all_i)) / 164 | num_mask_bits))) 165 | seg_timer = Signal(intbv(0, 0, SEG_PERIOD + 1)) 166 | # Blanking signal for turning off all the segments. 167 | blank = Signal(bool(0)) 168 | 169 | inst = [] # List of submodule instantiations. 170 | 171 | # Logic for sequencing through the digits and the segments within each digit. 172 | # One shift register selects the currently active LED digit, while the other 173 | # selects the active LED segments within that digit. A timer measures the 174 | # interval each segment will remain active, and a segment counter determines 175 | # when all the segments for a digit have been processed. 176 | @always_seq(clk_i.posedge, reset=None) 177 | def scan_segments_and_digits(): 178 | if initialized != True: 179 | # Initialize the rotating shift registers. 180 | seg_mask.next = intbv('0010101') 181 | digit_shf.next = intbv('00000001') 182 | initialized.next = not initialized # Do initialization only once. 183 | elif seg_timer == 0: # When done driving the current segments... 184 | seg_timer.next = seg_timer.max - 1 # Reload the segment timer... 185 | seg_mask.next[7:1] = seg_mask[6:0] # Rotate the shift register... 186 | seg_mask.next[0] = seg_mask[6] # to activate different segments... 187 | blank.next = (seg_cntr == 1) 188 | if seg_cntr == 0: # When all segments of current digit are done... 189 | digit_shf.next[8:1] = digit_shf[7:0] # Shift to the next digit. 190 | digit_shf.next[0] = digit_shf[7] 191 | seg_cntr.next = seg_cntr.max - 1 # Reset segment counter for new digit. 192 | else: # Current digit is not done being displayed... 193 | seg_cntr.next = seg_cntr - 1 # So shift to next set of segments. 194 | else: # Current segments are not done being displayed... 195 | seg_timer.next = seg_timer - 1 # So just decrement the timer. 196 | 197 | # Declare the signal that holds the currently active digit code. 198 | active_digit = Signal(intbv(0)[len(seg_mask):]) 199 | 200 | # Select the digit input based on which bit is active in the digit shift 201 | # register. The active digit is an OR of the individual input digit and the 202 | # corresponding field of the digit_all_i input. (Either the input digit or 203 | # the digit_all_i input will be all 0s so the OR output will just be the 204 | # non-zero input.) 205 | @always_comb 206 | def get_active_digit(): 207 | if digit_shf[0] == 1: 208 | active_digit.next = digit1_i | digit_all_i[7:0] 209 | elif digit_shf[1] == 1: 210 | active_digit.next = digit2_i | digit_all_i[14:7] 211 | elif digit_shf[2] == 1: 212 | active_digit.next = digit3_i | digit_all_i[21:14] 213 | elif digit_shf[3] == 1: 214 | active_digit.next = digit4_i | digit_all_i[28:21] 215 | elif digit_shf[4] == 1: 216 | active_digit.next = digit5_i | digit_all_i[35:28] 217 | elif digit_shf[5] == 1: 218 | active_digit.next = digit6_i | digit_all_i[42:35] 219 | elif digit_shf[6] == 1: 220 | active_digit.next = digit7_i | digit_all_i[49:42] 221 | elif digit_shf[7] == 1: 222 | active_digit.next = digit8_i | digit_all_i[56:49] 223 | else: 224 | active_digit.next = 0 225 | 226 | # Declare the signal that holds the values driven to the digit segments. 227 | segments = Signal(intbv(0)[len(seg_mask):]) 228 | 229 | # Select whether the active digit code is driven directly to the display, 230 | # or whether it is interpreted as an ASCII character and needs to be transformed 231 | # into an activation code. 232 | if enable_ascii_to_7seg == True: 233 | # Translate from ASCII into an LED digit activation code. 234 | inst.append(ascii_to_7seg(segments, active_digit)) 235 | else: 236 | # Directly drive the LED segments with the active digit code. 237 | @always_comb 238 | def pass_thru(): 239 | segments.next = active_digit 240 | 241 | # Declare the signal that holds the segments which will be turned on. 242 | active_segments = Signal(intbv(0)[len(segments):]) 243 | 244 | # AND the segments signal with the segment shift register to select the ON segments. 245 | @always_comb 246 | def get_active_segments(): 247 | active_segments.next = segments & seg_mask 248 | 249 | # Declare the signal that holds the LEDDigits board driver outputs. 250 | drvr_enbls = Signal(intbv(0)[len(active_segments) + 1:]) 251 | 252 | # The driver bits are set as follows: 253 | # * If digit i is active, then digit_shf[i-1] bit is on and 254 | # drvr_enbls[i-1] bit is driven high to source the digit i LED anodes. 255 | # * The remaining drvr_enbls bits are filled with the bits from 256 | # active_segments as follows: 257 | # drvr_enbls[i-1:0] = active_segments[i-1:0] 258 | # drvr_enbls[8:i] = active_segments[7:i-1] 259 | # Essentially, the ON bit at position i in digit_shf is inserted between 260 | # bits i and i-1 of active_segments. 261 | @always_comb 262 | def combine_drivers(): 263 | if blank == True: 264 | drvr_enbls.next = 0 265 | elif digit_shf[0] == 1: 266 | drvr_enbls.next[8:1] = active_segments[7:0] 267 | drvr_enbls.next[0] = 1 268 | elif digit_shf[1] == 1: 269 | drvr_enbls.next[8:2] = active_segments[7:1] 270 | drvr_enbls.next[1] = 1 271 | drvr_enbls.next[0] = active_segments[1:0] 272 | elif digit_shf[2] == 1: 273 | drvr_enbls.next[8:3] = active_segments[7:2] 274 | drvr_enbls.next[2] = 1 275 | drvr_enbls.next[2:0] = active_segments[2:0] 276 | elif digit_shf[3] == 1: 277 | drvr_enbls.next[8:4] = active_segments[7:3] 278 | drvr_enbls.next[3] = 1 279 | drvr_enbls.next[3:0] = active_segments[3:0] 280 | elif digit_shf[4] == 1: 281 | drvr_enbls.next[8:5] = active_segments[7:4] 282 | drvr_enbls.next[4] = 1 283 | drvr_enbls.next[4:0] = active_segments[4:0] 284 | elif digit_shf[5] == 1: 285 | drvr_enbls.next[8:6] = active_segments[7:5] 286 | drvr_enbls.next[5] = 1 287 | drvr_enbls.next[5:0] = active_segments[5:0] 288 | elif digit_shf[6] == 1: 289 | drvr_enbls.next[8:7] = active_segments[7:6] 290 | drvr_enbls.next[6] = 1 291 | drvr_enbls.next[6:0] = active_segments[6:0] 292 | elif digit_shf[7] == 1: 293 | drvr_enbls.next[7] = 1 294 | drvr_enbls.next[7:0] = active_segments[7:0] 295 | else: 296 | drvr_enbls.next = 0 297 | 298 | def tristate_driver(o, i, enbl): 299 | ''' Tristate driver module. 300 | o: 3-state output (high, low, Z). Must be declared TriStateSignal(). 301 | i: input. 302 | enbl: When low, o is Z, otherwise o is i. 303 | ''' 304 | 305 | o_drvr = o.driver() # Get ShadowSignal for driving output. 306 | 307 | @always_comb 308 | def drvr_logic(): 309 | if enbl == 1: 310 | o_drvr.next = i # Drive output with value on input. 311 | else: 312 | o_drvr.next = None # Equivalent to Z. 313 | 314 | # Dummy signal driven by o so MyHDL recognizes it as an inout. 315 | dummy = Signal(bool(0)) 316 | 317 | @always_comb 318 | def dummy_logic(): 319 | dummy.next = bool(o) 320 | 321 | return instances() 322 | 323 | # Attach tristate drivers. The bits where drvr_enbls has 1s will be enabled, 324 | # while the rest will be Z. Of the enabled bits, the bit driving the anode 325 | # of the active digit will be high and the rest (connected to the cathodes) 326 | # will be low. 327 | d = [d0_o, d1_o, d2_o, d3_o, d4_o, d5_o, d6_o, d7_o] 328 | for i in range(len(d)): 329 | inst.append(tristate_driver(d[i], digit_shf(i), drvr_enbls(i))) 330 | 331 | return instances() 332 | 333 | 334 | def led_digits_scroll(d0_o, 335 | d1_o, 336 | d2_o, 337 | d3_o, 338 | d4_o, 339 | d5_o, 340 | d6_o, 341 | d7_o, 342 | clk_i, 343 | enable_ascii_to_7seg=True, 344 | freq_g=100e6): 345 | ''' Example design for scrolling pattern across LED digits. 346 | d0_o, ... d7_o: 3-state outputs to drive the StickIt! LEDDigits board. 347 | clk_i: Input clock. 348 | enable_ascii_to_7seg: Set True to interpret input digits as ASCII. 349 | freq_g: Set to frequency of input clock. 350 | ''' 351 | 352 | initialized = Signal(bool(0)) # Initialization flag - starts off uninitialized. 353 | SCROLL_INTERVAL = 1 # Time interval in seconds between digits scrolling. 354 | cntr = Signal(intbv(0, 0, int(SCROLL_INTERVAL * freq_g))) # 1-sec interval counter. 355 | charstring = Signal(intbv(0)[64:]) # Holds the scrolling characters. 356 | 357 | @always_seq(clk_i.posedge, reset=None) 358 | def cntr_logic(): 359 | if initialized == False: # Initialize the character string once upon startup. 360 | initialized.next = not initialized 361 | charstring.next = 0x0706050403020120 362 | elif cntr == 0: # Rotate the character string once each second. 363 | cntr.next = cntr.max - 1 364 | charstring.next[64:8] = charstring[56:0] 365 | charstring.next[8:0] = charstring[64:56] 366 | else: # Decrement the 1-second interval counter. 367 | cntr.next = cntr - 1 368 | 369 | # Attach the scrolling digits to the LEDDigits module. 370 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] # LEDDigits drivers. 371 | disp = led_digits_display(drvrs[0], 372 | drvrs[1], 373 | drvrs[2], 374 | drvrs[3], 375 | drvrs[4], 376 | drvrs[5], 377 | drvrs[6], 378 | drvrs[7], 379 | clk_i, 380 | charstring(8, 0), 381 | charstring(16, 8), 382 | charstring(24, 16), 383 | charstring(32, 24), 384 | charstring(40, 32), 385 | charstring(48, 40), 386 | charstring(56, 48), 387 | charstring(64, 56), 388 | enable_ascii_to_7seg=enable_ascii_to_7seg, 389 | freq_g=freq_g) 390 | 391 | # Attach the LEDDigits drivers to the output pins of this module. 392 | @always_comb 393 | def io_logic(): 394 | d0_o.next = drvrs[0] 395 | d1_o.next = drvrs[1] 396 | d2_o.next = drvrs[2] 397 | d3_o.next = drvrs[3] 398 | d4_o.next = drvrs[4] 399 | d5_o.next = drvrs[5] 400 | d6_o.next = drvrs[6] 401 | d7_o.next = drvrs[7] 402 | 403 | return instances() 404 | 405 | 406 | def led_digits_scroll_tb(): 407 | '''Testbench for the LED digits scroller.''' 408 | clk = Signal(bool(0)) 409 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] 410 | dut = led_digits_scroll(drvrs[0].driver(), 411 | drvrs[1].driver(), 412 | drvrs[2].driver(), 413 | drvrs[3].driver(), 414 | drvrs[4].driver(), 415 | drvrs[5].driver(), 416 | drvrs[6].driver(), 417 | drvrs[7].driver(), 418 | clk, 419 | enable_ascii_to_7seg=False, 420 | freq_g=100e4) 421 | 422 | @instance 423 | def clk_gen(): 424 | for i in range(10000): 425 | clk.next = not clk 426 | yield delay(10) 427 | raise StopSimulation 428 | 429 | return instances() 430 | 431 | 432 | def led_digits_cnt(d0_o, 433 | d1_o, 434 | d2_o, 435 | d3_o, 436 | d4_o, 437 | d5_o, 438 | d6_o, 439 | d7_o, 440 | clk_i, 441 | enable_ascii_to_7seg=True, 442 | freq_g=100e6): 443 | ''' Example design for eight-digit counter. 444 | d0_o, ... d7_o: 3-state outputs to drive the StickIt! LEDDigits board. 445 | clk_i: Input clock. 446 | enable_ascii_to_7seg: Set True to interpret input digits as ASCII. 447 | freq_g: Set to frequency of input clock. 448 | ''' 449 | 450 | # Increment a 56-bit counter every clock cycle. 451 | cntr = Signal(intbv(0)[56:]) 452 | 453 | @always_seq(clk_i.posedge, reset=None) 454 | def cntr_logic(): 455 | cntr.next = cntr + 1 456 | 457 | # Attach the upper 32 bits of the counter to the LED module and discard 458 | # the lower 24 bits. 459 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] # LEDDigits drivers. 460 | disp = led_digits_display(drvrs[0], 461 | drvrs[1], 462 | drvrs[2], 463 | drvrs[3], 464 | drvrs[4], 465 | drvrs[5], 466 | drvrs[6], 467 | drvrs[7], 468 | clk_i, 469 | cntr(28, 24), 470 | cntr(32, 28), 471 | cntr(36, 32), 472 | cntr(40, 36), 473 | cntr(44, 40), 474 | cntr(48, 44), 475 | cntr(52, 48), 476 | cntr(56, 52), 477 | enable_ascii_to_7seg=enable_ascii_to_7seg, 478 | freq_g=freq_g) 479 | 480 | # Attach the LEDDigits drivers to the output pins of this module. 481 | @always_comb 482 | def io_logic(): 483 | d0_o.next = drvrs[0] 484 | d1_o.next = drvrs[1] 485 | d2_o.next = drvrs[2] 486 | d3_o.next = drvrs[3] 487 | d4_o.next = drvrs[4] 488 | d5_o.next = drvrs[5] 489 | d6_o.next = drvrs[6] 490 | d7_o.next = drvrs[7] 491 | 492 | return instances() 493 | 494 | 495 | def led_digits_cnt_tb(): 496 | '''Testbench for the LED digits counter.''' 497 | clk = Signal(bool(0)) 498 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] 499 | dut = led_digits_cnt(drvrs[0].driver(), 500 | drvrs[1].driver(), 501 | drvrs[2].driver(), 502 | drvrs[3].driver(), 503 | drvrs[4].driver(), 504 | drvrs[5].driver(), 505 | drvrs[6].driver(), 506 | drvrs[7].driver(), 507 | clk, 508 | freq_g=100e4) 509 | 510 | @instance 511 | def clk_gen(): 512 | for i in range(10000): 513 | clk.next = not clk 514 | yield delay(10) 515 | raise StopSimulation 516 | 517 | return instances() 518 | 519 | # Main routine that does simulation and Verilog conversion. 520 | if __name__ == '__main__': 521 | 522 | Simulation(traceSignals(led_digits_scroll_tb)).run() 523 | 524 | clk = Signal(bool(0)) 525 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] 526 | toVerilog(led_digits_scroll, drvrs[0].driver(), drvrs[1].driver(), 527 | drvrs[2].driver(), drvrs[3].driver(), drvrs[4].driver(), 528 | drvrs[5].driver(), drvrs[6].driver(), drvrs[7].driver(), clk, 529 | False) 530 | -------------------------------------------------------------------------------- /tests/rand_gen.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2016 by XESS Corporation. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from myhdl import * 24 | 25 | 26 | # Maximum-length LFSR taps from Table 3 of XAPP 052: 27 | # http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf 28 | lfsr_taps = { 29 | 3: (3, 2), 30 | 4: (4, 3), 31 | 5: (5, 3), 32 | 6: (6, 5), 33 | 7: (7, 6), 34 | 8: (8, 6, 5, 4), 35 | 9: (9, 5), 36 | 10: (10, 7), 37 | 11: (11, 9), 38 | 12: (12, 6, 4, 1), 39 | 13: (13, 4, 3, 1), 40 | 14: (14, 5, 3, 1), 41 | 15: (15, 14), 42 | 16: (16, 15, 13, 4), 43 | 17: (17, 14), 44 | 18: (18, 11), 45 | 19: (19, 6, 2, 1), 46 | 20: (20, 17), 47 | 21: (21, 19), 48 | 22: (22, 21), 49 | 23: (23, 18), 50 | 24: (24, 23, 22, 17), 51 | 25: (25, 22), 52 | 26: (26, 6, 2, 1), 53 | 27: (27, 5, 2, 1), 54 | 28: (28, 25), 55 | 29: (29, 27), 56 | 30: (30, 6, 4, 1), 57 | 31: (31, 28), 58 | 32: (32, 22, 2, 1), 59 | 33: (33, 20), 60 | 34: (34, 27, 2, 1), 61 | 35: (35, 33), 62 | 36: (36, 25), 63 | 37: (37, 5, 4, 3, 2, 1), 64 | 38: (38, 6, 5, 1), 65 | 39: (39, 35), 66 | 40: (40, 38, 21, 19), 67 | 41: (41, 38), 68 | 42: (42, 41, 20, 19), 69 | 43: (43, 42, 38, 37), 70 | 44: (44, 43, 18, 17), 71 | 45: (45, 44, 42, 41), 72 | 46: (46, 45, 26, 25), 73 | 47: (47, 42), 74 | 48: (48, 47, 21, 20), 75 | 49: (49, 40), 76 | 50: (50, 49, 24, 23), 77 | 51: (51, 50, 36, 35), 78 | 52: (52, 49), 79 | 53: (53, 52, 38, 37), 80 | 54: (54, 53, 18, 17), 81 | 55: (55, 31), 82 | 56: (56, 55, 35, 34), 83 | 57: (57, 50), 84 | 58: (58, 39), 85 | 59: (59, 58, 38, 37), 86 | 60: (60, 59), 87 | 61: (61, 60, 46, 45), 88 | 62: (62, 61, 6, 5), 89 | 63: (63, 62), 90 | 64: (64, 63, 61, 60), 91 | 65: (65, 47), 92 | 66: (66, 65, 57, 56), 93 | 67: (67, 66, 58, 57), 94 | 68: (68, 59), 95 | 69: (69, 67, 42, 40), 96 | 70: (70, 69, 55, 54), 97 | 71: (71, 65), 98 | 72: (72, 66, 25, 19), 99 | 73: (73, 48), 100 | 74: (74, 73, 59, 58), 101 | 75: (75, 74, 65, 64), 102 | 76: (76, 75, 41, 40), 103 | 77: (77, 76, 47, 46), 104 | 78: (78, 77, 59, 58), 105 | 79: (79, 70), 106 | 80: (80, 79, 43, 42), 107 | 81: (81, 77), 108 | 82: (82, 79, 47, 44), 109 | 83: (83, 82, 38, 37), 110 | 84: (84, 71), 111 | 85: (85, 84, 58, 57), 112 | 86: (86, 85, 74, 73), 113 | 87: (87, 74), 114 | 88: (88, 87, 17, 16), 115 | 89: (89, 51), 116 | 90: (90, 89, 72, 71), 117 | 91: (91, 90, 8, 7), 118 | 92: (92, 91, 80, 79), 119 | 93: (93, 91), 120 | 94: (94, 73), 121 | 95: (95, 84), 122 | 96: (96, 94, 49, 47), 123 | 97: (97, 91), 124 | 98: (98, 87), 125 | 99: (99, 97, 54, 52), 126 | 100: (100, 63), 127 | 101: (101, 100, 95, 94), 128 | 102: (102, 101, 36, 35), 129 | 103: (103, 94), 130 | 104: (104, 103, 94, 93), 131 | 105: (105, 89), 132 | 106: (106, 91), 133 | 107: (107, 105, 44, 42), 134 | 108: (108, 77), 135 | 109: (109, 108, 103, 102), 136 | 110: (110, 109, 98, 97), 137 | 111: (111, 101), 138 | 112: (112, 110, 69, 67), 139 | 113: (113, 104), 140 | 114: (114, 113, 33, 32), 141 | 115: (115, 114, 101, 100), 142 | 116: (116, 115, 46, 45), 143 | 117: (117, 115, 99, 97), 144 | 118: (118, 85), 145 | 119: (119, 111), 146 | 120: (120, 113, 9, 2), 147 | 121: (121, 103), 148 | 122: (122, 121, 63, 62), 149 | 123: (123, 121), 150 | 124: (124, 87), 151 | 125: (125, 124, 18, 17), 152 | 126: (126, 125, 90, 89), 153 | 127: (127, 126), 154 | 128: (128, 126, 101, 99), 155 | 129: (129, 124), 156 | 130: (130, 127), 157 | 131: (131, 130, 84, 83), 158 | 132: (132, 103), 159 | 133: (133, 132, 82, 81), 160 | 134: (134, 77), 161 | 135: (135, 124), 162 | 136: (136, 135, 11, 10), 163 | 137: (137, 116), 164 | 138: (138, 137, 131, 130), 165 | 139: (139, 136, 134, 131), 166 | 140: (140, 111), 167 | 141: (141, 140, 110, 109), 168 | 142: (142, 121), 169 | 143: (143, 142, 123, 122), 170 | 144: (144, 143, 75, 74), 171 | 145: (145, 93), 172 | 146: (146, 145, 87, 86), 173 | 147: (147, 146, 110, 109), 174 | 148: (148, 121), 175 | 149: (149, 148, 40, 39), 176 | 150: (150, 97), 177 | 151: (151, 148), 178 | 152: (152, 151, 87, 86), 179 | 153: (153, 152), 180 | 154: (154, 152, 27, 25), 181 | 155: (155, 154, 124, 123), 182 | 156: (156, 155, 41, 40), 183 | 157: (157, 156, 131, 130), 184 | 158: (158, 157, 132, 131), 185 | 159: (159, 128), 186 | 160: (160, 159, 142, 141), 187 | 161: (161, 143), 188 | 162: (162, 161, 75, 74), 189 | 163: (163, 162, 104, 103), 190 | 164: (164, 163, 151, 150), 191 | 165: (165, 164, 135, 134), 192 | 166: (166, 165, 128, 127), 193 | 167: (167, 161), 194 | 168: (168, 166, 153, 151), 195 | } 196 | 197 | 198 | def uniform_rand_gen(clk_i, enbl_i, load_i, seed_i, rand_o): 199 | '''Uniform random number generator.''' 200 | 201 | width = len(rand_o) # Width of random number to be generated. 202 | 203 | shfreg = Signal(intbv(1, 0, rand_o.max)) # Holds random number. 204 | 205 | # Create a mask with 1-bits at each tap position in the random number. 206 | mask = 0 207 | for t in lfsr_taps[width]: 208 | mask = mask | (1 << (t - 1)) 209 | 210 | # Sequential process to generate random number. 211 | @always_seq(clk_i.posedge, reset=None) 212 | def rand_shift(): 213 | 214 | # Mask off the feedback bit values and XOR them. 215 | bits = shfreg & mask 216 | xor_bit = 0 217 | for i in range(width): 218 | xor_bit = xor_bit ^ bits[i] 219 | 220 | if load_i: 221 | # Load the random number register with the starting seed value. 222 | shfreg.next = seed_i 223 | elif enbl_i: 224 | # Shift the random number by one bit and push in the XOR bit. 225 | shfreg.next[len(shfreg):1] = shfreg[len(shfreg) - 1:0] 226 | shfreg.next[0] = xor_bit 227 | 228 | # Combinational process to output the random number. 229 | @always_comb 230 | def rand_out(): 231 | rand_o.next = shfreg 232 | 233 | return instances() 234 | 235 | 236 | def xorshift_rand_gen(clk_i, enbl_i, load_i, seed_i, rand_o): 237 | '''Uniform random number generator.''' 238 | 239 | x, y, z, w, t = [Signal(intbv(0,0,2**32)) for _ in range(5)] 240 | 241 | # Sequential process to generate random number. 242 | @always_seq(clk_i.posedge, reset=None) 243 | def rand_shift(): 244 | 245 | if load_i: 246 | # Load the random number register with the starting seed value. 247 | # (The seed_i input is ignored.) 248 | x.next = 123456789 249 | y.next = 362436069 250 | z.next = 521288629 251 | w.next = 88675123 252 | elif enbl_i: 253 | t.next = x ^ (x << 11)[32:0] 254 | x.next = y 255 | y.next = z 256 | z.next = w 257 | w.next = w ^ (w>>19) ^ (t ^ (t>>8)) 258 | 259 | # Combinational process to output the random number. 260 | # The maximum width of the output is 32 bits. 261 | @always_comb 262 | def rand_out(): 263 | rand_o.next = w[len(rand_o):0] 264 | 265 | return instances() 266 | 267 | 268 | import math # Need this to compute scaling shift. 269 | 270 | sum_length = 16 271 | base_rng = xorshift_rand_gen 272 | 273 | def normal_rand_gen(clk_i, enbl_i, load_i, seed_i, rand_o): 274 | '''Normal (Gaussian) random number generator.''' 275 | 276 | # Instantiate a uniform RNG. 277 | uni_rand = Signal(intbv(0, 0, rand_o.max)) 278 | uni_rng = base_rng(clk_i, enbl_i, load_i, seed_i, uni_rand) 279 | 280 | # Create a FIFO for storing samples of the uniform random numbers. 281 | uni_rand_samples = [Signal(intbv(0, 0, rand_o.max)) for _ in range(sum_length)] 282 | 283 | # Create a signal with more bits for storing the sum of N random numbers. 284 | rand_sum = Signal(intbv(0, 0, sum_length*rand_o.max)) 285 | 286 | # Update the sum of random numbers with a new value on every clock cycle. 287 | @always_seq(clk_i.posedge, reset=None) 288 | def uni_sum_to_gauss(): 289 | 290 | # Create the sum by adding the newest random number and subtracting the oldest. 291 | rand_sum.next = rand_sum - uni_rand_samples[sum_length-1] + uni_rand 292 | 293 | # Then enter the newest into the FIFO while discarding the oldest. 294 | for i in range(sum_length-1): 295 | uni_rand_samples[i+1].next = uni_rand_samples[i] 296 | uni_rand_samples[0].next = uni_rand 297 | 298 | # The sum has to be scaled to be in the same range as the original random numbers. 299 | scale_shift = int(round(math.log(sum_length,2))) 300 | 301 | # Output the scaled sum. This will be a normally-distributed random number. 302 | @always_comb 303 | def scale_and_output_sum(): 304 | rand_o.next = rand_sum >> scale_shift 305 | 306 | return instances() 307 | 308 | 309 | rand_seq = [] # Store the generated random numbers here. 310 | 311 | def rand_gen_tb(rng, width, n_cycles): 312 | 313 | # Define the signals that connect to the RNG. 314 | clk = Signal(bool(0)) 315 | enbl = Signal(bool(0)) 316 | load = Signal(bool(0)) 317 | rand = Signal(intbv(0)[width:]) # This sets the #bits for the random numbers. 318 | seed = 42 # 42 is the answer for everything, so use it for the RNG seed. 319 | 320 | # Instantiate the given RNG model and connect it to the defined signals. 321 | dut = rng(clk, enbl, load, seed, rand) 322 | 323 | @instance 324 | def tb(): 325 | 326 | enbl.next = 1 # Enable random number generation. 327 | load.next = 1 # Load the random number seed on the 1st clock pulse. 328 | for _ in range(n_cycles): 329 | 330 | # Generate a new randon number by pulsing the clock. 331 | clk.next = 0 332 | yield delay(1) 333 | clk.next = 1 334 | yield delay(1) 335 | 336 | rand_seq.append(int(rand.val)) # Store the current output of the RNG. 337 | load.next = 0 # Turn off seed loading for the remaining clock pulses. 338 | 339 | return instances() 340 | 341 | 342 | if __name__ == '__main__': 343 | base_rng = xorshift_rand_gen 344 | Simulation(rand_gen_tb(normal_rand_gen, 16, 2**16)).run() 345 | 346 | import seaborn as sns # Use the pretty Seaborn coloring for the plots. 347 | import matplotlib.pyplot as plt # Load the plotting library. 348 | 349 | # Show a histogram of the random numbers that were generated. 350 | bins = list(range(0,65535,656)) # Divide the random number range into 100 bins. 351 | plt.hist(rand_seq, bins) 352 | plt.show() 353 | 354 | # clk = Signal(bool(0)) 355 | # enbl = Signal(bool(0)) 356 | # load = Signal(bool(0)) 357 | # seed = Signal(intbv(0)[16:]) 358 | # rand = Signal(intbv(0)[16:]) 359 | # toVerilog(uniform_rand_gen, clk, enbl, load, seed, rand) 360 | # toVerilog(xorshift_rand_gen, clk, enbl, load, seed, rand) 361 | # toVerilog(normal_rand_gen, clk, enbl, load, seed, rand) 362 | -------------------------------------------------------------------------------- /tests/reset_cat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A script to reset the iCE40 FPGA. 4 | # 5 | # Copyright (C) 2015 Jan Marjanovic 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | 21 | echo "" 22 | 23 | if [ $EUID -ne 0 ]; then 24 | echo "This script must be run as root" 1>&2 25 | exit 1 26 | fi 27 | 28 | 29 | if [ ! -d /sys/class/gpio/gpio25 ]; then 30 | echo "GPIO 25 not exported, trying to export..." 31 | echo 25 > /sys/class/gpio/export 32 | if [ ! -d /sys/class/gpio/gpio25 ]; then 33 | echo "ERROR: directory /sys/class/gpio/gpio25 does not exist" 34 | exit 1 35 | fi 36 | else 37 | echo "OK: GPIO 25 exported" 38 | fi 39 | 40 | if [ ! -d /sys/class/gpio/gpio17 ]; then 41 | echo "GPIO 17 not exported, trying to export..." 42 | echo 17 > /sys/class/gpio/export 43 | if [ ! -d /sys/class/gpio/gpio17 ]; then 44 | echo "ERROR: directory /sys/class/gpio/gpio17 does not exist" 45 | exit 1 46 | fi 47 | else 48 | echo "OK: GPIO 17 exported" 49 | fi 50 | 51 | if [ ! -d /sys/class/gpio/gpio22 ]; then 52 | echo "GPIO 22 not exported, trying to export..." 53 | echo 22 > /sys/class/gpio/export 54 | if [ ! -d /sys/class/gpio/gpio22 ]; then 55 | echo "ERROR: directory /sys/class/gpio/gpio22 does not exist" 56 | exit 1 57 | fi 58 | else 59 | echo "OK: GPIO 22 exported" 60 | fi 61 | 62 | echo "" 63 | if [ -e /dev/spidev0.0 ]; then 64 | echo "OK: SPI driver loaded" 65 | else 66 | echo "spidev does not exist" 67 | 68 | lsmod | grep spi_bcm2708 >& /dev/null 69 | 70 | if [ $? -ne 0 ]; then 71 | echo "SPI driver not loaded, try to load it..." 72 | modprobe spi_bcm2708 73 | 74 | if [ $? -eq 0 ]; then 75 | echo "OK: SPI driver loaded" 76 | else 77 | echo "Could not load SPI driver" 78 | exit 1 79 | fi 80 | fi 81 | fi 82 | 83 | echo "" 84 | echo "Setting GPIO directions" 85 | echo out > /sys/class/gpio/gpio25/direction 86 | cat /sys/class/gpio/gpio25/direction 87 | echo out > /sys/class/gpio/gpio22/direction 88 | cat /sys/class/gpio/gpio22/direction 89 | echo in > /sys/class/gpio/gpio17/direction 90 | cat /sys/class/gpio/gpio17/direction 91 | 92 | echo "Setting output to low" 93 | echo 0 > /sys/class/gpio/gpio25/value 94 | cat /sys/class/gpio/gpio25/value 95 | 96 | #echo "" 97 | #echo "Please reset the iCE40 FPGA board" 98 | #echo "Press any key..." 99 | #read 100 | 101 | echo "Reseting FPGA" 102 | echo 0 > /sys/class/gpio/gpio22/value 103 | cat /sys/class/gpio/gpio22/value 104 | echo 1 > /sys/class/gpio/gpio22/value 105 | cat /sys/class/gpio/gpio22/value 106 | 107 | echo "Checking DONE pin" 108 | cat /sys/class/gpio/gpio17/value 109 | 110 | -------------------------------------------------------------------------------- /tests/sdram_test.py: -------------------------------------------------------------------------------- 1 | # MIT license 2 | # 3 | # Copyright (C) 2016 by XESS Corporation. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from myhdl import * 24 | from led_digits_display import * 25 | from ice40_primitives import * 26 | from SDRAM_Controller import * 27 | from rand_gen import uniform_rand_gen 28 | 29 | 30 | def memory_test(clk_i, reset_i, status_o, led_status, host_intf): 31 | 32 | MAX_ADDRESS = 0xFFFFFF 33 | address = Signal(intbv(0)[len(host_intf.addr_i)+3:]) 34 | wr_enable = Signal(bool(0)) 35 | rd_enable = Signal(bool(0)) 36 | rand_enable = Signal(bool(0)) 37 | rand_load = Signal(bool(0)) 38 | rand_seed = 42 39 | rand_val = Signal(intbv(0)[len(host_intf.data_i):]) 40 | error = Signal(bool(False)) 41 | testState = enum('INIT', 'WRITE', 'VERIFY', 'SHOW_RESULT') 42 | test_state = Signal(testState.INIT) 43 | 44 | rand_gen = uniform_rand_gen(clk_i, rand_enable, rand_load, rand_seed, rand_val) 45 | 46 | @always_seq(clk_i.posedge, reset=None) 47 | def sdram_tester(): 48 | if reset_i == True: 49 | error.next = False 50 | test_state.next = testState.WRITE 51 | status_o.next = intbv(ord("1"),0,256) 52 | led_status.next = intbv('0001')[4:0] 53 | address.next = 0 54 | rand_load.next = 1 55 | elif test_state == testState.WRITE: 56 | rand_load.next = 0 57 | rand_enable.next = 0 58 | status_o.next = intbv(ord("2"),0,256) 59 | led_status.next = intbv('0010')[4:0] 60 | if host_intf.done_o == False: 61 | wr_enable.next = True 62 | else: 63 | wr_enable.next = False 64 | rand_enable.next = 1 65 | address.next = address + 1 66 | if address == MAX_ADDRESS: 67 | test_state.next = testState.VERIFY 68 | address.next = 0 69 | rand_load.next = 1 70 | error.next = False 71 | elif test_state == testState.VERIFY: 72 | rand_load.next = 0 73 | rand_enable.next = 0 74 | status_o.next = intbv(ord("3"),0,256) 75 | led_status.next = intbv('0100')[4:0] 76 | if host_intf.done_o == False: 77 | rd_enable.next = True 78 | else: 79 | rd_enable.next = False 80 | rand_enable.next = 1 81 | address.next = address + 1 82 | if rand_val != host_intf.data_o: 83 | error.next = True 84 | if address == MAX_ADDRESS: 85 | test_state.next = testState.SHOW_RESULT 86 | else: 87 | rand_load.next = 0 88 | rand_enable.next = 0 89 | if error == True: 90 | status_o.next = intbv(ord("F"),0,256) 91 | led_status.next = intbv('1000')[4:0] 92 | else: 93 | status_o.next = intbv(ord("O"),0,256) 94 | led_status.next = intbv('1111')[4:0] 95 | 96 | @always_comb 97 | def host_connections(): 98 | host_intf.rst_i.next = reset_i 99 | host_intf.wr_i.next = wr_enable and not host_intf.done_o 100 | host_intf.rd_i.next = rd_enable and not host_intf.done_o 101 | host_intf.data_i.next = rand_val 102 | host_intf.addr_i.next = address 103 | 104 | return instances() 105 | 106 | 107 | def sdram_test(master_clk_i, sdram_clk_o, sdram_clk_i, led_disp_d0_o, 108 | led_disp_d1_o, led_disp_d2_o, led_disp_d3_o, led_disp_d4_o, 109 | led_disp_d5_o, led_disp_d6_o, led_disp_d7_o, led_status, pb_i, sd_intf): 110 | 111 | clk = Signal(bool(0)) 112 | 113 | @always_comb 114 | def clock_routing(): 115 | sdram_clk_o.next = master_clk_i 116 | clk.next = sdram_clk_i 117 | 118 | initialized = Signal(bool(False)) 119 | 120 | @always_seq(clk.posedge, reset=None) 121 | def internal_reset(): 122 | if initialized == False: 123 | initialized.next = not initialized 124 | 125 | # Get an internal version of the pushbutton signal and debounce it. 126 | pb, pb_prev, pb_debounced = [Signal(bool(0)) for _ in range(3)] 127 | #pb_inst = input_pin(pb_i, pb, pullup=True) 128 | #pb_debouncer = debouncer(clk, pb, pb_debounced, dbnc_window_g=0.01) 129 | DEBOUNCE_INTERVAL = int(49) 130 | debounce_cntr = Signal(intbv(DEBOUNCE_INTERVAL - 1, 0, DEBOUNCE_INTERVAL)) 131 | 132 | @always_seq(clk.posedge, reset=None) 133 | def debounce_pb(): 134 | if pb_i != pb_prev: 135 | debounce_cntr.next = DEBOUNCE_INTERVAL - 1 136 | else: 137 | if debounce_cntr == 0: 138 | pb_debounced.next = pb_i 139 | debounce_cntr.next = 1 140 | else: 141 | debounce_cntr.next = debounce_cntr - 1 142 | pb_prev.next = pb_i 143 | 144 | reset = Signal(bool(False)) 145 | 146 | @always_comb 147 | def reset_logic(): 148 | # Reset if not initialized upon startup or if pushbutton is pressed (low). 149 | reset.next = not initialized or not pb_debounced 150 | 151 | test_status = Signal(intbv(0)[8:]) 152 | host_intf_inst = host_intf() 153 | memory_test_inst = memory_test(clk, reset, test_status, led_status, host_intf_inst) 154 | sdramCntl_inst = MySdramCntl(clk, host_intf_inst, sd_intf) 155 | 156 | # LED display for showing test status. 157 | # space = 0x20 # ASCII code for space character. 158 | # led_disp_drvrs = [TristateSignal(bool(0)) for _ in range(8)] 159 | # led_disp_inst = led_digits_display( 160 | # led_disp_drvrs[0], led_disp_drvrs[1], led_disp_drvrs[2], 161 | # led_disp_drvrs[3], led_disp_drvrs[4], led_disp_drvrs[5], 162 | # led_disp_drvrs[6], led_disp_drvrs[7], clk, test_status, space, space, 163 | # space, space, space, space, space, enable_ascii_to_7seg=True) 164 | 165 | # @always_comb 166 | # def led_disp_connect(): 167 | # led_disp_d0_o.next = led_disp_drvrs[0] 168 | # led_disp_d1_o.next = led_disp_drvrs[1] 169 | # led_disp_d2_o.next = led_disp_drvrs[2] 170 | # led_disp_d3_o.next = led_disp_drvrs[3] 171 | # led_disp_d4_o.next = led_disp_drvrs[4] 172 | # led_disp_d5_o.next = led_disp_drvrs[5] 173 | # led_disp_d6_o.next = led_disp_drvrs[6] 174 | # led_disp_d7_o.next = led_disp_drvrs[7] 175 | 176 | return instances() 177 | 178 | 179 | def sdram_test_tb(): 180 | clk, sdram_clk, sdram_return_clk = [Signal(bool(0)) for _ in range(3)] 181 | 182 | @always_comb 183 | def sdram_clk_loopback(): 184 | sdram_return_clk.next = sdram_clk 185 | 186 | drvrs = [TristateSignal(bool(0)) for _ in range(8)] 187 | led_status = Signal(intbv(0,0,16)) 188 | pb = Signal(bool(1)) 189 | sd_intf_inst = sd_intf() 190 | sdram_inst = sdram(sdram_clk, sd_intf_inst, show_command=False) 191 | dut = sdram_test(clk, sdram_clk, sdram_return_clk, drvrs[0].driver(), 192 | drvrs[1].driver(), drvrs[2].driver(), drvrs[3].driver(), 193 | drvrs[4].driver(), drvrs[5].driver(), drvrs[6].driver(), 194 | drvrs[7].driver(), led_status, pb, sd_intf_inst) 195 | 196 | @instance 197 | def clk_gen(): 198 | yield delay(140) 199 | for _ in range(6000): 200 | clk.next = not clk 201 | yield delay(1) 202 | pb.next = 0 203 | for _ in range(100): 204 | clk.next = not clk 205 | yield delay(1) 206 | pb.next = 1 207 | for _ in range(6000): 208 | clk.next = not clk 209 | yield delay(1) 210 | raise StopSimulation 211 | 212 | return instances() 213 | 214 | 215 | if __name__ == '__main__': 216 | # Simulation(traceSignals(sdram_test_tb)).run() 217 | 218 | clk, sdram_clk, sdram_return_clk = [Signal(bool(0)) for _ in range(3)] 219 | d0, d1, d2, d3, d4, d5, d6, d7 = [TristateSignal(bool(0)) 220 | for _ in range(8)] 221 | led_status = Signal(intbv(0,0,16)) 222 | pb = Signal(bool(1)) 223 | sd_intf_inst = sd_intf() 224 | toVerilog(sdram_test, clk, sdram_clk, sdram_return_clk, d0.driver(), 225 | d1.driver(), d2.driver(), d3.driver(), 226 | d4.driver(), d5.driver(), d6.driver(), 227 | d7.driver(), led_status, pb, sd_intf_inst) 228 | -------------------------------------------------------------------------------- /tests/sdram_test.v: -------------------------------------------------------------------------------- 1 | // File: sdram_test.v 2 | // Generated by MyHDL 0.11.45 3 | // Date: Tue Feb 27 11:28:48 2024 4 | 5 | 6 | `timescale 1ns/10ps 7 | 8 | module sdram_test ( 9 | master_clk_i, 10 | sdram_clk_o, 11 | sdram_clk_i, 12 | led_disp_d0_o, 13 | led_disp_d1_o, 14 | led_disp_d2_o, 15 | led_disp_d3_o, 16 | led_disp_d4_o, 17 | led_disp_d5_o, 18 | led_disp_d6_o, 19 | led_disp_d7_o, 20 | led_status, 21 | pb_i, 22 | sd_intf_cke, 23 | sd_intf_cs, 24 | sd_intf_cas, 25 | sd_intf_ras, 26 | sd_intf_we, 27 | sd_intf_bs, 28 | sd_intf_addr, 29 | sd_intf_dqml, 30 | sd_intf_dqmh, 31 | sd_intf_dq 32 | ); 33 | 34 | 35 | input master_clk_i; 36 | output sdram_clk_o; 37 | wire sdram_clk_o; 38 | input sdram_clk_i; 39 | input led_disp_d0_o; 40 | input led_disp_d1_o; 41 | input led_disp_d2_o; 42 | input led_disp_d3_o; 43 | input led_disp_d4_o; 44 | input led_disp_d5_o; 45 | input led_disp_d6_o; 46 | input led_disp_d7_o; 47 | output [3:0] led_status; 48 | reg [3:0] led_status; 49 | input pb_i; 50 | output sd_intf_cke; 51 | reg sd_intf_cke; 52 | output sd_intf_cs; 53 | reg sd_intf_cs; 54 | output sd_intf_cas; 55 | reg sd_intf_cas; 56 | output sd_intf_ras; 57 | reg sd_intf_ras; 58 | output sd_intf_we; 59 | reg sd_intf_we; 60 | output [1:0] sd_intf_bs; 61 | reg [1:0] sd_intf_bs; 62 | output [12:0] sd_intf_addr; 63 | reg [12:0] sd_intf_addr; 64 | output sd_intf_dqml; 65 | reg sd_intf_dqml; 66 | output sd_intf_dqmh; 67 | reg sd_intf_dqmh; 68 | inout [15:0] sd_intf_dq; 69 | wire [15:0] sd_intf_dq; 70 | 71 | wire clk; 72 | reg initialized; 73 | reg [5:0] debounce_cntr; 74 | reg pb_debounced; 75 | reg pb_prev; 76 | wire reset; 77 | reg [7:0] test_status; 78 | reg sdramCntl_inst_activateInProgress_s; 79 | reg [1:0] sdramCntl_inst_activeBank_r; 80 | reg [1:0] sdramCntl_inst_activeBank_x; 81 | reg [1:0] sdramCntl_inst_ba_r; 82 | wire [1:0] sdramCntl_inst_ba_x; 83 | wire [1:0] sdramCntl_inst_bank_s; 84 | reg [2:0] sdramCntl_inst_cmd_r; 85 | reg [2:0] sdramCntl_inst_cmd_x; 86 | wire [8:0] sdramCntl_inst_col_s; 87 | reg sdramCntl_inst_doActivate_s; 88 | reg [2:0] sdramCntl_inst_rasTimer_r; 89 | reg [2:0] sdramCntl_inst_rasTimer_x; 90 | reg sdramCntl_inst_rdInProgress_s; 91 | reg [4:0] sdramCntl_inst_rdPipeline_r; 92 | reg [4:0] sdramCntl_inst_rdPipeline_x; 93 | reg [9:0] sdramCntl_inst_refTimer_r; 94 | reg [9:0] sdramCntl_inst_refTimer_x; 95 | reg [13:0] sdramCntl_inst_rfshCntr_r; 96 | reg [13:0] sdramCntl_inst_rfshCntr_x; 97 | wire [12:0] sdramCntl_inst_row_s; 98 | reg [12:0] sdramCntl_inst_sAddr_r; 99 | reg [12:0] sdramCntl_inst_sAddr_x; 100 | reg sdramCntl_inst_sDataDir_r; 101 | reg sdramCntl_inst_sDataDir_x; 102 | reg [15:0] sdramCntl_inst_sData_r; 103 | wire [15:0] sdramCntl_inst_sData_x; 104 | reg [15:0] sdramCntl_inst_sDriver; 105 | reg [15:0] sdramCntl_inst_sdramData_r; 106 | reg [15:0] sdramCntl_inst_sdramData_x; 107 | reg [2:0] sdramCntl_inst_state_r; 108 | reg [2:0] sdramCntl_inst_state_x; 109 | reg [10:0] sdramCntl_inst_timer_r; 110 | reg [10:0] sdramCntl_inst_timer_x; 111 | reg [4:0] sdramCntl_inst_wrPipeline_r; 112 | reg [4:0] sdramCntl_inst_wrPipeline_x; 113 | reg [1:0] sdramCntl_inst_wrTimer_r; 114 | reg [1:0] sdramCntl_inst_wrTimer_x; 115 | reg sdramCntl_inst_writeInProgress_s; 116 | wire sdramCntl_inst_host_intf_rd_i; 117 | wire sdramCntl_inst_host_intf_wr_i; 118 | wire sdramCntl_inst_host_intf_done_o; 119 | wire [15:0] sdramCntl_inst_host_intf_data_o; 120 | wire sdramCntl_inst_host_intf_rdPending_o; 121 | wire [15:0] sdramCntl_inst_host_intf_data_i; 122 | wire [23:0] sdramCntl_inst_host_intf_addr_i; 123 | reg [26:0] memory_test_inst_address; 124 | reg memory_test_inst_error; 125 | reg memory_test_inst_rand_enable; 126 | reg memory_test_inst_rand_load; 127 | wire [15:0] memory_test_inst_rand_val; 128 | reg memory_test_inst_rd_enable; 129 | reg [1:0] memory_test_inst_test_state; 130 | reg memory_test_inst_wr_enable; 131 | wire memory_test_inst_host_intf_rst_i; 132 | reg [15:0] memory_test_inst_rand_gen_shfreg; 133 | reg sdramCntl_inst_activeFlag_r [0:4-1]; 134 | reg sdramCntl_inst_activeFlag_x [0:4-1]; 135 | reg [12:0] sdramCntl_inst_activeRow_r [0:4-1]; 136 | reg [12:0] sdramCntl_inst_activeRow_x [0:4-1]; 137 | 138 | assign sd_intf_dq = sdramCntl_inst_sDriver; 139 | 140 | 141 | 142 | assign sdram_clk_o = master_clk_i; 143 | assign clk = sdram_clk_i; 144 | 145 | 146 | always @(posedge clk) begin: SDRAM_TEST_INTERNAL_RESET 147 | if ((initialized == 1'b0)) begin 148 | initialized <= (!initialized); 149 | end 150 | end 151 | 152 | 153 | always @(posedge clk) begin: SDRAM_TEST_DEBOUNCE_PB 154 | if ((pb_i != pb_prev)) begin 155 | debounce_cntr <= (49 - 1); 156 | end 157 | else begin 158 | if ((debounce_cntr == 0)) begin 159 | pb_debounced <= pb_i; 160 | debounce_cntr <= 1; 161 | end 162 | else begin 163 | debounce_cntr <= (debounce_cntr - 1); 164 | end 165 | end 166 | pb_prev <= pb_i; 167 | end 168 | 169 | 170 | 171 | assign reset = ((!initialized) || (!pb_debounced)); 172 | 173 | 174 | always @(posedge clk) begin: SDRAM_TEST_MEMORY_TEST_INST_RAND_GEN_RAND_SHIFT 175 | integer bits; 176 | integer xor_bit; 177 | integer i; 178 | bits = (memory_test_inst_rand_gen_shfreg & 53256); 179 | xor_bit = 0; 180 | for (i=0; i<16; i=i+1) begin 181 | xor_bit = (xor_bit ^ bits[i]); 182 | end 183 | if (memory_test_inst_rand_load) begin 184 | memory_test_inst_rand_gen_shfreg <= 42; 185 | end 186 | else if (memory_test_inst_rand_enable) begin 187 | memory_test_inst_rand_gen_shfreg[16-1:1] <= memory_test_inst_rand_gen_shfreg[(16 - 1)-1:0]; 188 | memory_test_inst_rand_gen_shfreg[0] <= xor_bit; 189 | end 190 | end 191 | 192 | 193 | 194 | assign memory_test_inst_rand_val = memory_test_inst_rand_gen_shfreg; 195 | 196 | 197 | always @(posedge clk) begin: SDRAM_TEST_MEMORY_TEST_INST_SDRAM_TESTER 198 | if ((reset == 1'b1)) begin 199 | memory_test_inst_error <= 1'b0; 200 | memory_test_inst_test_state <= 2'b01; 201 | test_status <= 49; 202 | led_status <= 4'h1; 203 | memory_test_inst_address <= 0; 204 | memory_test_inst_rand_load <= 1; 205 | end 206 | else if ((memory_test_inst_test_state == 2'b01)) begin 207 | memory_test_inst_rand_load <= 0; 208 | memory_test_inst_rand_enable <= 0; 209 | test_status <= 50; 210 | led_status <= 4'h2; 211 | if ((sdramCntl_inst_host_intf_done_o == 1'b0)) begin 212 | memory_test_inst_wr_enable <= 1'b1; 213 | end 214 | else begin 215 | memory_test_inst_wr_enable <= 1'b0; 216 | memory_test_inst_rand_enable <= 1; 217 | memory_test_inst_address <= (memory_test_inst_address + 1); 218 | if ((memory_test_inst_address == 16777215)) begin 219 | memory_test_inst_test_state <= 2'b10; 220 | memory_test_inst_address <= 0; 221 | memory_test_inst_rand_load <= 1; 222 | memory_test_inst_error <= 1'b0; 223 | end 224 | end 225 | end 226 | else if ((memory_test_inst_test_state == 2'b10)) begin 227 | memory_test_inst_rand_load <= 0; 228 | memory_test_inst_rand_enable <= 0; 229 | test_status <= 51; 230 | led_status <= 4'h4; 231 | if ((sdramCntl_inst_host_intf_done_o == 1'b0)) begin 232 | memory_test_inst_rd_enable <= 1'b1; 233 | end 234 | else begin 235 | memory_test_inst_rd_enable <= 1'b0; 236 | memory_test_inst_rand_enable <= 1; 237 | memory_test_inst_address <= (memory_test_inst_address + 1); 238 | if ((memory_test_inst_rand_val != sdramCntl_inst_host_intf_data_o)) begin 239 | memory_test_inst_error <= 1'b1; 240 | end 241 | if ((memory_test_inst_address == 16777215)) begin 242 | memory_test_inst_test_state <= 2'b11; 243 | end 244 | end 245 | end 246 | else begin 247 | memory_test_inst_rand_load <= 0; 248 | memory_test_inst_rand_enable <= 0; 249 | if ((memory_test_inst_error == 1'b1)) begin 250 | test_status <= 70; 251 | led_status <= 4'h8; 252 | end 253 | else begin 254 | test_status <= 79; 255 | led_status <= 4'hf; 256 | end 257 | end 258 | end 259 | 260 | 261 | 262 | assign memory_test_inst_host_intf_rst_i = reset; 263 | assign sdramCntl_inst_host_intf_wr_i = (memory_test_inst_wr_enable && (!sdramCntl_inst_host_intf_done_o)); 264 | assign sdramCntl_inst_host_intf_rd_i = (memory_test_inst_rd_enable && (!sdramCntl_inst_host_intf_done_o)); 265 | assign sdramCntl_inst_host_intf_data_i = memory_test_inst_rand_val; 266 | assign sdramCntl_inst_host_intf_addr_i = memory_test_inst_address; 267 | 268 | 269 | always @(sdramCntl_inst_bank_s, sdramCntl_inst_doActivate_s, sdramCntl_inst_activeBank_r, sdramCntl_inst_host_intf_wr_i, sdramCntl_inst_refTimer_r, sdramCntl_inst_sAddr_r, sdramCntl_inst_ba_r, sdramCntl_inst_wrTimer_r, sdramCntl_inst_sDataDir_r, sdramCntl_inst_writeInProgress_s, sdramCntl_inst_rasTimer_r, sdramCntl_inst_activateInProgress_s, sdramCntl_inst_host_intf_rd_i, sdramCntl_inst_rfshCntr_r, sdramCntl_inst_state_r, sdramCntl_inst_activeFlag_r[0], sdramCntl_inst_activeFlag_r[1], sdramCntl_inst_activeFlag_r[2], sdramCntl_inst_activeFlag_r[3], sdramCntl_inst_activeRow_r[0], sdramCntl_inst_activeRow_r[1], sdramCntl_inst_activeRow_r[2], sdramCntl_inst_activeRow_r[3], sdramCntl_inst_rdPipeline_r, sdramCntl_inst_timer_r, sdramCntl_inst_row_s, sdramCntl_inst_ba_x, sdramCntl_inst_col_s, sdramCntl_inst_rdInProgress_s) begin: SDRAM_TEST_SDRAMCNTL_INST_COMB_FUNC 270 | integer index; 271 | sdramCntl_inst_rdPipeline_x = {1'b0, sdramCntl_inst_rdPipeline_r[(3 + 2)-1:1]}; 272 | sdramCntl_inst_wrPipeline_x = 5'h0; 273 | if ((sdramCntl_inst_rasTimer_r != 0)) begin 274 | sdramCntl_inst_rasTimer_x = (sdramCntl_inst_rasTimer_r - 1); 275 | end 276 | else begin 277 | sdramCntl_inst_rasTimer_x = sdramCntl_inst_rasTimer_r; 278 | end 279 | if ((sdramCntl_inst_wrTimer_r != 0)) begin 280 | sdramCntl_inst_wrTimer_x = (sdramCntl_inst_wrTimer_r - 1); 281 | end 282 | else begin 283 | sdramCntl_inst_wrTimer_x = sdramCntl_inst_wrTimer_r; 284 | end 285 | if ((sdramCntl_inst_refTimer_r != 0)) begin 286 | sdramCntl_inst_refTimer_x = (sdramCntl_inst_refTimer_r - 1); 287 | sdramCntl_inst_rfshCntr_x = sdramCntl_inst_rfshCntr_r; 288 | end 289 | else begin 290 | sdramCntl_inst_refTimer_x = 782; 291 | sdramCntl_inst_rfshCntr_x = (sdramCntl_inst_rfshCntr_r + 1); 292 | end 293 | sdramCntl_inst_cmd_x = 7; 294 | sdramCntl_inst_state_x = sdramCntl_inst_state_r; 295 | sdramCntl_inst_sAddr_x = sdramCntl_inst_sAddr_r; 296 | sdramCntl_inst_activeBank_x = sdramCntl_inst_activeBank_r; 297 | sdramCntl_inst_sDataDir_x = sdramCntl_inst_sDataDir_r; 298 | for (index=0; index<(2 ** 2); index=index+1) begin 299 | sdramCntl_inst_activeFlag_x[index] = sdramCntl_inst_activeFlag_r[index]; 300 | sdramCntl_inst_activeRow_x[index] = sdramCntl_inst_activeRow_r[index]; 301 | end 302 | if ((sdramCntl_inst_timer_r != 0)) begin 303 | sdramCntl_inst_timer_x = (sdramCntl_inst_timer_r - 1); 304 | sdramCntl_inst_cmd_x = 7; 305 | end 306 | else begin 307 | sdramCntl_inst_timer_x = sdramCntl_inst_timer_r; 308 | case (sdramCntl_inst_state_r) 309 | 3'b000: begin 310 | sdramCntl_inst_timer_x = 2000; 311 | sdramCntl_inst_state_x = 3'b001; 312 | end 313 | 3'b001: begin 314 | sdramCntl_inst_cmd_x = 2; 315 | sdramCntl_inst_timer_x = 2; 316 | sdramCntl_inst_state_x = 3'b011; 317 | sdramCntl_inst_sAddr_x = 512; 318 | sdramCntl_inst_rfshCntr_x = 8; 319 | end 320 | 3'b011: begin 321 | sdramCntl_inst_cmd_x = 1; 322 | sdramCntl_inst_timer_x = 7; 323 | sdramCntl_inst_rfshCntr_x = (sdramCntl_inst_rfshCntr_r - 1); 324 | if ((sdramCntl_inst_rfshCntr_r == 1)) begin 325 | sdramCntl_inst_state_x = 3'b010; 326 | end 327 | end 328 | 3'b010: begin 329 | sdramCntl_inst_cmd_x = 0; 330 | sdramCntl_inst_timer_x = 2; 331 | sdramCntl_inst_state_x = 3'b100; 332 | sdramCntl_inst_sAddr_x = 48; 333 | end 334 | 3'b100: begin 335 | if ((sdramCntl_inst_rfshCntr_r != 0)) begin 336 | if (((sdramCntl_inst_activateInProgress_s == 1'b0) && (sdramCntl_inst_writeInProgress_s == 1'b0) && (sdramCntl_inst_rdInProgress_s == 1'b0))) begin 337 | sdramCntl_inst_cmd_x = 2; 338 | sdramCntl_inst_timer_x = 2; 339 | sdramCntl_inst_state_x = 3'b110; 340 | sdramCntl_inst_sAddr_x = 512; 341 | for (index=0; index<(2 ** 2); index=index+1) begin 342 | sdramCntl_inst_activeFlag_x[index] = 1'b0; 343 | end 344 | end 345 | end 346 | else if ((sdramCntl_inst_host_intf_rd_i == 1'b1)) begin 347 | if ((sdramCntl_inst_ba_x == sdramCntl_inst_ba_r)) begin 348 | if ((sdramCntl_inst_doActivate_s == 1'b1)) begin 349 | if (((sdramCntl_inst_activateInProgress_s == 1'b0) && (sdramCntl_inst_writeInProgress_s == 1'b0) && (sdramCntl_inst_rdInProgress_s == 1'b0))) begin 350 | sdramCntl_inst_cmd_x = 2; 351 | sdramCntl_inst_timer_x = 2; 352 | sdramCntl_inst_state_x = 3'b101; 353 | sdramCntl_inst_sAddr_x = 0; 354 | sdramCntl_inst_activeFlag_x[sdramCntl_inst_bank_s] = 1'b0; 355 | end 356 | end 357 | else if ((sdramCntl_inst_rdInProgress_s == 1'b0)) begin 358 | sdramCntl_inst_cmd_x = 5; 359 | sdramCntl_inst_sDataDir_x = 1'b0; 360 | sdramCntl_inst_sAddr_x = sdramCntl_inst_col_s; 361 | sdramCntl_inst_rdPipeline_x = {1'b1, sdramCntl_inst_rdPipeline_r[(3 + 2)-1:1]}; 362 | end 363 | end 364 | end 365 | else if ((sdramCntl_inst_host_intf_wr_i == 1'b1)) begin 366 | if ((sdramCntl_inst_ba_x == sdramCntl_inst_ba_r)) begin 367 | if ((sdramCntl_inst_doActivate_s == 1'b1)) begin 368 | if (((sdramCntl_inst_activateInProgress_s == 1'b0) && (sdramCntl_inst_writeInProgress_s == 1'b0) && (sdramCntl_inst_rdInProgress_s == 1'b0))) begin 369 | sdramCntl_inst_cmd_x = 2; 370 | sdramCntl_inst_timer_x = 2; 371 | sdramCntl_inst_state_x = 3'b101; 372 | sdramCntl_inst_sAddr_x = 0; 373 | sdramCntl_inst_activeFlag_x[sdramCntl_inst_bank_s] = 1'b0; 374 | end 375 | end 376 | else if ((sdramCntl_inst_rdInProgress_s == 1'b0)) begin 377 | sdramCntl_inst_cmd_x = 4; 378 | sdramCntl_inst_sDataDir_x = 1'b1; 379 | sdramCntl_inst_sAddr_x = sdramCntl_inst_col_s; 380 | sdramCntl_inst_wrPipeline_x = 5'h1; 381 | sdramCntl_inst_wrTimer_x = 2; 382 | end 383 | end 384 | end 385 | else begin 386 | sdramCntl_inst_cmd_x = 7; 387 | sdramCntl_inst_state_x = 3'b100; 388 | end 389 | end 390 | 3'b101: begin 391 | sdramCntl_inst_cmd_x = 3; 392 | sdramCntl_inst_timer_x = 2; 393 | sdramCntl_inst_state_x = 3'b100; 394 | sdramCntl_inst_rasTimer_x = 5; 395 | sdramCntl_inst_sAddr_x = sdramCntl_inst_row_s; 396 | sdramCntl_inst_activeBank_x = sdramCntl_inst_bank_s; 397 | sdramCntl_inst_activeRow_x[sdramCntl_inst_bank_s] = sdramCntl_inst_row_s; 398 | sdramCntl_inst_activeFlag_x[sdramCntl_inst_bank_s] = 1'b1; 399 | end 400 | 3'b110: begin 401 | sdramCntl_inst_cmd_x = 1; 402 | sdramCntl_inst_timer_x = 7; 403 | sdramCntl_inst_state_x = 3'b100; 404 | sdramCntl_inst_rfshCntr_x = (sdramCntl_inst_rfshCntr_r - 1); 405 | end 406 | default: begin 407 | sdramCntl_inst_state_x = 3'b000; 408 | end 409 | endcase 410 | end 411 | end 412 | 413 | 414 | always @(posedge clk, posedge memory_test_inst_host_intf_rst_i) begin: SDRAM_TEST_SDRAMCNTL_INST_SEQ_FUNC 415 | integer index; 416 | if (memory_test_inst_host_intf_rst_i == 1) begin 417 | sdramCntl_inst_sAddr_r <= 0; 418 | sdramCntl_inst_activeFlag_r[0] <= 0; 419 | sdramCntl_inst_activeFlag_r[1] <= 0; 420 | sdramCntl_inst_activeFlag_r[2] <= 0; 421 | sdramCntl_inst_activeFlag_r[3] <= 0; 422 | sdramCntl_inst_rfshCntr_r <= 0; 423 | sdramCntl_inst_activeRow_r[0] <= 0; 424 | sdramCntl_inst_activeRow_r[1] <= 0; 425 | sdramCntl_inst_activeRow_r[2] <= 0; 426 | sdramCntl_inst_activeRow_r[3] <= 0; 427 | sdramCntl_inst_ba_r <= 0; 428 | sdramCntl_inst_wrTimer_r <= 0; 429 | sdramCntl_inst_sDataDir_r <= 0; 430 | sdramCntl_inst_activeBank_r <= 0; 431 | sdramCntl_inst_rdPipeline_r <= 0; 432 | sdramCntl_inst_timer_r <= 0; 433 | sdramCntl_inst_rasTimer_r <= 0; 434 | sdramCntl_inst_refTimer_r <= 782; 435 | sdramCntl_inst_state_r <= 3'b000; 436 | sdramCntl_inst_sdramData_r <= 0; 437 | sdramCntl_inst_wrPipeline_r <= 0; 438 | sdramCntl_inst_sData_r <= 0; 439 | sdramCntl_inst_cmd_r <= 7; 440 | end 441 | else begin 442 | sdramCntl_inst_state_r <= sdramCntl_inst_state_x; 443 | sdramCntl_inst_cmd_r <= sdramCntl_inst_cmd_x; 444 | sdramCntl_inst_sAddr_r <= sdramCntl_inst_sAddr_x; 445 | sdramCntl_inst_sData_r <= sdramCntl_inst_sData_x; 446 | sdramCntl_inst_sDataDir_r <= sdramCntl_inst_sDataDir_x; 447 | sdramCntl_inst_activeBank_r <= sdramCntl_inst_activeBank_x; 448 | sdramCntl_inst_sdramData_r <= sdramCntl_inst_sdramData_x; 449 | sdramCntl_inst_wrPipeline_r <= sdramCntl_inst_wrPipeline_x; 450 | sdramCntl_inst_rdPipeline_r <= sdramCntl_inst_rdPipeline_x; 451 | sdramCntl_inst_ba_r <= sdramCntl_inst_ba_x; 452 | sdramCntl_inst_timer_r <= sdramCntl_inst_timer_x; 453 | sdramCntl_inst_rasTimer_r <= sdramCntl_inst_rasTimer_x; 454 | sdramCntl_inst_refTimer_r <= sdramCntl_inst_refTimer_x; 455 | sdramCntl_inst_wrTimer_r <= sdramCntl_inst_wrTimer_x; 456 | sdramCntl_inst_rfshCntr_r <= sdramCntl_inst_rfshCntr_x; 457 | for (index=0; index<(2 ** 2); index=index+1) begin 458 | sdramCntl_inst_activeRow_r[index] <= sdramCntl_inst_activeRow_x[index]; 459 | sdramCntl_inst_activeFlag_r[index] <= sdramCntl_inst_activeFlag_x[index]; 460 | end 461 | end 462 | end 463 | 464 | 465 | always @(sdramCntl_inst_sAddr_r, sdramCntl_inst_bank_s, sdramCntl_inst_sDataDir_r, sdramCntl_inst_sData_r, sdramCntl_inst_cmd_r) begin: SDRAM_TEST_SDRAMCNTL_INST_SDRAM_PIN_MAP 466 | sd_intf_cke = 1; 467 | sd_intf_cs = 0; 468 | sd_intf_ras = sdramCntl_inst_cmd_r[2]; 469 | sd_intf_cas = sdramCntl_inst_cmd_r[1]; 470 | sd_intf_we = sdramCntl_inst_cmd_r[0]; 471 | sd_intf_bs = sdramCntl_inst_bank_s; 472 | sd_intf_addr = sdramCntl_inst_sAddr_r; 473 | if ((sdramCntl_inst_sDataDir_r == 1'b1)) begin 474 | sdramCntl_inst_sDriver = sdramCntl_inst_sData_r; 475 | end 476 | else begin 477 | sdramCntl_inst_sDriver = 'bz; 478 | end 479 | sd_intf_dqml = 0; 480 | sd_intf_dqmh = 0; 481 | end 482 | 483 | 484 | 485 | assign sdramCntl_inst_host_intf_done_o = (sdramCntl_inst_rdPipeline_r[0] || sdramCntl_inst_wrPipeline_r[0]); 486 | assign sdramCntl_inst_host_intf_data_o = sdramCntl_inst_sdramData_r; 487 | assign sdramCntl_inst_host_intf_rdPending_o = sdramCntl_inst_rdInProgress_s; 488 | assign sdramCntl_inst_sData_x = sdramCntl_inst_host_intf_data_i; 489 | 490 | 491 | 492 | assign sdramCntl_inst_bank_s = sdramCntl_inst_host_intf_addr_i[((2 + 13) + 9)-1:(13 + 9)]; 493 | assign sdramCntl_inst_ba_x = sdramCntl_inst_host_intf_addr_i[((2 + 13) + 9)-1:(13 + 9)]; 494 | assign sdramCntl_inst_row_s = sdramCntl_inst_host_intf_addr_i[(13 + 9)-1:9]; 495 | assign sdramCntl_inst_col_s = sdramCntl_inst_host_intf_addr_i[9-1:0]; 496 | 497 | 498 | always @(sdramCntl_inst_bank_s, sdramCntl_inst_activeFlag_r[0], sdramCntl_inst_activeFlag_r[1], sdramCntl_inst_activeFlag_r[2], sdramCntl_inst_activeFlag_r[3], sdramCntl_inst_activeRow_r[0], sdramCntl_inst_activeRow_r[1], sdramCntl_inst_activeRow_r[2], sdramCntl_inst_activeRow_r[3], sd_intf_dq, sdramCntl_inst_wrTimer_r, sdramCntl_inst_activeBank_r, sdramCntl_inst_rdPipeline_r, sdramCntl_inst_rasTimer_r, sdramCntl_inst_sdramData_r, sdramCntl_inst_row_s) begin: SDRAM_TEST_SDRAMCNTL_INST_DO_ACTIVE 499 | if (((sdramCntl_inst_bank_s != sdramCntl_inst_activeBank_r) || (sdramCntl_inst_row_s != sdramCntl_inst_activeRow_r[sdramCntl_inst_bank_s]) || (sdramCntl_inst_activeFlag_r[sdramCntl_inst_bank_s] == 1'b0))) begin 500 | sdramCntl_inst_doActivate_s = 1'b1; 501 | end 502 | else begin 503 | sdramCntl_inst_doActivate_s = 1'b0; 504 | end 505 | if ((sdramCntl_inst_rdPipeline_r[1] == 1'b1)) begin 506 | sdramCntl_inst_sdramData_x = sd_intf_dq; 507 | end 508 | else begin 509 | sdramCntl_inst_sdramData_x = sdramCntl_inst_sdramData_r; 510 | end 511 | if ((sdramCntl_inst_rasTimer_r != 0)) begin 512 | sdramCntl_inst_activateInProgress_s = 1'b1; 513 | end 514 | else begin 515 | sdramCntl_inst_activateInProgress_s = 1'b0; 516 | end 517 | if ((sdramCntl_inst_wrTimer_r != 0)) begin 518 | sdramCntl_inst_writeInProgress_s = 1'b1; 519 | end 520 | else begin 521 | sdramCntl_inst_writeInProgress_s = 1'b0; 522 | end 523 | if ((sdramCntl_inst_rdPipeline_r[(3 + 2)-1:1] != 0)) begin 524 | sdramCntl_inst_rdInProgress_s = 1'b1; 525 | end 526 | else begin 527 | sdramCntl_inst_rdInProgress_s = 1'b0; 528 | end 529 | end 530 | 531 | endmodule 532 | --------------------------------------------------------------------------------