| @ -0,0 +1,13 @@ | |||
| DOC := qz2021_-_using_python_for_verification_of_digital_systems.md | |||
| PDF := $(DOC:.md=.pdf) | |||
| .PHONY: all | |||
| all: $(PDF) | |||
| %.pdf: %.md template/template.tex images/* | |||
| pandoc -t beamer --pdf-engine xelatex --listings --template=template/template.tex $< -o $@ | |||
| .PHONY: clean | |||
| clean: | |||
| rm -rf $(PDF) | |||
| @ -0,0 +1 @@ | |||
| <mxfile host="Electron" modified="2022-02-10T13:58:48.700Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="DX6n_f_eDgUMa4p41MyS" version="16.5.1" type="device"><diagram id="vomTti7XoeUnKlfPLwag" name="Page-1">7ZpZb9s4EIB/jYHuQwrdlh8bO012kwLBeutN9qVgJFpiS4suRcV2f/2SEmlJpny0lqIibQIE4vD+ZjjDIwN7vFhfU7CMP5AQ4oFlhOuBPRlYlmcb/K8QbAqB63uFIKIoLERmKZiib1AKZb0oQyFMawUZIZihZV0YkCSBAavJAKVkVS82J7je6xJEUBNMA4B16b8oZLGUeoZRZtxAFMWqa0vlLIAqLQVpDEKyqojsq4E9poSw4muxHkMs4CkwRb33e3K3I6MwYadUwF8vJ1n64e+Pn9AnY2OsHu7+G19YRSvPAGdyxlO0yDBghMpRs41iQUmWhFC0Zg7sy1WMGJwuQSByV1z5XBazBZbZz5AyxDm+wyhKuIwRUUAfs5yGKA7XFZGcwzUkC8johheRuY4CLC3KUXxXFf2MpCyuqsaVQiBtItq2XVLjHxLcd0C0NYiTj/8MLA/zni+fOEgvEl9vZjeTu4HF+zBmkCJMoj8OMDaOM54jjMcEc1WJunboQj90uDxllHyBlRzferI9ryX+Tp2/azTwtxr4d4bf1fCPCefIUALb5QugPw+a+HqBD5/m7fA1zR37dnS+XgNeqyu8pqnxnd3c/3keWkoYYIgIz3AxMtohZ/u75FyNnO12Q+45+8uaecHt1+B2SDarh/TudnKhg7vfsJhP+izPWrXKhHAbP+xsNX4NlPciHfXpaxuZ6gFr1pEtngVOs0W/Z1vUY1Rni7hVcK7V9yIeHYFEKF/TEUkAviNi3eVoPkPGNnI7CzJG6uDgGrGHyvejaOotn2mRnKxl03lioxIJn85DXtJVycdqXlktT6l6KQOUvRN7YS4IMEhTFCjxe4TVmIpZwlDbD2seOSUZDeABZFI9vIMIsqORRTcFCvkGFD3XB9K+JzE0xYrZT2VSutaOdP2KVb3fbfemabNHTQ9/NVXbfapaPwtcnxvlGvZbbcQ5a2eDMNTjnNOws3K6inOeRq7nU9RZeLVT1PDlTlGNeIevGm/TJcCL4vVfN167Z7ymfzCClsHyqpS2F1DL7dJjJedYPK1F0zK4/jTx1HRODKhunwFVjbKysi5REqIkSttbWCGcgyy/Le3iSGmpe6ADZ/Hhi64mPdZOgxiGGYZUX2cYo2Uq1lMagyXMrZNk4XHA2/eG3Ly/QBbEW1sXvku9ZzR4ubkrfoWcJKwiL34avV/+05L32707aYjdfoO+urtz0oO3rqYk1L1H7a6kujZ+7FAYnu2I9j9f6Nqo0HYP0D7ZDcke7gniA9wq29t5ztm+GKomiuHLWqUitYbc4ageM9XFkWqo8LNaQ7lFbKd9hpHoW5BzjaSm8B8NbKcbytH7ml4NxVFV9un3VEPRHrDM0VvXellbGf0OAIeeGN2dANDwBNZSAODJ8gW+UG/5fwz21f8=</diagram></mxfile> | |||
| @ -0,0 +1 @@ | |||
| <mxfile host="Electron" modified="2022-02-10T16:20:18.510Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="MWMbJNU4ZVDDTQi6pcMl" version="16.5.1" type="device"><diagram id="vomTti7XoeUnKlfPLwag" name="Page-1">1VjbctowEP0aP5bxPfAI5NLOJDOZkLSkL4ywF1uNbFFZDqZfXwnL+AppA7lgZhjt2dXt7B5ZY80aR9kVQ8vwhvpANFP3M80610zzzDbEvwTWCtDPciBg2M8howQm+A8oUFdoin1IaoGcUsLxsg56NI7B4zUMMUZX9bAFJfVZlyiAFjDxEGmjP7DPQ4W6ul46vgIOwmJqs/BEqIhWQBIin64qkHWhWWNGKc9bUTYGIskriMn7Xe7wblfGIOb/0oH8Hp2nyc3dwwzP9LW+ml7/HH+x81GeEUnVjjkkfJYixnmm1s3XBRuMprEPcjxds0arEHOYLJEnvSuRfoGFPCLCMkSToDmQW5pgjmksME+sE5hwPAPjWFB83QiIsO/LmUaI4KCzx1A5OJVzLTAhY0oo2yzOWjjyJ3Ea8wqePwJPOKNPUPG4m0d42lQqduXEkFUgRe0V0Ag4W4sQ5bWKvKtCtwbKXpVlYxcxYaViTEeBSJVqsB27TKZoqHz+R26dVm5lWmea6RIx92jORCuQLQYeYLHVw/LdSIePoL/wOmn3+jBfHId2t0G77bRp73ew7r4V6YbZYhF8caQokzIe0oDGiFyU6KjOcxlzTWWhb9j9BZyv1fmIUk7r3EOG+VR27znKeqx4zjM18sZYF0Ys9jutGo/lCNIsu22sot/OrCU0ZR7s4cZVBzhiAfA9caaVB0ri9hYBA4K4qNz6sd+RUtX1lmKx5lKzzqA3EBW0fexaLTlnes+yBuVTHz/fhhqyUTXbNb6+kNyWep8RnvnsRIVqmZ9NqPZHCtWoyLQU7S6h+kN5lRFmTGPIkUsst7vxJ6ISeRHhEZQk2CtgFWYcpNtCjy8K13kf3bq23uvQquvs1Gq+xTfTakFQRazjELynk1SqbdeV6rhtpRrme0rVbLE7wVEqSoju49d4md/ue+UxOGyedmYHh24Hh4bxViS2S/RBnA/3B17ymxXqQN+3uyq0b86tY921mxXa9S553wrtt8j9Pvx2Ou+Xz3oRPPo98KAkD9oKGt7dn0qWX5+tD3v778iWMMuvJvkrvPz2ZF38BQ==</diagram></mxfile> | |||
| @ -0,0 +1 @@ | |||
| <mxfile host="Electron" modified="2022-02-11T11:50:12.021Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="5KG1EeJpEw0BMWRu-WNY" version="16.5.1" type="device"><diagram id="nl_DDaarRVB9L5eDG9c8" name="Page-1">5Vpdc6MgFP01mdl96Iwf0SSPbdpu+9DZneZhn4lQZRbFRWyS/fULClHRJmmaptY+BS5wuZ5zuAJm5M7j9Q8G0uiBQkRGjgXXI/d65Di2bTniR1o2ymI5XmkJGYbKVhkW+B/SHZU1xxBljY6cUsJx2jQGNElQwBs2wBhdNbs9UdKcNQUhahkWASBt628MeaSsvmVVDXcIh5Ge2tEtMdC9lSGLAKSrmsm9GblzRikvS/F6joiETwNTjrt9oXUbGUMJP2TA7QO5h6uUs7vl4u7eiZcXs/RCeXkGJFdPrILlGw2BiDuVRTETx4A8CphBEsrWq1WEOVqkIJDtKyEBYYt4TETNFsUl5ZzGomKJClMgyfITJmROCWWintBEulJxIMbR+sUHtLewCcUhGiPONqLLestKOUSJzdX1VcXcVJmiGmfaBpRWwq3nCk1RUIC+AtzxgMB1nZ6B6w0I3PG0Z+D6AwLXH/cM3ElfwIWYCceYJoWJSTBOAbjXtzw8HTjgY6tngM8GDrjTt5Sit8uDRXzSt+2H7exHHCXwUp5BKnRqoDKaJxBBhWQ5FsHWaWQvQDUAvA4AtI0hAjh+brrvQkXN8ItiMfGL27/tAUi7yGjOAqRG1U8hpiOv6cgzY+GAhYi3HBUkbR/7Dby5X4o3z8hU3mx2HG+ebfJmnZe3Aw5TQ+JtH9zHr7cz83bAOW1AvJl3EMfnyX0J9715O+AIOCDezDx5NG9T64N5O+B0GeTsuWBG8lQjMSAgy3DwmXl09ZDtPtE9cv25k2be9LyDeBRYgk2tWyo7ZDsCnjX1MratnXE5k+58XsmojOCkotK56IuKyrye881TxXu/jF8tKvMtNNktqrEZ1+Qcojrg28OARWXeIRwvqiN3Cm8W1Wy3qEyx+2fJVF3Hcp9weVlBi+gqdfl/c6obLrLi0+Ol6CA0sq4aRSmUv484w0l4I+T07bv2KCIsnZZdWurlaM0NiSIxD1gWHaRIQc5pOXPRDAgO5cVJICSKmDDIOxMcAHKpGmIMYXFjo8gS03hXI++6+y4m44z+QYaxa5W87bOb3Z1s6uvIdjsWkpn8TnY347TP+I8IwJ8J2UjyPh9LUmXq27hzItZa7zTfa7PmdLDmvp41Ua0+c5crvfq7gHvzHw==</diagram></mxfile> | |||
| @ -0,0 +1,4 @@ | |||
| {signal: [ | |||
| {name: 'tx', wave: '10.10...101..'}, | |||
| {name: '', wave: "x34.......53x", data: ["start", "data (0x42, 0d66)", "par", "stop"] } | |||
| ]} | |||
| @ -0,0 +1,7 @@ | |||
| {signal: [ | |||
| {name: 'reset', wave: '01...|.....'}, | |||
| {name: 'clk', wave: 'P....|.....'}, | |||
| {name: 'valid', wave: '0.1.0|..10.'}, | |||
| {name: 'accept', wave: '0..10|1..0.'}, | |||
| {name: 'data', wave: 'x.3.x|..3x.'} | |||
| ]} | |||
| @ -0,0 +1 @@ | |||
| <mxfile host="Electron" modified="2022-02-10T13:01:01.834Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="S9JdeyS9-GK7bHc6NI_U" version="16.5.1" type="device"><diagram id="vomTti7XoeUnKlfPLwag" name="Page-1">1Vlbb9owFP41SNvDUJxbw2OBbp1EJVS6rd1LZZID8WpiZkyB/frZxLmRAC0l0KZSlXN8if1953w+CQ2rM1l+43ga3rAAaMM0gmXD6jZMs4U8+V85VrHDc+zYMeYkiF0ocwzIP9BOQ3vnJIBZoaNgjAoyLTp9FkXgi4IPc84WxW4jRotPneIxlBwDH9Oy9xcJRKi9rmFkDddAxmHyaDNpmeCkt3bMQhywRc5lXTWsDmdMxHeTZQeoAi8BJh73dUtrujIOkXjJAPq33Z3Pbm5/PJJHY2Us7nu/O1/MeJZnTOd6xwMymVMsGNerFqsEC87mUQBqNtSw2ouQCBhMsa9aF5J86QvFhOrmZ+CCSBwvKRlH0ieY6qCfJttguXUbKAVHRhWwCQi+kl30ANPReOqIsjxtLzJ+nISEMEdNygzWMTFO585QkzcauFeAaJdAvIOZGELkhztANPaDSPEQaJ/NiCBMgehLjIDn0O1tdJiQIFBPamMNe2lEkY8RobTDqCRbLc4aOepP+Vkkcv74kv6Z4OwJci3u+joSs16RWRuVmbXtCmaRXRezrRJ/EEh90CbjImRjFmF6lXnbRYazPj2mIF/z+geEWGmxw3PBiqzDkoj73P2DmqrpaKu71DOvjZU24nWqxe0GX+6FzbkPO/ZsaZnFfAxiRz+nmkwOUj3Ic3EdRyfGKqVc98fd25JtIxcCB7zArop5zxxax4r5NJ6TmHfKMY/Miph36wp5p4RsJwT/CXadBwegi8Eb+ZWK4nswHB0H3fSY3oGud0pwvY+iJxJgvrrPG7lRysyGra0adMh9oQ5Z59QhZJ6T0YzFh1zLPkabCKEiqwa62MPr2uoDJxI2VU+ci2y0JeFfzLYe2mdELjGTYaPVbOUuryAbjrehB/Ey9RwbEZQu6vCgcksSPBCqKicfUIIt851JcPJGmkc3lNsJpI+SIcf6GQfD/AEq7bSy1qS4FZU2qmIFobpoMc8qpIcdjU3PaxWFtLXvfKxbRxN+TiSkl5zjVa7DVEnibLvOuhvlrus6G5ETz3hUOU0wyWX8LYxAgiuhNF0qYWoPZXnrjtWd/oS16f7EphANBr3Px9Xgs7xkuJZTTveTvmQg+7xlk07cNOONtebuyHlp1Jm1yafNut+5q7PSaRXjo1TvxBuord5B5/nMcuArThZFuo5Oo6i15+B4J0GEjFqiKFWLtKhwThtFqCTzP6/739+m1zVUwM5Fudiy3Ar1NV+vvtLMflCIgc1+lrGu/gM=</diagram></mxfile> | |||
| @ -0,0 +1 @@ | |||
| <mxfile host="Electron" modified="2022-02-10T13:17:36.889Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="Uwtb3SQXxcPGzdBz5ZS-" version="16.5.1" type="device"><diagram id="vomTti7XoeUnKlfPLwag" name="Page-1">1VhNc9owEP01HMvYku2YY4G0PSQzmZBMk14ywl5sNbJFhRxwf30lLH9hh6YJJEXMMN6nlbR6b7UID/Ak2XwVZBlf8hDYAFnhZoCnA4TOPEt9ayA3gHVWAJGgYQHZNTCjv8GAZlyU0RBWLUfJOZN02QYDnqYQyBZGhODrttuCs/aqSxJBB5gFhHXR7zSUsUE9y6o7vgGN4nJpVPYkpPQ2wComIV83IHw+wBPBuSyeks0EmCavJKYY9+WZ3ioyAal8yQD2azzNVpfXtw/0wcqt9d3Fj8knVMzyRFhmdjyjScaI5MJELfOSC8GzNAQ9mz3A43VMJcyWJNC9ayW+wmKZMNP9BEJSxeNnRqNUYZJrB7Oa6oPNs9uwK3JUVgFPQIpcuZgByDV8mozCvrHXtT5uKULckAaVjsTkRFTNXbOmHgxx/0Ci0yHxBlZyDmkQ7yHR+juJjMyBXfEVlZRrEgPFEYgGuxc7DgkNQ73SmBjaOyPaeiwoYxPOlNg6OLxw9UfjPJUNvGgKX0nBH6HR423bgZT128o6dldZx+lTFh1L2VFHPwhVfTAmFzLmEU8JO6/RcVvh2ueCa8q3uv4EKXNT7EgmeVt12FB513i+11MNXWNNN2bmrZEbo4hTB7effLUXnokA9uwZmzJLRARyj5/bL6YAVT3oUzuOgwuDO0duenvztsO2cxZCF/zQ6ct5H83xoXK+yucy591uztuoJ+e9Y6W822F2EkPwCPt+D17BLgF/EfRWlMCH+eIw7FY/03vY9d+TXP9U6okiWOR3TaMxSpv1sK11hDrkvbAO4Y+sQzb6SEVrFe8bPSevKHqrpGboFacqxKoaYHc0HKmSUDWnVRzcM2uI8ahu7fmLqM2UO1lTxfj6RPI6ZXcm9U2cnmDZxeg/K7u2cyp194CnDb3XRa7/tHmONew5YZ777AkrdnS0E4a6d8ZrWIAiVtGo/q8Xry5O/gbpOse7QSqzfl9R6FK/9cHnfwA=</diagram></mxfile> | |||
| @ -0,0 +1,498 @@ | |||
| --- | |||
| title: Using Python for Verification of Digital Systems | |||
| subtitle: QZ 2021 | |||
| author: | |||
| - Torsten MeiĂźner | |||
| - torsten.meissner@secunet.com | |||
| date: February 2022 | |||
| ... | |||
| # Overview | |||
| * Introduction | |||
| * Functional Verification | |||
| * Co-Simulation | |||
| * Cocotb | |||
| * Python Packages | |||
| * Live Demo | |||
| * Summary | |||
| # Introduction | |||
| ## FPGA-Workflow | |||
| 1. Specification | |||
| 2. Design entry | |||
| 3. **Verification** | |||
| 4. Synthesis | |||
| 5. Device Mapping | |||
| 6. Place & Route | |||
| 7. Static Timing Analysis | |||
| 8. Programming file generation | |||
| # Introduction | |||
| ## Design Entry | |||
| 1. Schematic Entry | |||
| 2. **Hardware Description Languages (RTL)** | |||
| * **(System)Verilog** | |||
| * **VHDL** | |||
| 3. High level languages | |||
| * System C | |||
| * Bluespec | |||
| * Chisel | |||
| * nmigen | |||
| # Functional Verification | |||
| 1. **Functional Verification** | |||
| * **Simulation** | |||
| * Emulation | |||
| 2. Formal Verification | |||
| * Property checking | |||
| * Equivalence checking | |||
| 3. Lab Tests | |||
| * Target platform | |||
| * Logic Analyzer | |||
| * Oscilloscope | |||
| # Functional Verification | |||
| ## Simulation | |||
| * Executing of design description in a simulator | |||
| * Test benches as infrastructure (HDL, C, etc.) | |||
| * Reference models (HDL, C, etc.) | |||
| * Directed & Random tests | |||
| * Code & functional Coverage | |||
| * Assertion Based Verification (PSL, SVA) | |||
| * Verification Frameworks (UVM, OSVVM, vUnit, etc.) | |||
| * Co-Simulation | |||
| # HDL Simulation | |||
|  | |||
| # Co-Simulation | |||
| - Simulation with access to/from external program code | |||
| - Linked per shared library | |||
| ## HDL Programming Interfaces | |||
| - VHDL Procedural Interface (VHPI) | |||
| - Verilog Procedural Interface (VPI) | |||
| - Propitrary interfaces (FLI) | |||
| - Access data in VHDL models in the simulator | |||
| ## Features | |||
| - Static VHDL Design Data (Traverse hierarchy etc.) | |||
| - Dynamic VHDL Objects (R/W values of VHDL objects) | |||
| - Interaction and control (Callbacks as comm. mechanism between simulator user code) | |||
| - Foreign model instantiation and intercommunication | |||
| # Co-Simulation with SW reference Model | |||
|  | |||
| HDL testbench controls program flow | |||
| # Cocotb | |||
| - COroutine based COsimulation TestBench environment | |||
| - Verifying HDL designs with Python | |||
| - HDL normally only used for design, not the testbench | |||
| - Simulator only used to execute DUT RTL description | |||
| - Support many simulators (Free & propitrary) | |||
| - Free & open-source, active community | |||
| ## | |||
| - High-level, multi-paradigm language | |||
| - Writing Python is fast - **very productive** language. | |||
| - **Easy interfacing** to other languages from Python | |||
| - **Huge library** of existing code to re-use | |||
| - **Interpreted** - tests can be edited and re-run w/o recompiling the design | |||
| - **Popular** - far more engineers know Python than Verilog / VHDL | |||
| - Working and reliable packet manager (PyPI) | |||
| # Cocotb Co-Simulation | |||
|  | |||
| Python testbench controls program flow | |||
| # Cocotb Design Interaction | |||
| ## Accessing Design | |||
| - *dut* as handle to toplevel instantiation | |||
| - Access to toplevel and other signals with dot-notation | |||
| ~~~~ {.python .stretch} | |||
| # Reference to toplevel clock input | |||
| clk = dut.clk_i | |||
| # Reference to signal in sub-unit | |||
| cpu_pc = dut.cpu.regfile.pc | |||
| ~~~~ | |||
| ## Read / Write Values from Signals | |||
| - Via handle's *value* property | |||
| - Direct R/W access through the hierarchy | |||
| ~~~~ {.python .stretch} | |||
| # Via value property | |||
| valid = dut.valid_i.value | |||
| if valid.value == 0: | |||
| valid.value = 1 | |||
| # Direct access through hierarchy | |||
| if dut.reset_i.value == 1: | |||
| dut.cpu.regfile.pc.value = 0 | |||
| ~~~~ | |||
| # Cocotb concurrent & sequential execution | |||
| ## *async*: Mark Functions & Methods as Coroutines | |||
| ~~~~ {.python .stretch} | |||
| async def reset(signal, time,): | |||
| signal.value = 0 | |||
| # Block execution, wait for simulator time advances by 100 ns | |||
| await Timer(time, units='ns') # cocotb built-in class | |||
| signal.value = 1 | |||
| ~~~~ | |||
| ## *await*: Wait for other Coroutines or Simulator | |||
| - Block on another coroutines execution | |||
| - Pass control of execution back to simulator, allowing simulation time to advance | |||
| ~~~~ {.python .stretch} | |||
| print("Hold reset") | |||
| await reset(dut.reset_i) | |||
| print("Released reset") | |||
| ~~~~ | |||
| # Cocotb concurrent execution | |||
| ## *start()* | |||
| 1. Schedules the new coroutine to be executed concurrently | |||
| 2. Yields control to allow the new task (& any other pending tasks) to run | |||
| 3. Resumes the calling task | |||
| ~~~~ {.python .stretch} | |||
| await cocotb.start(reset(dut.reset_i, 100) | |||
| await Timer(90, units='ns') | |||
| print(f"Reset is still active: {dut.reset_i.value}") | |||
| await Timer(15, units='ns') | |||
| print(f"Reset has gone inactive: {dut.reset_i.value}") | |||
| ~~~~ | |||
| ## *start_soon()*: | |||
| - Schedules the new coroutine for future execution, after the calling task yields control | |||
| ~~~~ {.python .stretch} | |||
| clock = Clock(dut.clk_i, 10, units="ns") # Create a clock, cocotb built-in class | |||
| cocotb.start_soon(clock.start()) # Start the clock concurrently | |||
| ~~~~ | |||
| # Cocotb test functions | |||
| ## *@cocotb.test()* Decorator | |||
| - Mark a callable which returns a coroutine as a test | |||
| - Provides a test timeout | |||
| - Allows to mark tests as skipped or expecting errors or failures | |||
| - Tests are evaluated in the order of their definition in a test module | |||
| ~~~~ {.python .stretch} | |||
| @cocotb.test() | |||
| async def test_aes_init(dut): | |||
| """ Test AES initialization """ | |||
| ... | |||
| @cocotb.test() | |||
| async def test_aes_enc(dut): | |||
| """ Test AES encryption """ | |||
| ... | |||
| # This test is skipped from execution | |||
| @cocotb.test(skip=True) | |||
| async def test_aes_enc(dut): | |||
| """ Test AES encryption """ | |||
| ~~~~ | |||
| # Cocotb Triggers | |||
| - Indicate when cocotb scheduler should resume coroutine execution | |||
| - Triggers should awaited for by coroutines | |||
| - Cause execution of the current coroutine to pause | |||
| - Execution of paused coroutine will resumes when trigger fires | |||
| - Triggers for simulator events, task synchronization etc. | |||
| ~~~~ {.python .stretch} | |||
| # Wait for 100 ns | |||
| await Timer(100, units='ns') | |||
| # Wait for rising clock edge | |||
| await RisingEdge(dut.clk_i) | |||
| # Wait for 10 clock cycles | |||
| await ClockCycles(dut.clk_i, 10) | |||
| # Fires when first trigger in fires & returns its result | |||
| t1 = Timer(10, units='ns') | |||
| t2 = Timer(15, units='ns') | |||
| t_ret = await First(t1, t2) # returns after 10 ns simulation time | |||
| ~~~~ | |||
| # Cocotb Example: Verifying an UART transmitter | |||
|  | |||
| # Cocotb Example: Verifying an UART transmitter | |||
| ## | |||
|  | |||
| # Cocotb Example: Verifying an UART transmitter | |||
| ## Valid-Accept Driver Model | |||
| ~~~~ {.python .stretch} | |||
| async def send(self, data, sync=True): | |||
| if sync: | |||
| await self._clkedge | |||
| self._valid.value = 1 | |||
| if isinstance(self._data, list): | |||
| for i in range(len(self._data)): | |||
| self._data[i].value = data[i] | |||
| else: | |||
| self._data.value = data | |||
| while True: | |||
| await ReadOnly() | |||
| if self._accept.value: | |||
| break | |||
| await self._clkedge | |||
| await self._clkedge | |||
| self._valid.value = 0 | |||
| ~~~~ | |||
| # Cocotb Example: Verifying an UART transmitter | |||
| ## UART Receiver Model | |||
| ~~~~ {.python .stretch} | |||
| async def receive(self): | |||
| # Wait for frame start | |||
| await FallingEdge(self._txrx) | |||
| # Consume start bit | |||
| await self._get_start_bit() | |||
| # Receive data bits | |||
| self._rec = 0 | |||
| for x in range(self._bits): | |||
| await self._wait_cycle() | |||
| await ReadOnly() | |||
| self._rec |= bool(self._txrx.value.integer) << x | |||
| if self._par: | |||
| # Consume parity bit | |||
| await self._get_parity_bit() | |||
| # Consume stop bit | |||
| await self._get_stop_bit() | |||
| return self._rec | |||
| ~~~~ | |||
| # Cocotb Example: Verifying an UART transmitter | |||
| ## Test function | |||
| ~~~~ {.python .stretch} | |||
| @cocotb.test() | |||
| async def test_uarttx(dut): | |||
| # Instantiate VAI driver & UART receiver | |||
| vai_driver = VaiDriver(dut.clk_i, dut.data_i, dut.valid_i, dut.accept_o) | |||
| uart_receiver = UartReceiver(dut.tx_o, dut.clk_i, 10, 8, True); | |||
| # Drive input defaults (setimmediatevalue to avoid x asserts) | |||
| dut.data_i.setimmediatevalue(0) | |||
| dut.valid_i.setimmediatevalue(0) | |||
| cocotb.start_soon(Clock(dut.clk_i, 10, units="ns").start()) # Start the clock | |||
| await reset(dut.reset_n_i, 100) # Block until reset() has completed | |||
| # Test 10 UART transmissions | |||
| for i in range(256): | |||
| await RisingEdge(dut.clk_i) | |||
| await vai_driver.send(i) | |||
| rec = await uart_receiver.receive(); | |||
| assert rec == i, "UART sent data was incorrect on the {}th cycle".format(i) | |||
| ~~~~ | |||
| # Cocotb Example: Verifying an UART transmitter | |||
| ~~~~ {.shell .stretch} | |||
| loading VPI module '/usr/local/lib/python3.9/dist-packages/cocotb/libs/libcocotbvpi_ghdl.so' | |||
| -.--ns INFO cocotb.gpi ../gpi/GpiCommon.cpp:99 in gpi_print_registered_impl VPI registered | |||
| VPI module loaded! | |||
| 0.00ns INFO Running on GHDL version 2.0.0-dev (v1.0.0-974-g0e46300c) [Dunoon edition] | |||
| 0.00ns INFO Running tests with cocotb v1.7.0.dev0 from /usr/local/lib/python3.9/... | |||
| 0.00ns INFO Seeding Python random module with 1644512771 | |||
| 0.00ns INFO Found test tb_uarttx.test_uarttx | |||
| 0.00ns INFO running test_uarttx (1/1) | |||
| First simple test | |||
| 0.00ns INFO Valid-accept driver | |||
| 0.00ns INFO cocotbext-vai version 0.0.1 | |||
| 0.00ns INFO Copyright (c) 2022 Torsten Meissner | |||
| 0.00ns INFO UART receiver | |||
| 0.00ns INFO cocotbext-uart version 0.0.1 | |||
| 0.00ns INFO Copyright (c) 2022 Torsten Meissner | |||
| 100.00ns INFO Released reset | |||
| 110.00ns INFO Send data: 0xb6 | |||
| ... | |||
| 11160.00ns INFO Received data: 0xd8 | |||
| 11160.00ns INFO test_uarttx passed | |||
| 11160.00ns INFO ********************************************************************** | |||
| ** TEST STATUS SIM TIME (ns) REAL TIME (s) | |||
| ********************************************************************** | |||
| ** tb_uarttx.test_uarttx PASS 11160.00 0.21 | |||
| ********************************************************************** | |||
| ** TESTS=1 PASS=1 FAIL=0 SKIP=0 11160.00 0.22 | |||
| ********************************************************************** | |||
| ~~~~ | |||
| # Python Packages | |||
| ## Cocotb related | |||
| - Reusable packages for cocotb testbenches | |||
| - Bus protocols, reference models etc. | |||
| - Verification libraries | |||
| - pyuvm | |||
| - cocotb-coverage | |||
| - umv-python | |||
| - Depending on cocotb | |||
| ## Python generic | |||
| - Generic Python packages useful for verification | |||
| - pyvsc | |||
| - pyucis | |||
| - Whole Python ecosystem | |||
| - Not depending on cocotb | |||
| # Python Packages: pyvsc | |||
| ## Python library for Verification Stimulus and Coverage | |||
| - Random verification-stimulus generation | |||
| - Functional coverage collection | |||
| - Implemented in pure Python | |||
| - Uses Boolector SMT-solver for solving user-defined constraints | |||
| ~~~~ {.python .stretch} | |||
| @vsc.randobj | |||
| class my_cr(): | |||
| def __init__(self): | |||
| self.a = vsc.rand_bit_t(8) | |||
| self.b = vsc.rand_bit_t(8) | |||
| @vsc.constraint | |||
| def ab_c(self): | |||
| self.a != 0 | |||
| self.a <= self.b | |||
| self.b in vsc.rangelist(1,2,4,8) | |||
| ~~~~ | |||
| # Live Demo | |||
| ## UART transmitter & receiver | |||
| - Simple tests using self written Python models for VAI & UART | |||
| ## Wishbone slave with local SRAM interface | |||
| - Using cocotbext-wishbone package from PyPI | |||
| ## AES128 en- and decryption | |||
| - Using pyvsc for constrained random & functional coverage | |||
| - Using Pycrypto for AES reference | |||
| # Summary | |||
| - Easy to use | |||
| - Good documentation | |||
| - In active development with regularly releases | |||
| - Free and open-source | |||
| - Allows Python SW-developers to verify digital systems | |||
| - Supports all major simulators used by FPGA teams | |||
| ## Presentations code examples | |||
| * https://github.com/tmeissner/cocotb_with_ghdl | |||
| ## References | |||
| * https://github.com/cocotb/cocotb | |||
| * https://github.com/fvutils/pyvsc | |||
| * https://github.com/wallento/cocotbext-wishbone | |||
| # Extras: Accessing signals | |||
| ## *dut.signal.value = 1* | |||
| - Value is stored by the Scheduler | |||
| - All stored values are written at the same time at the end of the current simulator time step | |||
| ## *.setimmediatevalue()* | |||
| - Value is assigned to this simulation object immediately | |||
| ## Access to elements of indexable objects (arrays etc.) | |||
| ~~~~ {.python .stretch} | |||
| dut.some_array[0].value = 1 | |||
| ~~~~ | |||
| - Bit order depends on the HDL object (*to* or *downto*) | |||
| # Extras: Accessing signals | |||
| ## Reading synchronous signals | |||
| - Returns after clock changes, but no sympathetic signals changed yet | |||
| - Sampling any signal here returns values settled during previous clock cycle | |||
| - Equivalent to registered processes in HDLs | |||
| ## *ReadOnly()* | |||
| - Triggers in the postpone phase | |||
| - All signals have settled | |||
| - No more updates may occur on the clock edge event | |||
| - Sampling any signal here returns values settled current clock cycle | |||
| # Extras: Accessing signals | |||
|  | |||
| @ -0,0 +1,191 @@ | |||
| \documentclass[usenames,dvipsnames,10pt,aspectratio=169]{beamer} | |||
| \usepackage{fontspec} | |||
| \setmainfont{Liberation Sans} | |||
| \setmonofont{Liberation Mono} | |||
| %\usepackage[margin=1in]{geometry} | |||
| \usepackage{hyperref} | |||
| \PassOptionsToPackage{usenames,dvipsnames}{color} % color is loaded by hyperref | |||
| \hypersetup{unicode=true, | |||
| $if(title-meta)$ | |||
| pdftitle={$title-meta$}, | |||
| $endif$ | |||
| $if(author-meta)$ | |||
| pdfauthor={$author-meta$}, | |||
| $endif$ | |||
| $if(keywords)$ | |||
| pdfkeywords={$for(keywords)$$keywords$$sep$; $endfor$}, | |||
| $endif$ | |||
| colorlinks=true, | |||
| linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$, | |||
| citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$, | |||
| urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$, | |||
| breaklinks=true} | |||
| \urlstyle{same} % don't use monospace font for urls | |||
| \setbeamercolor{title}{fg=Maroon} | |||
| \setbeamercolor{subtitle}{fg=MidnightBlue} | |||
| \setbeamercolor{frametitle}{fg=MidnightBlue} | |||
| \setbeamercolor{structure}{fg=MidnightBlue} | |||
| % Don't show things we don't want to see | |||
| \beamertemplatenavigationsymbolsempty | |||
| % Slide number in lower right | |||
| \setbeamertemplate{footline}{ | |||
| \raisebox{5pt}{ | |||
| \makebox[\paperwidth]{ | |||
| \hfill\makebox[0.15\linewidth]{\color{Gray} \footnotesize Torsten MeiĂźner} | |||
| \hfill\makebox[0.7\linewidth]{\color{Gray} \footnotesize \insertshorttitle} | |||
| \hfill\makebox[0.15\linewidth]{\color{Gray} \footnotesize \insertframenumber ~/ \inserttotalframenumber} | |||
| } | |||
| } | |||
| \hspace*{5pt} | |||
| } | |||
| % Color and shape of bullets | |||
| \setbeamercolor{item}{fg=Gray} | |||
| \setbeamercolor{subitem}{fg=Gray} | |||
| % \setbeamercolor{itemize/enumerate subbody}{fg=gray} | |||
| \setbeamertemplate{itemize item}{{\textendash}} | |||
| \setbeamertemplate{itemize subitem}{{\textendash}} | |||
| \setbeamerfont{itemize/enumerate subbody}{size=\footnotesize} | |||
| \setbeamerfont{itemize/enumerate subitem}{size=\footnotesize} | |||
| %\usepackage{fancyvrb} | |||
| %\DefineVerbatimEnvironment{verbatim}{Verbatim}{frame=leftline, fontsize=\small, baselinestretch=1.17} | |||
| %\VerbatimFootnotes % allows verbatim text in footnotes | |||
| \usepackage{listings} | |||
| \lstset{ | |||
| basicstyle=\ttfamily\scriptsize, | |||
| keywordstyle=\color{Maroon}, | |||
| stringstyle=\color{NavyBlue}, | |||
| showstringspaces=false, | |||
| frame=leftline, | |||
| xleftmargin=5pt, | |||
| tabsize=2, | |||
| } | |||
| $if(highlighting-macros)$ | |||
| $highlighting-macros$ | |||
| $endif$ | |||
| $if(verbatim-in-note)$ | |||
| \usepackage{fancyvrb} | |||
| \VerbatimFootnotes % allows verbatim text in footnotes | |||
| $endif$ | |||
| $if(tables)$ | |||
| \usepackage{longtable,booktabs} | |||
| \usepackage{caption} | |||
| % These lines are needed to make table captions work with longtable: | |||
| \makeatletter | |||
| \def\fnum@table{\tablename~\thetable} | |||
| \makeatother | |||
| $endif$ | |||
| $if(graphics)$ | |||
| \usepackage{graphicx,grffile} | |||
| \makeatletter | |||
| \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} | |||
| \def\maxheight{\ifdim\Gin@nat@height>\textheight0.8\textheight\else\Gin@nat@height\fi} | |||
| \makeatother | |||
| \centering | |||
| % Scale images if necessary, so that they will not overflow the page | |||
| % margins by default, and it is still possible to overwrite the defaults | |||
| % using explicit options in \includegraphics[width, height, ...]{} | |||
| \setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} | |||
| $endif$ | |||
| % Prevent slide breaks in the middle of a paragraph: | |||
| \widowpenalties 1 10000 | |||
| \raggedbottom | |||
| \newif\ifbibliography | |||
| $if(section-titles)$ | |||
| \AtBeginPart{ | |||
| \let\insertpartnumber\relax | |||
| \let\partname\relax | |||
| \frame{\partpage} | |||
| } | |||
| \AtBeginSection{ | |||
| \ifbibliography | |||
| \else | |||
| \let\insertsectionnumber\relax | |||
| \let\sectionname\relax | |||
| \frame{\sectionpage} | |||
| \fi | |||
| } | |||
| \AtBeginSubsection{ | |||
| \let\insertsubsectionnumber\relax | |||
| \let\subsectionname\relax | |||
| \frame{\subsectionpage} | |||
| } | |||
| $endif$ | |||
| $if(links-as-notes)$ | |||
| % Make links footnotes instead of hotlinks: | |||
| \renewcommand{\href}[2]{#2\footnote{\url{#1}}} | |||
| $endif$ | |||
| $if(strikeout)$ | |||
| \usepackage[normalem]{ulem} | |||
| % avoid problems with \sout in headers with hyperref: | |||
| \pdfstringdefDisableCommands{\renewcommand{\sout}{}} | |||
| $endif$ | |||
| \setlength{\emergencystretch}{3em} % prevent overfull lines | |||
| \providecommand{\tightlist}{% | |||
| \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} | |||
| $if(numbersections)$ | |||
| \setcounter{secnumdepth}{5} | |||
| $else$ | |||
| \setcounter{secnumdepth}{0} | |||
| $endif$ | |||
| $if(dir)$ | |||
| \ifxetex | |||
| % load bidi as late as possible as it modifies e.g. graphicx | |||
| $if(latex-dir-rtl)$ | |||
| \usepackage[RTLdocument]{bidi} | |||
| $else$ | |||
| \usepackage{bidi} | |||
| $endif$ | |||
| \fi | |||
| \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex | |||
| \TeXXeTstate=1 | |||
| \newcommand{\RL}[1]{\beginR #1\endR} | |||
| \newcommand{\LR}[1]{\beginL #1\endL} | |||
| \newenvironment{RTL}{\beginR}{\endR} | |||
| \newenvironment{LTR}{\beginL}{\endL} | |||
| \fi | |||
| $endif$ | |||
| $if(title)$ | |||
| \title{$title$} | |||
| $endif$ | |||
| $if(subtitle)$ | |||
| \subtitle{$subtitle$} | |||
| $endif$ | |||
| $if(author)$ | |||
| \author{$for(author)$$author$$sep$ \\ $endfor$} | |||
| $endif$ | |||
| \date{$date$} | |||
| \begin{document} | |||
| $if(title)$ | |||
| \frame{\maketitle} | |||
| $endif$ | |||
| $for(include-before)$ | |||
| $include-before$ | |||
| $endfor$ | |||
| $if(toc)$ | |||
| \begin{frame} | |||
| \tableofcontents[hideallsubsections] | |||
| \end{frame} | |||
| $endif$ | |||
| $body$ | |||
| $for(include-after)$ | |||
| $include-after$ | |||
| $endfor$ | |||
| \end{document} | |||