├── LICENSE ├── Makefile ├── README.md ├── component.xml ├── design_modules.svg ├── hdl ├── axi_csi.v ├── axilite_control.v ├── ecc_block.v ├── pckthandler.v ├── pckthandler_fsm.v ├── ph_finder.v ├── raw10_decoder.v └── wordalign.v ├── unit_tests ├── Makefile ├── csirx_tb.v ├── ecc_block_tb.v ├── ecc_block_testvec.txt ├── image4.bin ├── image4_out.bin ├── pckthandler_fsm_tb.v ├── pckthandler_fsm_testvec.txt ├── pckthandler_tb.v ├── pckthandler_tb2.v ├── pckthandler_testvec.txt ├── ph_finder_tb.v ├── ph_finder_testvec.txt ├── raw10_decoder_tb.v ├── raw10_decoder_testvec.txt └── viewdump.py └── xgui ├── axi_csi_v1_1.tcl └── axi_csi_v1_1_v1_0.tcl /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | IVERILOG := iverilog -g2005 3 | BUILDDIR := build 4 | 5 | .PHONY: all clean 6 | 7 | all: ecc_block pckthandler pckthandler_fsm ph_finder raw10_decoder 8 | 9 | 10 | pckthandler2 : unit_tests/pckthandler_tb2.v 11 | $(IVERILOG) *.v unit_tests/pckthandler_tb2.v -o $(BUILDDIR)/$@ 12 | cd unit_tests; vvp ../$(BUILDDIR)/$@ 13 | 14 | # All the unit tests 15 | # Run them from the unit_tests dir since they depend on files 16 | % : %.v 17 | $(IVERILOG) *.v unit_tests/$*_tb.v -o $(BUILDDIR)/$@ 18 | cd unit_tests; vvp ../$(BUILDDIR)/$@ 19 | 20 | clean: 21 | rm -rf build/* 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # csirx 2 | Open-source CSI-2 receiver for Xilinx UltraScale parts 3 | 4 | 5 | # Supported cameras 6 | Right now, this only supports the Sony IMX219 (aka the Raspberry Pi camera). In the Raspberry Pi configuration, it supports 2 data lanes and 10-bit RAW output. 7 | 8 | # License 9 | This code is released under the GNU LGPL 3.0. That means you're welcome to use it however you want, but if you publish/sell a design based on a modified version of the code, then you need to share your changes to this code (but not the rest of your system). 10 | 11 | # Links 12 | Several others have created similar CSI-2 receivers: 13 | 14 | * https://github.com/daveshah1/CSI2Rx 15 | 16 | -------------------------------------------------------------------------------- /component.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | stanford.edu 4 | user 5 | axi_csi 6 | 1.1 7 | 8 | 9 | output_m_axis 10 | 11 | 12 | 13 | 14 | 15 | 16 | TDATA 17 | 18 | 19 | output_m_axis_tdata 20 | 21 | 22 | 23 | 24 | TSTRB 25 | 26 | 27 | output_m_axis_tstrb 28 | 29 | 30 | 31 | 32 | TLAST 33 | 34 | 35 | output_m_axis_tlast 36 | 37 | 38 | 39 | 40 | TVALID 41 | 42 | 43 | output_m_axis_tvalid 44 | 45 | 46 | 47 | 48 | TREADY 49 | 50 | 51 | output_m_axis_tready 52 | 53 | 54 | 55 | 56 | 57 | regspace_s_axi 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | AWADDR 67 | 68 | 69 | regspace_s_axi_awaddr 70 | 71 | 72 | 73 | 74 | AWPROT 75 | 76 | 77 | regspace_s_axi_awprot 78 | 79 | 80 | 81 | 82 | AWVALID 83 | 84 | 85 | regspace_s_axi_awvalid 86 | 87 | 88 | 89 | 90 | AWREADY 91 | 92 | 93 | regspace_s_axi_awready 94 | 95 | 96 | 97 | 98 | WDATA 99 | 100 | 101 | regspace_s_axi_wdata 102 | 103 | 104 | 105 | 106 | WSTRB 107 | 108 | 109 | regspace_s_axi_wstrb 110 | 111 | 112 | 113 | 114 | WVALID 115 | 116 | 117 | regspace_s_axi_wvalid 118 | 119 | 120 | 121 | 122 | WREADY 123 | 124 | 125 | regspace_s_axi_wready 126 | 127 | 128 | 129 | 130 | BRESP 131 | 132 | 133 | regspace_s_axi_bresp 134 | 135 | 136 | 137 | 138 | BVALID 139 | 140 | 141 | regspace_s_axi_bvalid 142 | 143 | 144 | 145 | 146 | BREADY 147 | 148 | 149 | regspace_s_axi_bready 150 | 151 | 152 | 153 | 154 | ARADDR 155 | 156 | 157 | regspace_s_axi_araddr 158 | 159 | 160 | 161 | 162 | ARPROT 163 | 164 | 165 | regspace_s_axi_arprot 166 | 167 | 168 | 169 | 170 | ARVALID 171 | 172 | 173 | regspace_s_axi_arvalid 174 | 175 | 176 | 177 | 178 | ARREADY 179 | 180 | 181 | regspace_s_axi_arready 182 | 183 | 184 | 185 | 186 | RDATA 187 | 188 | 189 | regspace_s_axi_rdata 190 | 191 | 192 | 193 | 194 | RRESP 195 | 196 | 197 | regspace_s_axi_rresp 198 | 199 | 200 | 201 | 202 | RVALID 203 | 204 | 205 | regspace_s_axi_rvalid 206 | 207 | 208 | 209 | 210 | RREADY 211 | 212 | 213 | regspace_s_axi_rready 214 | 215 | 216 | 217 | 218 | 219 | regspace_s_axi_aresetn 220 | 221 | 222 | 223 | 224 | 225 | 226 | RST 227 | 228 | 229 | regspace_s_axi_aresetn 230 | 231 | 232 | 233 | 234 | 235 | POLARITY 236 | ACTIVE_LOW 237 | 238 | 239 | 240 | 241 | regspace_s_axi_aclk 242 | 243 | 244 | 245 | 246 | 247 | 248 | CLK 249 | 250 | 251 | regspace_s_axi_aclk 252 | 253 | 254 | 255 | 256 | 257 | ASSOCIATED_BUSIF 258 | regspace_s_axi 259 | 260 | 261 | ASSOCIATED_RESET 262 | regspace_s_axi_aresetn 263 | 264 | 265 | 266 | 267 | csi_intr 268 | 269 | 270 | 271 | 272 | 273 | 274 | INTERRUPT 275 | 276 | 277 | csi_intr 278 | 279 | 280 | 281 | 282 | 283 | SENSITIVITY 284 | LEVEL_HIGH 285 | 286 | 287 | 288 | 289 | rxbyteclkhs_resetn 290 | 291 | 292 | 293 | 294 | 295 | 296 | RST 297 | 298 | 299 | rxbyteclkhs_resetn 300 | 301 | 302 | 303 | 304 | 305 | POLARITY 306 | ACTIVE_LOW 307 | 308 | 309 | 310 | 311 | ppi_rxbyteclkhs_clk 312 | 313 | 314 | 315 | 316 | 317 | 318 | CLK 319 | 320 | 321 | ppi_rxbyteclkhs_clk 322 | 323 | 324 | 325 | 326 | 327 | ASSOCIATED_BUSIF 328 | input_mipi_ppi:output_m_axis 329 | 330 | 331 | 332 | 333 | input_mipi_ppi 334 | 335 | 336 | 337 | 338 | 339 | 340 | DL1_RXACTIVEHS 341 | 342 | 343 | ppi_dl1_rxactivehs 344 | 345 | 346 | 347 | 348 | CL_ENABLE 349 | 350 | 351 | ppi_cl_enable 352 | 353 | 354 | 355 | 356 | DL1_RXDATAHS 357 | 358 | 359 | ppi_dl1_rxdatahs 360 | 361 | 362 | 363 | 364 | CL_STOPSTATE 365 | 366 | 367 | ppi_cl_stopstate 368 | 369 | 370 | 371 | 372 | DL0_RXSYNCHS 373 | 374 | 375 | ppi_dl0_rxsynchs 376 | 377 | 378 | 379 | 380 | DL1_RXVALIDHS 381 | 382 | 383 | ppi_dl1_rxvalidhs 384 | 385 | 386 | 387 | 388 | DL0_RXACTIVEHS 389 | 390 | 391 | ppi_dl0_rxactivehs 392 | 393 | 394 | 395 | 396 | DL1_RXSYNCHS 397 | 398 | 399 | ppi_dl1_rxsynchs 400 | 401 | 402 | 403 | 404 | DL0_ENABLE 405 | 406 | 407 | ppi_dl0_enable 408 | 409 | 410 | 411 | 412 | DL0_RXDATAHS 413 | 414 | 415 | ppi_dl0_rxdatahs 416 | 417 | 418 | 419 | 420 | DL1_FORCERXMODE 421 | 422 | 423 | ppi_dl1_forcerxmode 424 | 425 | 426 | 427 | 428 | DL1_ENABLE 429 | 430 | 431 | ppi_dl1_enable 432 | 433 | 434 | 435 | 436 | DL0_RXVALIDHS 437 | 438 | 439 | ppi_dl0_rxvalidhs 440 | 441 | 442 | 443 | 444 | DL0_FORCERXMODE 445 | 446 | 447 | ppi_dl0_forcerxmode 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | regspace_s_axi 456 | 457 | reg0 458 | 0 459 | 4096 460 | 32 461 | register 462 | 463 | 464 | 465 | 466 | 467 | 468 | xilinx_anylanguagesynthesis 469 | Synthesis 470 | :vivado.xilinx.com:synthesis 471 | Verilog 472 | axi_csi 473 | 474 | xilinx_anylanguagesynthesis_view_fileset 475 | 476 | 477 | 478 | viewChecksum 479 | b6a6cb14 480 | 481 | 482 | 483 | 484 | xilinx_anylanguagebehavioralsimulation 485 | Simulation 486 | :vivado.xilinx.com:simulation 487 | Verilog 488 | axi_csi 489 | 490 | xilinx_anylanguagebehavioralsimulation_view_fileset 491 | 492 | 493 | 494 | viewChecksum 495 | b6a6cb14 496 | 497 | 498 | 499 | 500 | xilinx_xpgui 501 | UI Layout 502 | :vivado.xilinx.com:xgui.ui 503 | 504 | xilinx_xpgui_view_fileset 505 | 506 | 507 | 508 | viewChecksum 509 | f92e9879 510 | 511 | 512 | 513 | 514 | 515 | 516 | csi_intr 517 | 518 | out 519 | 520 | 521 | wire 522 | xilinx_anylanguagesynthesis 523 | xilinx_anylanguagebehavioralsimulation 524 | 525 | 526 | 527 | 528 | 529 | rxbyteclkhs_resetn 530 | 531 | in 532 | 533 | 534 | wire 535 | xilinx_anylanguagesynthesis 536 | xilinx_anylanguagebehavioralsimulation 537 | 538 | 539 | 540 | 541 | 542 | ppi_cl_stopstate 543 | 544 | in 545 | 546 | 547 | wire 548 | xilinx_anylanguagesynthesis 549 | xilinx_anylanguagebehavioralsimulation 550 | 551 | 552 | 553 | 554 | 555 | ppi_cl_enable 556 | 557 | out 558 | 559 | 560 | wire 561 | xilinx_anylanguagesynthesis 562 | xilinx_anylanguagebehavioralsimulation 563 | 564 | 565 | 566 | 567 | 568 | ppi_rxbyteclkhs_clk 569 | 570 | in 571 | 572 | 573 | wire 574 | xilinx_anylanguagesynthesis 575 | xilinx_anylanguagebehavioralsimulation 576 | 577 | 578 | 579 | 580 | 581 | ppi_dl0_rxactivehs 582 | 583 | in 584 | 585 | 586 | wire 587 | xilinx_anylanguagesynthesis 588 | xilinx_anylanguagebehavioralsimulation 589 | 590 | 591 | 592 | 593 | 594 | ppi_dl0_rxsynchs 595 | 596 | in 597 | 598 | 599 | wire 600 | xilinx_anylanguagesynthesis 601 | xilinx_anylanguagebehavioralsimulation 602 | 603 | 604 | 605 | 606 | 607 | ppi_dl0_enable 608 | 609 | out 610 | 611 | 612 | wire 613 | xilinx_anylanguagesynthesis 614 | xilinx_anylanguagebehavioralsimulation 615 | 616 | 617 | 618 | 619 | 620 | ppi_dl0_forcerxmode 621 | 622 | out 623 | 624 | 625 | wire 626 | xilinx_anylanguagesynthesis 627 | xilinx_anylanguagebehavioralsimulation 628 | 629 | 630 | 631 | 632 | 633 | ppi_dl0_rxvalidhs 634 | 635 | in 636 | 637 | 638 | wire 639 | xilinx_anylanguagesynthesis 640 | xilinx_anylanguagebehavioralsimulation 641 | 642 | 643 | 644 | 645 | 646 | ppi_dl0_rxdatahs 647 | 648 | in 649 | 650 | 7 651 | 0 652 | 653 | 654 | 655 | wire 656 | xilinx_anylanguagesynthesis 657 | xilinx_anylanguagebehavioralsimulation 658 | 659 | 660 | 661 | 662 | 663 | ppi_dl1_rxactivehs 664 | 665 | in 666 | 667 | 668 | wire 669 | xilinx_anylanguagesynthesis 670 | xilinx_anylanguagebehavioralsimulation 671 | 672 | 673 | 674 | 675 | 676 | ppi_dl1_rxsynchs 677 | 678 | in 679 | 680 | 681 | wire 682 | xilinx_anylanguagesynthesis 683 | xilinx_anylanguagebehavioralsimulation 684 | 685 | 686 | 687 | 688 | 689 | ppi_dl1_enable 690 | 691 | out 692 | 693 | 694 | wire 695 | xilinx_anylanguagesynthesis 696 | xilinx_anylanguagebehavioralsimulation 697 | 698 | 699 | 700 | 701 | 702 | ppi_dl1_forcerxmode 703 | 704 | out 705 | 706 | 707 | wire 708 | xilinx_anylanguagesynthesis 709 | xilinx_anylanguagebehavioralsimulation 710 | 711 | 712 | 713 | 714 | 715 | ppi_dl1_rxvalidhs 716 | 717 | in 718 | 719 | 720 | wire 721 | xilinx_anylanguagesynthesis 722 | xilinx_anylanguagebehavioralsimulation 723 | 724 | 725 | 726 | 727 | 728 | ppi_dl1_rxdatahs 729 | 730 | in 731 | 732 | 7 733 | 0 734 | 735 | 736 | 737 | wire 738 | xilinx_anylanguagesynthesis 739 | xilinx_anylanguagebehavioralsimulation 740 | 741 | 742 | 743 | 744 | 745 | regspace_s_axi_aclk 746 | 747 | in 748 | 749 | 750 | wire 751 | xilinx_anylanguagesynthesis 752 | xilinx_anylanguagebehavioralsimulation 753 | 754 | 755 | 756 | 757 | 758 | regspace_s_axi_aresetn 759 | 760 | in 761 | 762 | 763 | wire 764 | xilinx_anylanguagesynthesis 765 | xilinx_anylanguagebehavioralsimulation 766 | 767 | 768 | 769 | 770 | 771 | regspace_s_axi_awaddr 772 | 773 | in 774 | 775 | 4 776 | 0 777 | 778 | 779 | 780 | wire 781 | xilinx_anylanguagesynthesis 782 | xilinx_anylanguagebehavioralsimulation 783 | 784 | 785 | 786 | 0 787 | 788 | 789 | 790 | 791 | regspace_s_axi_awprot 792 | 793 | in 794 | 795 | 2 796 | 0 797 | 798 | 799 | 800 | wire 801 | xilinx_anylanguagesynthesis 802 | xilinx_anylanguagebehavioralsimulation 803 | 804 | 805 | 806 | 0 807 | 808 | 809 | 810 | 811 | regspace_s_axi_awvalid 812 | 813 | in 814 | 815 | 816 | wire 817 | xilinx_anylanguagesynthesis 818 | xilinx_anylanguagebehavioralsimulation 819 | 820 | 821 | 822 | 0 823 | 824 | 825 | 826 | 827 | regspace_s_axi_awready 828 | 829 | out 830 | 831 | 832 | wire 833 | xilinx_anylanguagesynthesis 834 | xilinx_anylanguagebehavioralsimulation 835 | 836 | 837 | 838 | 839 | 840 | regspace_s_axi_wdata 841 | 842 | in 843 | 844 | 31 845 | 0 846 | 847 | 848 | 849 | wire 850 | xilinx_anylanguagesynthesis 851 | xilinx_anylanguagebehavioralsimulation 852 | 853 | 854 | 855 | 0 856 | 857 | 858 | 859 | 860 | regspace_s_axi_wstrb 861 | 862 | in 863 | 864 | 3 865 | 0 866 | 867 | 868 | 869 | wire 870 | xilinx_anylanguagesynthesis 871 | xilinx_anylanguagebehavioralsimulation 872 | 873 | 874 | 875 | 1 876 | 877 | 878 | 879 | 880 | regspace_s_axi_wvalid 881 | 882 | in 883 | 884 | 885 | wire 886 | xilinx_anylanguagesynthesis 887 | xilinx_anylanguagebehavioralsimulation 888 | 889 | 890 | 891 | 0 892 | 893 | 894 | 895 | 896 | regspace_s_axi_wready 897 | 898 | out 899 | 900 | 901 | wire 902 | xilinx_anylanguagesynthesis 903 | xilinx_anylanguagebehavioralsimulation 904 | 905 | 906 | 907 | 908 | 909 | regspace_s_axi_bresp 910 | 911 | out 912 | 913 | 1 914 | 0 915 | 916 | 917 | 918 | wire 919 | xilinx_anylanguagesynthesis 920 | xilinx_anylanguagebehavioralsimulation 921 | 922 | 923 | 924 | 925 | 926 | regspace_s_axi_bvalid 927 | 928 | out 929 | 930 | 931 | wire 932 | xilinx_anylanguagesynthesis 933 | xilinx_anylanguagebehavioralsimulation 934 | 935 | 936 | 937 | 938 | 939 | regspace_s_axi_bready 940 | 941 | in 942 | 943 | 944 | wire 945 | xilinx_anylanguagesynthesis 946 | xilinx_anylanguagebehavioralsimulation 947 | 948 | 949 | 950 | 0 951 | 952 | 953 | 954 | 955 | regspace_s_axi_araddr 956 | 957 | in 958 | 959 | 4 960 | 0 961 | 962 | 963 | 964 | wire 965 | xilinx_anylanguagesynthesis 966 | xilinx_anylanguagebehavioralsimulation 967 | 968 | 969 | 970 | 0 971 | 972 | 973 | 974 | 975 | regspace_s_axi_arprot 976 | 977 | in 978 | 979 | 2 980 | 0 981 | 982 | 983 | 984 | wire 985 | xilinx_anylanguagesynthesis 986 | xilinx_anylanguagebehavioralsimulation 987 | 988 | 989 | 990 | 0 991 | 992 | 993 | 994 | 995 | regspace_s_axi_arvalid 996 | 997 | in 998 | 999 | 1000 | wire 1001 | xilinx_anylanguagesynthesis 1002 | xilinx_anylanguagebehavioralsimulation 1003 | 1004 | 1005 | 1006 | 0 1007 | 1008 | 1009 | 1010 | 1011 | regspace_s_axi_arready 1012 | 1013 | out 1014 | 1015 | 1016 | wire 1017 | xilinx_anylanguagesynthesis 1018 | xilinx_anylanguagebehavioralsimulation 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | regspace_s_axi_rdata 1025 | 1026 | out 1027 | 1028 | 31 1029 | 0 1030 | 1031 | 1032 | 1033 | wire 1034 | xilinx_anylanguagesynthesis 1035 | xilinx_anylanguagebehavioralsimulation 1036 | 1037 | 1038 | 1039 | 0 1040 | 1041 | 1042 | 1043 | 1044 | regspace_s_axi_rresp 1045 | 1046 | out 1047 | 1048 | 1 1049 | 0 1050 | 1051 | 1052 | 1053 | wire 1054 | xilinx_anylanguagesynthesis 1055 | xilinx_anylanguagebehavioralsimulation 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | regspace_s_axi_rvalid 1062 | 1063 | out 1064 | 1065 | 1066 | wire 1067 | xilinx_anylanguagesynthesis 1068 | xilinx_anylanguagebehavioralsimulation 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | regspace_s_axi_rready 1075 | 1076 | in 1077 | 1078 | 1079 | wire 1080 | xilinx_anylanguagesynthesis 1081 | xilinx_anylanguagebehavioralsimulation 1082 | 1083 | 1084 | 1085 | 0 1086 | 1087 | 1088 | 1089 | 1090 | output_m_axis_tvalid 1091 | 1092 | out 1093 | 1094 | 1095 | wire 1096 | xilinx_anylanguagesynthesis 1097 | xilinx_anylanguagebehavioralsimulation 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | output_m_axis_tdata 1104 | 1105 | out 1106 | 1107 | 63 1108 | 0 1109 | 1110 | 1111 | 1112 | wire 1113 | xilinx_anylanguagesynthesis 1114 | xilinx_anylanguagebehavioralsimulation 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | output_m_axis_tstrb 1121 | 1122 | out 1123 | 1124 | 7 1125 | 0 1126 | 1127 | 1128 | 1129 | wire 1130 | xilinx_anylanguagesynthesis 1131 | xilinx_anylanguagebehavioralsimulation 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | output_m_axis_tlast 1138 | 1139 | out 1140 | 1141 | 1142 | wire 1143 | xilinx_anylanguagesynthesis 1144 | xilinx_anylanguagebehavioralsimulation 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | output_m_axis_tready 1151 | 1152 | in 1153 | 1154 | 1155 | wire 1156 | xilinx_anylanguagesynthesis 1157 | xilinx_anylanguagebehavioralsimulation 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | choice_list_99a1d2b9 1167 | LEVEL_HIGH 1168 | LEVEL_LOW 1169 | EDGE_RISING 1170 | EDGE_FALLING 1171 | 1172 | 1173 | choice_list_9d8b0d81 1174 | ACTIVE_HIGH 1175 | ACTIVE_LOW 1176 | 1177 | 1178 | 1179 | 1180 | xilinx_anylanguagesynthesis_view_fileset 1181 | 1182 | hdl/axilite_control.v 1183 | verilogSource 1184 | 1185 | 1186 | hdl/ecc_block.v 1187 | verilogSource 1188 | 1189 | 1190 | hdl/pckthandler.v 1191 | verilogSource 1192 | 1193 | 1194 | hdl/pckthandler_fsm.v 1195 | verilogSource 1196 | 1197 | 1198 | hdl/ph_finder.v 1199 | verilogSource 1200 | 1201 | 1202 | hdl/raw10_decoder.v 1203 | verilogSource 1204 | 1205 | 1206 | hdl/axi_csi.v 1207 | verilogSource 1208 | 1209 | 1210 | hdl/wordalign.v 1211 | verilogSource 1212 | CHECKSUM_d54e92fb 1213 | 1214 | 1215 | 1216 | xilinx_anylanguagebehavioralsimulation_view_fileset 1217 | 1218 | hdl/axilite_control.v 1219 | verilogSource 1220 | 1221 | 1222 | hdl/ecc_block.v 1223 | verilogSource 1224 | 1225 | 1226 | hdl/pckthandler.v 1227 | verilogSource 1228 | 1229 | 1230 | hdl/pckthandler_fsm.v 1231 | verilogSource 1232 | 1233 | 1234 | hdl/ph_finder.v 1235 | verilogSource 1236 | 1237 | 1238 | hdl/raw10_decoder.v 1239 | verilogSource 1240 | 1241 | 1242 | hdl/axi_csi.v 1243 | verilogSource 1244 | 1245 | 1246 | hdl/wordalign.v 1247 | verilogSource 1248 | 1249 | 1250 | 1251 | xilinx_xpgui_view_fileset 1252 | 1253 | xgui/axi_csi_v1_1.tcl 1254 | tclSource 1255 | CHECKSUM_f92e9879 1256 | XGUI_VERSION_2 1257 | 1258 | 1259 | 1260 | CSI decoder for 2-lane, 10-bpp camera 1261 | 1262 | 1263 | Component_Name 1264 | axi_csi_v1_1_v1_0 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | zynq 1271 | qzynq 1272 | azynq 1273 | zynquplus 1274 | 1275 | 1276 | /UserIP 1277 | /Video_&_Image_Processing 1278 | 1279 | axi_csi 1280 | package_project 1281 | 3 1282 | 1283 | user.org:user:axi_csi_v1_1:1.0 1284 | 1285 | 2018-06-14T06:14:13Z 1286 | 1287 | 1288 | /mnt/data/Documents/research/fcam5/mipi_csi/csirx 1289 | /mnt/data/Documents/research/fcam5/mipi_csi/csirx 1290 | /mnt/data/Documents/research/fcam5/mipi_csi/csirx 1291 | /nobackup/sebell/work/ultrazed/ip_repo/csirx 1292 | 1293 | 1294 | 1295 | 2017.2 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | -------------------------------------------------------------------------------- /design_modules.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 43 | 49 | 50 | 58 | 64 | 65 | 73 | 79 | 80 | 88 | 94 | 95 | 103 | 109 | 110 | 118 | 124 | 125 | 133 | 139 | 140 | 148 | 154 | 155 | 163 | 169 | 170 | 178 | 184 | 185 | 193 | 199 | 200 | 201 | 221 | 224 | 225 | 227 | 228 | 230 | image/svg+xml 231 | 233 | 234 | 235 | 236 | 237 | 241 | 248 | csirx 259 | PPI from DPHY 270 | byteclk from DPHY 281 | 287 | AXI4 stream 298 | 305 | resetn 316 | wordalign 327 | 333 | 339 | word out 350 | word valid 361 | 368 | packet handler 379 | 384 | 389 | 395 | 401 | out_stream 412 | frame_valid 423 | 429 | frame_active 440 | 447 | raw10_decoder 458 | 465 | ph_finder 476 | 483 | ecc_block 494 | 501 | pckthandler_fsm 512 | 518 | 524 | 530 | 531 | 532 | -------------------------------------------------------------------------------- /hdl/axi_csi.v: -------------------------------------------------------------------------------- 1 | /* axi_csi Top-level wrapper for the CSI receiver with AXI-Lite control 2 | * interface. 3 | */ 4 | 5 | `timescale 1 ns / 1 ps 6 | 7 | module axi_csi # 8 | ( 9 | localparam CONTROL_DATA_WIDTH = 32, 10 | localparam CONTROL_ADDR_WIDTH = 5 11 | ) 12 | ( 13 | // interrupt line 14 | output wire csi_intr, 15 | 16 | // reset signal, synchronized to ppi_rxbyteclkhs_clk 17 | input wire rxbyteclkhs_resetn, 18 | 19 | // PPI interface 20 | input wire ppi_cl_stopstate, 21 | output wire ppi_cl_enable, // clock enable 22 | input wire ppi_rxbyteclkhs_clk, // receive byte clock 23 | 24 | input wire ppi_dl0_rxactivehs, // whether high-speed receive is active on this lane 25 | input wire ppi_dl0_rxsynchs, // pulse at beginning of high-speed transmission 26 | output wire ppi_dl0_enable, // enable this lane 27 | output wire ppi_dl0_forcerxmode, 28 | input wire ppi_dl0_rxvalidhs, // this lane is valid 29 | input wire [7:0] ppi_dl0_rxdatahs,// data for this lane 30 | 31 | input wire ppi_dl1_rxactivehs, // whether high-speed receive is active on this lane 32 | input wire ppi_dl1_rxsynchs, // pulse at beginning of high-speed transmission 33 | output wire ppi_dl1_enable, // enable this lane 34 | output wire ppi_dl1_forcerxmode, 35 | input wire ppi_dl1_rxvalidhs, // this lane is valid 36 | input wire [7:0] ppi_dl1_rxdatahs,// data for this lane 37 | 38 | // AXI-Lite control bus 39 | input wire regspace_s_axi_aclk, 40 | input wire regspace_s_axi_aresetn, 41 | input wire [CONTROL_ADDR_WIDTH-1 : 0] regspace_s_axi_awaddr, 42 | input wire [2 : 0] regspace_s_axi_awprot, 43 | input wire regspace_s_axi_awvalid, 44 | output wire regspace_s_axi_awready, 45 | input wire [CONTROL_DATA_WIDTH-1 : 0] regspace_s_axi_wdata, 46 | input wire [(CONTROL_DATA_WIDTH/8)-1 : 0] regspace_s_axi_wstrb, 47 | input wire regspace_s_axi_wvalid, 48 | output wire regspace_s_axi_wready, 49 | output wire [1 : 0] regspace_s_axi_bresp, 50 | output wire regspace_s_axi_bvalid, 51 | input wire regspace_s_axi_bready, 52 | input wire [CONTROL_ADDR_WIDTH-1 : 0] regspace_s_axi_araddr, 53 | input wire [2 : 0] regspace_s_axi_arprot, 54 | input wire regspace_s_axi_arvalid, 55 | output wire regspace_s_axi_arready, 56 | output wire [CONTROL_DATA_WIDTH-1 : 0] regspace_s_axi_rdata, 57 | output wire [1 : 0] regspace_s_axi_rresp, 58 | output wire regspace_s_axi_rvalid, 59 | input wire regspace_s_axi_rready, 60 | 61 | 62 | // AXI-Stream master output 63 | // synchronized to the ppi_rxbyteclkhs_clk clock signal 64 | output wire output_m_axis_tvalid, 65 | output wire [63: 0] output_m_axis_tdata, 66 | output wire [7: 0] output_m_axis_tstrb, 67 | output wire output_m_axis_tlast, 68 | input wire output_m_axis_tready 69 | ); 70 | 71 | // Instantiation of Axi Bus Interface RegSpace_S_AXI 72 | // All logic is embedded inside RegSpace_S_AXI 73 | axilite_control # ( 74 | .N_DATA_LANES(2), 75 | .C_S_AXI_DATA_WIDTH(32), 76 | .C_S_AXI_ADDR_WIDTH(5) 77 | ) axilite_control_inst ( 78 | // interrupt line 79 | .csi_intr(csi_intr), 80 | 81 | // reset signal 82 | .rxbyteclkhs_resetn(rxbyteclkhs_resetn), 83 | 84 | // PPI interface 85 | .cl_stopstate(ppi_cl_stopstate), 86 | .cl_enable(ppi_cl_enable), 87 | .rxbyteclkhs(ppi_rxbyteclkhs_clk), 88 | 89 | .dl0_rxactivehs(ppi_dl0_rxactivehs), 90 | .dl0_rxsynchs(ppi_dl0_rxsynchs), 91 | .dl0_enable(ppi_dl0_enable), 92 | .dl0_forcerxmode(ppi_dl0_forcerxmode), 93 | .dl0_rxvalidhs(ppi_dl0_rxvalidhs), 94 | .dl0_rxdatahs(ppi_dl0_rxdatahs), 95 | 96 | .dl1_rxactivehs(ppi_dl1_rxactivehs), 97 | .dl1_rxsynchs(ppi_dl1_rxsynchs), 98 | .dl1_enable(ppi_dl1_enable), 99 | .dl1_forcerxmode(ppi_dl1_forcerxmode), 100 | .dl1_rxvalidhs(ppi_dl1_rxvalidhs), 101 | .dl1_rxdatahs(ppi_dl1_rxdatahs), 102 | 103 | // AXI Stream Interface Outpout 104 | .m_axis_tvalid(output_m_axis_tvalid), 105 | .m_axis_tdata(output_m_axis_tdata), 106 | .m_axis_tstrb(output_m_axis_tstrb), 107 | .m_axis_tlast(output_m_axis_tlast), 108 | .m_axis_tready(output_m_axis_tready), 109 | 110 | // AXI Lite Interface RegSpace 111 | .S_AXI_ACLK(regspace_s_axi_aclk), 112 | .S_AXI_ARESETN(regspace_s_axi_aresetn), 113 | .S_AXI_AWADDR(regspace_s_axi_awaddr), 114 | .S_AXI_AWPROT(regspace_s_axi_awprot), 115 | .S_AXI_AWVALID(regspace_s_axi_awvalid), 116 | .S_AXI_AWREADY(regspace_s_axi_awready), 117 | .S_AXI_WDATA(regspace_s_axi_wdata), 118 | .S_AXI_WSTRB(regspace_s_axi_wstrb), 119 | .S_AXI_WVALID(regspace_s_axi_wvalid), 120 | .S_AXI_WREADY(regspace_s_axi_wready), 121 | .S_AXI_BRESP(regspace_s_axi_bresp), 122 | .S_AXI_BVALID(regspace_s_axi_bvalid), 123 | .S_AXI_BREADY(regspace_s_axi_bready), 124 | .S_AXI_ARADDR(regspace_s_axi_araddr), 125 | .S_AXI_ARPROT(regspace_s_axi_arprot), 126 | .S_AXI_ARVALID(regspace_s_axi_arvalid), 127 | .S_AXI_ARREADY(regspace_s_axi_arready), 128 | .S_AXI_RDATA(regspace_s_axi_rdata), 129 | .S_AXI_RRESP(regspace_s_axi_rresp), 130 | .S_AXI_RVALID(regspace_s_axi_rvalid), 131 | .S_AXI_RREADY(regspace_s_axi_rready) 132 | ); 133 | 134 | endmodule 135 | -------------------------------------------------------------------------------- /hdl/axilite_control.v: -------------------------------------------------------------------------------- 1 | /* axilite_control Implementation of an AXI-Lite control bus and register 2 | * space for the CSI receiver. */ 3 | 4 | `timescale 1 ns / 1 ps 5 | 6 | module axilite_control # 7 | ( 8 | // Lots of things are hard-coded for 2 data lanes, so this isn't configurable 9 | parameter integer N_DATA_LANES = 2, 10 | 11 | // Width of S_AXI data bus 12 | parameter integer C_S_AXI_DATA_WIDTH = 32, 13 | // Width of S_AXI address bus 14 | parameter integer C_S_AXI_ADDR_WIDTH = 5 15 | ) 16 | ( 17 | // interrupt line 18 | output wire csi_intr, 19 | 20 | // reset signal synchronized to rxbyteclkhs clock 21 | input wire rxbyteclkhs_resetn, 22 | 23 | // PPI interface 24 | input wire cl_stopstate, 25 | output wire cl_enable, 26 | input wire rxbyteclkhs, 27 | 28 | input wire dl0_rxactivehs, 29 | input wire dl0_rxsynchs, 30 | output wire dl0_enable, 31 | output wire dl0_forcerxmode, 32 | input wire dl0_rxvalidhs, 33 | input wire [7:0] dl0_rxdatahs, 34 | 35 | input wire dl1_rxactivehs, 36 | input wire dl1_rxsynchs, 37 | output wire dl1_enable, 38 | output wire dl1_forcerxmode, 39 | input wire dl1_rxvalidhs, 40 | input wire [7:0] dl1_rxdatahs, 41 | 42 | // AXI Stream Interface Output 43 | // Uses the rxbyteclkhs clock 44 | // and rxbyteclkhs_resetn reset signals 45 | output wire m_axis_tvalid, 46 | output wire [63:0] m_axis_tdata, 47 | output wire [7:0] m_axis_tstrb, 48 | output wire m_axis_tlast, 49 | input wire m_axis_tready, 50 | 51 | // User ports ends 52 | // Do not modify the ports beyond this line 53 | 54 | // Global Clock Signal 55 | input wire S_AXI_ACLK, 56 | // Global Reset Signal. This Signal is Active LOW 57 | input wire S_AXI_ARESETN, 58 | // Write address (issued by master, acceped by Slave) 59 | input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, 60 | // Write channel Protection type. This signal indicates the 61 | // privilege and security level of the transaction, and whether 62 | // the transaction is a data access or an instruction access. 63 | input wire [2 : 0] S_AXI_AWPROT, 64 | // Write address valid. This signal indicates that the master signaling 65 | // valid write address and control information. 66 | input wire S_AXI_AWVALID, 67 | // Write address ready. This signal indicates that the slave is ready 68 | // to accept an address and associated control signals. 69 | output wire S_AXI_AWREADY, 70 | // Write data (issued by master, acceped by Slave) 71 | input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, 72 | // Write strobes. This signal indicates which byte lanes hold 73 | // valid data. There is one write strobe bit for each eight 74 | // bits of the write data bus. 75 | input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, 76 | // Write valid. This signal indicates that valid write 77 | // data and strobes are available. 78 | input wire S_AXI_WVALID, 79 | // Write ready. This signal indicates that the slave 80 | // can accept the write data. 81 | output wire S_AXI_WREADY, 82 | // Write response. This signal indicates the status 83 | // of the write transaction. 84 | output wire [1 : 0] S_AXI_BRESP, 85 | // Write response valid. This signal indicates that the channel 86 | // is signaling a valid write response. 87 | output wire S_AXI_BVALID, 88 | // Response ready. This signal indicates that the master 89 | // can accept a write response. 90 | input wire S_AXI_BREADY, 91 | // Read address (issued by master, acceped by Slave) 92 | input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, 93 | // Protection type. This signal indicates the privilege 94 | // and security level of the transaction, and whether the 95 | // transaction is a data access or an instruction access. 96 | input wire [2 : 0] S_AXI_ARPROT, 97 | // Read address valid. This signal indicates that the channel 98 | // is signaling valid read address and control information. 99 | input wire S_AXI_ARVALID, 100 | // Read address ready. This signal indicates that the slave is 101 | // ready to accept an address and associated control signals. 102 | output wire S_AXI_ARREADY, 103 | // Read data (issued by slave) 104 | output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, 105 | // Read response. This signal indicates the status of the 106 | // read transfer. 107 | output wire [1 : 0] S_AXI_RRESP, 108 | // Read valid. This signal indicates that the channel is 109 | // signaling the required read data. 110 | output wire S_AXI_RVALID, 111 | // Read ready. This signal indicates that the master can 112 | // accept the read data and response information. 113 | input wire S_AXI_RREADY 114 | ); 115 | 116 | // used for interrupts and run/stop 117 | localparam NUM_INTRS = 2; // number of interrupts 118 | localparam SOF_REG_BIT = 2; // bit position for SOF interrupts in CONFIG, CTRL, and STATUS registers 119 | localparam SOF_INTR_BIT = 0; // bit position for SOF interrupts in irqs_posted 120 | localparam EOF_REG_BIT = 3; // bit position for EOF interrupts in CONFIG, CTRL, and STATUS registers 121 | localparam OUTPUT_EN_BIT = 4; // bit position for Output Enable. When zero, core runs but output isn't produced 122 | localparam EOF_INTR_BIT = 1; // bit position for EOF interrupts in irqs_posted 123 | localparam GLOBALINT_BIT= 1; // bit position for global interrupts in CONFIG, CTRL, and STATUS registers 124 | localparam RS_REG_BIT = 0; // bit position for Run/Stop in CONFIG, CTRL, and STATUS registers 125 | 126 | reg [(NUM_INTRS-1):0] irqs_posted, irqs_acked; 127 | reg frame_active_new, frame_active_last; 128 | reg RS_flag; 129 | reg RS_new, RS_last; 130 | reg enable_output; // Output enable flag latched in at SOF 131 | 132 | // other user signals 133 | wire reset; 134 | wire [(N_DATA_LANES*8)-1:0] aligned_word_out; 135 | wire aligned_word_valid; 136 | wire frame_active; // whether we're in the process of receiving a frame 137 | wire frame_valid; // whether the output frame data is actually valid 138 | wire [(N_DATA_LANES*8)-1:0] frame_out; 139 | wire [63:0] unpacked_out; 140 | wire unpacked_out_valid; 141 | wire unpacked_last; 142 | wire last_packet; 143 | 144 | 145 | // AXI4LITE signals 146 | reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; 147 | reg axi_awready; 148 | reg axi_wready; 149 | reg [1 : 0] axi_bresp; 150 | reg axi_bvalid; 151 | reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; 152 | reg axi_arready; 153 | reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; 154 | reg [1 : 0] axi_rresp; 155 | reg axi_rvalid; 156 | 157 | // Example-specific design signals 158 | // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH 159 | // ADDR_LSB is used for addressing 32/64 bit registers/memories 160 | // ADDR_LSB = 2 for 32 bits (n downto 2) 161 | // ADDR_LSB = 3 for 64 bits (n downto 3) 162 | localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1; 163 | localparam integer OPT_MEM_ADDR_BITS = 2; 164 | //---------------------------------------------- 165 | //-- Signals for user logic register space example 166 | //------------------------------------------------ 167 | //-- Number of Slave Registers 8 168 | reg [C_S_AXI_DATA_WIDTH-1:0] CSI_CONFIG_REG; // configuration register (R/W) 169 | reg [C_S_AXI_DATA_WIDTH-1:0] CSI_CTRL_SET_REG; // "SET" register for CSI_CTRL (write-only, read all 0's) 170 | reg [C_S_AXI_DATA_WIDTH-1:0] CSI_CTRL_CLEAR_REG; // "CLEAR" register for CSI_CTRL (write-only, read all 0's) 171 | reg [C_S_AXI_DATA_WIDTH-1:0] CSI_STATUS_REG; // status register (read-only) 172 | reg [C_S_AXI_DATA_WIDTH-1:0] CSI_FR_LINES_REG; // expected number of image lines per frame 173 | reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg5; // unimplemented (always read 0xDEADBEEF 174 | reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg6; // unimplemented (always read 0xDEADBEEF 175 | reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg7; // unimplemented (always read 0xDEADBEEF 176 | wire slv_reg_rden; 177 | wire slv_reg_wren; 178 | reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; 179 | integer byte_index; 180 | reg aw_en; 181 | 182 | // I/O Connections assignments 183 | 184 | assign S_AXI_AWREADY = axi_awready; 185 | assign S_AXI_WREADY = axi_wready; 186 | assign S_AXI_BRESP = axi_bresp; 187 | assign S_AXI_BVALID = axi_bvalid; 188 | assign S_AXI_ARREADY = axi_arready; 189 | assign S_AXI_RDATA = axi_rdata; 190 | assign S_AXI_RRESP = axi_rresp; 191 | assign S_AXI_RVALID = axi_rvalid; 192 | // Implement axi_awready generation 193 | // axi_awready is asserted for one S_AXI_ACLK clock cycle when both 194 | // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is 195 | // de-asserted when reset is low. 196 | 197 | always @( posedge S_AXI_ACLK ) 198 | begin 199 | if ( S_AXI_ARESETN == 1'b0 ) 200 | begin 201 | axi_awready <= 1'b0; 202 | aw_en <= 1'b1; 203 | end 204 | else 205 | begin 206 | if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) 207 | begin 208 | // slave is ready to accept write address when 209 | // there is a valid write address and write data 210 | // on the write address and data bus. This design 211 | // expects no outstanding transactions. 212 | axi_awready <= 1'b1; 213 | aw_en <= 1'b0; 214 | end 215 | else if (S_AXI_BREADY && axi_bvalid) 216 | begin 217 | aw_en <= 1'b1; 218 | axi_awready <= 1'b0; 219 | end 220 | else 221 | begin 222 | axi_awready <= 1'b0; 223 | end 224 | end 225 | end 226 | 227 | // Implement axi_awaddr latching 228 | // This process is used to latch the address when both 229 | // S_AXI_AWVALID and S_AXI_WVALID are valid. 230 | 231 | always @( posedge S_AXI_ACLK ) 232 | begin 233 | if ( S_AXI_ARESETN == 1'b0 ) 234 | begin 235 | axi_awaddr <= 0; 236 | end 237 | else 238 | begin 239 | if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) 240 | begin 241 | // Write Address latching 242 | axi_awaddr <= S_AXI_AWADDR; 243 | end 244 | end 245 | end 246 | 247 | // Implement axi_wready generation 248 | // axi_wready is asserted for one S_AXI_ACLK clock cycle when both 249 | // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 250 | // de-asserted when reset is low. 251 | 252 | always @( posedge S_AXI_ACLK ) 253 | begin 254 | if ( S_AXI_ARESETN == 1'b0 ) 255 | begin 256 | axi_wready <= 1'b0; 257 | end 258 | else 259 | begin 260 | if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) 261 | begin 262 | // slave is ready to accept write data when 263 | // there is a valid write address and write data 264 | // on the write address and data bus. This design 265 | // expects no outstanding transactions. 266 | axi_wready <= 1'b1; 267 | end 268 | else 269 | begin 270 | axi_wready <= 1'b0; 271 | end 272 | end 273 | end 274 | 275 | // Implement memory mapped register select and write logic generation 276 | // The write data is accepted and written to memory mapped registers when 277 | // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to 278 | // select byte enables of slave registers while writing. 279 | // These registers are cleared when reset (active low) is applied. 280 | // Slave register write enable is asserted when valid address and data are available 281 | // and the slave is ready to accept the write address and write data. 282 | assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; 283 | 284 | always @( posedge S_AXI_ACLK ) 285 | begin 286 | if ( S_AXI_ARESETN == 1'b0 ) 287 | begin 288 | CSI_CONFIG_REG <= 0; 289 | CSI_CTRL_SET_REG <= 0; 290 | CSI_CTRL_CLEAR_REG <= 0; 291 | CSI_STATUS_REG <= 0; 292 | CSI_FR_LINES_REG <= 0; 293 | slv_reg5 <= 0; 294 | slv_reg6 <= 0; 295 | slv_reg7 <= 0; 296 | 297 | irqs_acked <= 0; 298 | RS_new <= 0; 299 | RS_last <= 0; 300 | end 301 | else begin 302 | irqs_acked <= 0; 303 | RS_last <= RS_new; 304 | 305 | if (slv_reg_wren) 306 | begin 307 | case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 308 | 3'h0: begin 309 | CSI_CONFIG_REG <= S_AXI_WDATA; 310 | end 311 | 3'h1: begin 312 | // handle interrupts acknowledgements 313 | irqs_acked <= {2{S_AXI_WDATA[GLOBALINT_BIT]}} | {S_AXI_WDATA[EOF_REG_BIT], S_AXI_WDATA[SOF_REG_BIT]}; 314 | 315 | // handle R/S 316 | if(S_AXI_WDATA[0] & ~RS_flag) begin 317 | RS_new <= 1'b1; 318 | RS_last <= 1'b0; 319 | end 320 | end 321 | 3'h2: begin 322 | if(S_AXI_WDATA[0] == 1'b1) begin 323 | RS_new <= 1'b0; 324 | end 325 | end 326 | 3'h3: begin 327 | // status register is read-only 328 | // writes are ignored 329 | CSI_STATUS_REG <= CSI_STATUS_REG; 330 | end 331 | 3'h4: begin 332 | CSI_FR_LINES_REG <= S_AXI_WDATA; 333 | end 334 | 3'h5: 335 | for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 336 | if ( S_AXI_WSTRB[byte_index] == 1 ) begin 337 | // Respective byte enables are asserted as per write strobes 338 | // Slave register 5 339 | slv_reg5[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 340 | end 341 | 3'h6: 342 | for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 343 | if ( S_AXI_WSTRB[byte_index] == 1 ) begin 344 | // Respective byte enables are asserted as per write strobes 345 | // Slave register 6 346 | slv_reg6[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 347 | end 348 | 3'h7: 349 | for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 350 | if ( S_AXI_WSTRB[byte_index] == 1 ) begin 351 | // Respective byte enables are asserted as per write strobes 352 | // Slave register 7 353 | slv_reg7[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 354 | end 355 | default : begin 356 | CSI_CONFIG_REG <= CSI_CONFIG_REG; 357 | CSI_CTRL_SET_REG <= CSI_CTRL_SET_REG; 358 | CSI_CTRL_CLEAR_REG <= CSI_CTRL_CLEAR_REG; 359 | CSI_STATUS_REG <= CSI_STATUS_REG; 360 | CSI_FR_LINES_REG <= CSI_FR_LINES_REG; 361 | slv_reg5 <= slv_reg5; 362 | slv_reg6 <= slv_reg6; 363 | slv_reg7 <= slv_reg7; 364 | end 365 | endcase 366 | end 367 | end 368 | end 369 | 370 | // Implement write response logic generation 371 | // The write response and response valid signals are asserted by the slave 372 | // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. 373 | // This marks the acceptance of address and indicates the status of 374 | // write transaction. 375 | 376 | always @( posedge S_AXI_ACLK ) 377 | begin 378 | if ( S_AXI_ARESETN == 1'b0 ) 379 | begin 380 | axi_bvalid <= 0; 381 | axi_bresp <= 2'b0; 382 | end 383 | else 384 | begin 385 | if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) 386 | begin 387 | // indicates a valid write response is available 388 | axi_bvalid <= 1'b1; 389 | axi_bresp <= 2'b0; // 'OKAY' response 390 | end // work error responses in future 391 | else 392 | begin 393 | if (S_AXI_BREADY && axi_bvalid) 394 | //check if bready is asserted while bvalid is high) 395 | //(there is a possibility that bready is always asserted high) 396 | begin 397 | axi_bvalid <= 1'b0; 398 | end 399 | end 400 | end 401 | end 402 | 403 | // Implement axi_arready generation 404 | // axi_arready is asserted for one S_AXI_ACLK clock cycle when 405 | // S_AXI_ARVALID is asserted. axi_awready is 406 | // de-asserted when reset (active low) is asserted. 407 | // The read address is also latched when S_AXI_ARVALID is 408 | // asserted. axi_araddr is reset to zero on reset assertion. 409 | 410 | always @( posedge S_AXI_ACLK ) 411 | begin 412 | if ( S_AXI_ARESETN == 1'b0 ) 413 | begin 414 | axi_arready <= 1'b0; 415 | axi_araddr <= 32'b0; 416 | end 417 | else 418 | begin 419 | if (~axi_arready && S_AXI_ARVALID) 420 | begin 421 | // indicates that the slave has acceped the valid read address 422 | axi_arready <= 1'b1; 423 | // Read address latching 424 | axi_araddr <= S_AXI_ARADDR; 425 | end 426 | else 427 | begin 428 | axi_arready <= 1'b0; 429 | end 430 | end 431 | end 432 | 433 | // Implement axi_arvalid generation 434 | // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 435 | // S_AXI_ARVALID and axi_arready are asserted. The slave registers 436 | // data are available on the axi_rdata bus at this instance. The 437 | // assertion of axi_rvalid marks the validity of read data on the 438 | // bus and axi_rresp indicates the status of read transaction.axi_rvalid 439 | // is deasserted on reset (active low). axi_rresp and axi_rdata are 440 | // cleared to zero on reset (active low). 441 | always @( posedge S_AXI_ACLK ) 442 | begin 443 | if ( S_AXI_ARESETN == 1'b0 ) 444 | begin 445 | axi_rvalid <= 0; 446 | axi_rresp <= 0; 447 | end 448 | else 449 | begin 450 | if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) 451 | begin 452 | // Valid read data is available at the read data bus 453 | axi_rvalid <= 1'b1; 454 | axi_rresp <= 2'b0; // 'OKAY' response 455 | end 456 | else if (axi_rvalid && S_AXI_RREADY) 457 | begin 458 | // Read data is accepted by the master 459 | axi_rvalid <= 1'b0; 460 | end 461 | end 462 | end 463 | 464 | // Implement memory mapped register select and read logic generation 465 | // Slave register read enable is asserted when valid address is available 466 | // and the slave is ready to accept the read address. 467 | assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; 468 | always @(*) 469 | begin 470 | // Address decoding for reading registers 471 | case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 472 | 3'h0 : reg_data_out <= CSI_CONFIG_REG; 473 | 3'h1 : reg_data_out <= 0; // CSI_CTRL_SET_REG always returns 0's when read 474 | 3'h2 : reg_data_out <= 0; // CSI_CTRL_CLEAR_REG always returns 0's when read 475 | 3'h3 : begin // Reading status register CSI_STATUS_REG 476 | // interrupts 477 | reg_data_out[31:4] <= 0; 478 | reg_data_out[3] <= irqs_posted[EOF_INTR_BIT]; 479 | reg_data_out[2] <= irqs_posted[SOF_INTR_BIT]; 480 | reg_data_out[1] <= (| irqs_posted); 481 | reg_data_out[0] <= RS_flag; 482 | end 483 | 3'h4 : reg_data_out <= CSI_FR_LINES_REG; 484 | 3'h5 : reg_data_out <= 32'hDEADBEEF; //slv_reg5 is un-implemented and returns 0xDEADBEEF when read 485 | 3'h6 : reg_data_out <= 32'hDEADBEEF; //slv_reg6 is un-implemented and returns 0xDEADBEEF when read 486 | 3'h7 : reg_data_out <= 32'hDEADBEEF; //slv_reg7 is un-implemented and returns 0xDEADBEEF when read 487 | default : reg_data_out <= 0; 488 | endcase 489 | end 490 | 491 | // Output register or memory read data 492 | always @( posedge S_AXI_ACLK ) 493 | begin 494 | if ( S_AXI_ARESETN == 1'b0 ) 495 | begin 496 | axi_rdata <= 0; 497 | end 498 | else 499 | begin 500 | // When there is a valid read address (S_AXI_ARVALID) with 501 | // acceptance of read address by the slave (axi_arready), 502 | // output the read dada 503 | if (slv_reg_rden) 504 | begin 505 | axi_rdata <= reg_data_out; // register read data 506 | end 507 | end 508 | end 509 | 510 | // Add user logic here 511 | 512 | // Make active-high reset 513 | assign reset = ~rxbyteclkhs_resetn | ~RS_flag; 514 | 515 | // interrupt-related 516 | assign csi_intr = CSI_CONFIG_REG[GLOBALINT_BIT] & (| (irqs_posted & CSI_CONFIG_REG[EOF_REG_BIT:SOF_REG_BIT])); 517 | 518 | // interrupt generation logic 519 | always @(posedge S_AXI_ACLK) 520 | begin 521 | if ( S_AXI_ARESETN == 1'b0 ) 522 | begin 523 | irqs_posted <= 0; 524 | frame_active_new <= 0; 525 | frame_active_last <= 0; 526 | end 527 | else begin 528 | frame_active_new <= frame_active; 529 | frame_active_last <= frame_active_new; 530 | 531 | if(~frame_active_last & frame_active_new) irqs_posted[SOF_INTR_BIT] <= 1'b1; 532 | else if(frame_active_last & ~frame_active_new) irqs_posted[EOF_INTR_BIT] <= 1'b1; 533 | else begin 534 | irqs_posted[SOF_INTR_BIT] <= irqs_posted[SOF_INTR_BIT] & ~irqs_acked[SOF_INTR_BIT]; 535 | irqs_posted[EOF_INTR_BIT] <= irqs_posted[EOF_INTR_BIT] & ~irqs_acked[EOF_INTR_BIT]; 536 | end 537 | end 538 | end 539 | 540 | 541 | // generating the RS signal 542 | always @(posedge S_AXI_ACLK) 543 | begin 544 | if ( S_AXI_ARESETN == 1'b0 ) RS_flag <= 0; 545 | else begin 546 | if(RS_last & ~RS_new) RS_flag <= 1'b0; 547 | else if(~RS_last & RS_new) RS_flag <= 1'b1; 548 | else if(~CSI_CONFIG_REG[RS_REG_BIT] & ~frame_active_new & frame_active_last) RS_flag <= 1'b0; 549 | else RS_flag <= RS_flag; 550 | end 551 | end 552 | 553 | // CSI modules 554 | wordalign align( 555 | .clk(rxbyteclkhs), 556 | .resetn(rxbyteclkhs_resetn), 557 | .dl0_rxvalidhs(dl0_rxvalidhs), 558 | .dl0_rxdatahs(dl0_rxdatahs), 559 | .dl1_rxvalidhs(dl1_rxvalidhs), 560 | .dl1_rxdatahs(dl1_rxdatahs), 561 | .word_out(aligned_word_out), 562 | .word_valid(aligned_word_valid) 563 | ); 564 | 565 | pckthandler depacket( 566 | .rxbyteclkhs(rxbyteclkhs), 567 | .reset(reset), 568 | .in_stream_valid(aligned_word_valid), 569 | .in_stream(aligned_word_out), 570 | .frame_active(frame_active), 571 | .frame_valid(frame_valid), 572 | .out_stream(frame_out), 573 | .lines_per_frame(CSI_FR_LINES_REG), 574 | .last_packet(last_packet) 575 | ); 576 | 577 | raw10_decoder unpack( 578 | .rxbyteclkhs(rxbyteclkhs), 579 | .reset(reset), 580 | .frame_active(frame_active), 581 | .frame_valid(frame_valid), 582 | .data_in(frame_out), 583 | .out_valid(unpacked_out_valid), 584 | .data_out(unpacked_out), 585 | .last_packet_in(last_packet), 586 | .last_packet_out(unpacked_last) 587 | ); 588 | 589 | 590 | // Latch in the output enable signal on SOF 591 | // The frame_active signal goes high just before the first data goes out 592 | always @(posedge S_AXI_ACLK) 593 | begin 594 | if ( S_AXI_ARESETN == 1'b0 ) 595 | enable_output <= 0; 596 | else if(~frame_active_last & frame_active_new) 597 | enable_output <= CSI_CONFIG_REG[OUTPUT_EN_BIT]; 598 | else 599 | enable_output <= enable_output; 600 | end 601 | 602 | // Stream Interface 603 | assign m_axis_tdata = enable_output ? unpacked_out : 0; 604 | assign m_axis_tvalid = enable_output ? unpacked_out_valid : 0; 605 | assign m_axis_tstrb = enable_output ? 8'b11111111 : 0; 606 | assign m_axis_tlast = enable_output ? unpacked_last : 0; 607 | 608 | // always enable the D-PHY 609 | assign cl_enable = 1'b1; 610 | assign dl0_enable = 1'b1; 611 | assign dl1_enable = 1'b1; 612 | 613 | // don't force the lanes into reset 614 | assign dl0_forcerxmode = 1'b1; 615 | assign dl1_forcerxmode = 1'b1; 616 | 617 | // User logic ends 618 | 619 | endmodule 620 | -------------------------------------------------------------------------------- /hdl/ecc_block.v: -------------------------------------------------------------------------------- 1 | /* ECC check block (combinational block): validates the packet header info based on received ECC 2 | * Gedeon Nyengele 3 | * 08 January 2018 4 | */ 5 | 6 | /* 7 | * @param PH_in input packet header (input) 8 | * @param PH_out possibly corrected PH without the ECC field (output) 9 | * @param no_error signals whether the PH has no errors (output) 10 | * @param corrected_error signals whether a single bit error was corrected (output) 11 | * @param error signals whether the PH has an error that cannot be corrected (output) 12 | */ 13 | 14 | module ecc_block(PH_in, PH_out, no_error, corrected_error, error); 15 | 16 | parameter PH_SIZE = 32; 17 | parameter ECC_SIZE = 8; 18 | 19 | input [(PH_SIZE-1):0] PH_in; 20 | output reg [(PH_SIZE-ECC_SIZE-1):0] PH_out; 21 | output reg no_error, corrected_error, error; 22 | 23 | wire [(PH_SIZE-ECC_SIZE-1):0] data = PH_in[(PH_SIZE-ECC_SIZE-1):0]; 24 | reg [(ECC_SIZE-1):0] calc_ecc; 25 | reg [(ECC_SIZE-1):0] syndrome; 26 | 27 | always @(*) begin 28 | // compute ECC 29 | calc_ecc = {2'b00, 30 | (^ {data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], data[21], data[22], data[23]}), 31 | (^ {data[4], data[5], data[6], data[7], data[8], data[9], data[16], data[17], data[18], data[19], data[20], data[22], data[23]}), 32 | (^ {data[1], data[2], data[3], data[7], data[8], data[9], data[13], data[14], data[15], data[19], data[20], data[21], data[23]}), 33 | (^ {data[0], data[2], data[3], data[5], data[6], data[9], data[11], data[12], data[15], data[18], data[20], data[21], data[22]}), 34 | (^ {data[0], data[1], data[3], data[4], data[6], data[8], data[10], data[12], data[14], data[17], data[20], data[21], data[22], data[23]}), 35 | (^ {data[0], data[1], data[2], data[4], data[5], data[7], data[10], data[11], data[13], data[16], data[20], data[21], data[22], data[23]}) 36 | }; 37 | 38 | // compute syndrome 39 | syndrome = PH_in[(PH_SIZE-1):(PH_SIZE-ECC_SIZE)] ^ calc_ecc; 40 | 41 | // correct data 42 | case(syndrome) 43 | 8'h07 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<0); end 44 | 8'h0B : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<1); end 45 | 8'h0D : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<2); end 46 | 8'h0E : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<3); end 47 | 8'h13 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<4); end 48 | 8'h15 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<5); end 49 | 8'h16 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<6); end 50 | 8'h19 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<7); end 51 | 8'h1A : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<8); end 52 | 8'h1C : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<9); end 53 | 8'h23 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<10); end 54 | 8'h25 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<11); end 55 | 8'h26 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<12); end 56 | 8'h29 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<13); end 57 | 8'h2A : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<14); end 58 | 8'h2C : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<15); end 59 | 8'h31 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<16); end 60 | 8'h32 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<17); end 61 | 8'h34 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<18); end 62 | 8'h38 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<19); end 63 | 8'h1F : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<20); end 64 | 8'h2F : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<21); end 65 | 8'h37 : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<22); end 66 | 8'h3B : begin {no_error, corrected_error, error} = 3'b010; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0] ^ (1<<23); end 67 | 8'h00 : begin {no_error, corrected_error, error} = 3'b100; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0]; end 68 | default: begin {no_error, corrected_error, error} = 3'b001; PH_out = PH_in[(PH_SIZE-ECC_SIZE-1):0]; end 69 | endcase 70 | end 71 | endmodule -------------------------------------------------------------------------------- /hdl/pckthandler.v: -------------------------------------------------------------------------------- 1 | /* Packet Handler: implements the csi protocol and part of the application-layer protocol 2 | * Gedeon Nyengele 3 | * 08 January 2018 4 | */ 5 | 6 | 7 | /* 8 | * @param rxbyteclkhs byte clock to synchronize to (input) 9 | * @param reset active-high synchronous reset signal (input) 10 | * @param in_stream byte-and-lane-aligned input stream (input) 11 | * @param in_stream_valid determines whether the input stream is valid (input) 12 | * @param out_stream csi payload stream (output) 13 | * @param frame_active determines whether new frame either about to transmitted or in progress (output) 14 | * @param frame_valid determines whether a frame output is in progress (output) 15 | * @param lines_per_frame is the number of image lines per frame 16 | * @param last_packet indicates whether the packet on out_stream is the last packet for the frame 17 | */ 18 | module pckthandler(rxbyteclkhs, reset, in_stream, in_stream_valid, out_stream, frame_active, frame_valid, lines_per_frame, last_packet); 19 | 20 | /* parameters */ 21 | parameter IN_STREAM_WIDTH = 16; 22 | parameter OUT_STREAM_WIDTH = IN_STREAM_WIDTH; 23 | 24 | /* inputs */ 25 | input rxbyteclkhs, reset, in_stream_valid; 26 | input [(IN_STREAM_WIDTH-1):0] in_stream; 27 | input [31:0] lines_per_frame; 28 | 29 | /* outputs */ 30 | output frame_active, frame_valid; 31 | output [(OUT_STREAM_WIDTH-1):0] out_stream; 32 | output last_packet; 33 | 34 | /* internal decl */ 35 | wire [31:0] ph_finder_out; 36 | wire ph_finder_ph_select; 37 | wire ph_finder_valid, ecc_error; 38 | wire [23:0] ecc_ph; 39 | wire ph_finder_reset; 40 | 41 | assign ph_finder_reset = reset | (~in_stream_valid); 42 | 43 | // Packet Finder 44 | ph_finder phf( 45 | .rxbyteclkhs(rxbyteclkhs), 46 | .reset(ph_finder_reset), 47 | .din(in_stream), 48 | .din_valid(in_stream_valid), 49 | .dout(ph_finder_out), 50 | .dout_valid(ph_finder_valid), 51 | .ph_select(ph_finder_ph_select) 52 | ); 53 | 54 | // ECC block 55 | ecc_block eccb(.PH_in(ph_finder_out), .PH_out(ecc_ph), .error(ecc_error)); 56 | 57 | // Packet Handler FSM 58 | pckthandler_fsm fsm( 59 | .rxbyteclkhs(rxbyteclkhs), 60 | .reset(reset), 61 | .data_stream(ph_finder_out[31:16]), 62 | .ph_stream(ecc_ph), 63 | .ph_select(ph_finder_ph_select), 64 | .valid_stream(ph_finder_valid), 65 | .ecc_error(ecc_error), 66 | .out_stream(out_stream), 67 | .frame_active(frame_active), 68 | .frame_valid(frame_valid), 69 | .lines_per_frame(lines_per_frame), 70 | .last_packet(last_packet) 71 | ); 72 | endmodule -------------------------------------------------------------------------------- /hdl/pckthandler_fsm.v: -------------------------------------------------------------------------------- 1 | /* Packet Handler FSM: this module represents the core logic of the packet handler FSM 2 | * Gedeon Nyengele 3 | * 08 January 2018 4 | */ 5 | 6 | /* 7 | * @param rxbyteclkhs the byte clock to synchronize to (input) 8 | * @param reset an acitve-high synchronous reset signal (input) 9 | * @param data_stream csi payload stream 10 | * @param ph_stream packet header data (WC_MSB, WC_LSB, DATA_ID) 11 | * @param ph_select defines whether to select the ph_stream or not 12 | * @param valid_stream determines if either stream is valid 13 | * @param ecc_error determines if the PH has an error 14 | * @param out_stream csi payload stream to next module 15 | * @param frame_active determines if we're either about to/in the middle TX'ing a frame 16 | * @param frame_valid signals that a frame output is in progress 17 | * @param lines_per_frame is the number of image lines per frame 18 | * @param last_packet indicates whether the packet on out_stream is the last packet for the frame 19 | */ 20 | module pckthandler_fsm(rxbyteclkhs, reset, data_stream, ph_stream, ph_select, valid_stream, ecc_error, 21 | out_stream, frame_active, frame_valid, lines_per_frame, last_packet 22 | ); 23 | 24 | /* parameters */ 25 | parameter DATA_STREAM_WIDTH = 16; 26 | parameter PH_STREAM_WIDTH = 24; 27 | 28 | /* inputs */ 29 | input rxbyteclkhs, reset, ph_select, valid_stream, ecc_error; 30 | input [(DATA_STREAM_WIDTH-1):0] data_stream; 31 | input [(PH_STREAM_WIDTH-1):0] ph_stream; 32 | input [31:0] lines_per_frame; 33 | 34 | /* outputs */ 35 | output frame_active, frame_valid; 36 | output [(DATA_STREAM_WIDTH-1):0] out_stream; 37 | output last_packet; 38 | 39 | /* internal decl */ 40 | reg frame_active, frame_valid; 41 | reg [(DATA_STREAM_WIDTH-1):0] out_stream; 42 | 43 | wire sof_id, eof_id, pxdata_id; 44 | assign sof_id = (ph_stream[5:0] == 6'h00) ? 1'b1 : 1'b0; 45 | assign eof_id = (ph_stream[5:0] == 6'h01) ? 1'b1 : 1'b0; 46 | assign pxdata_id = (ph_stream[5:0] == 6'h2B) ? 1'b1 : 1'b0; // 2B = RAW10 47 | 48 | reg [1:0] state; 49 | reg [15:0] packet_size, byte_count; 50 | reg [31:0] line_count; 51 | reg last_line, last_out; 52 | 53 | parameter PH_DECODE = 2'b00; 54 | parameter WAIT_EOT = 2'b01; 55 | parameter REC_DATA = 2'b10; 56 | 57 | assign last_packet = last_out; 58 | 59 | always @(posedge rxbyteclkhs) begin 60 | if(reset) begin 61 | frame_active <= 0; 62 | frame_valid <= 0; 63 | packet_size <= 0; 64 | byte_count <= 0; 65 | out_stream <= 0; 66 | line_count <= 0; 67 | last_line <= 0; 68 | last_out <= 0; 69 | state <= PH_DECODE; 70 | end 71 | else begin 72 | case(state) 73 | PH_DECODE: begin 74 | if(valid_stream && ph_select && ~ecc_error) begin 75 | if(sof_id) begin 76 | frame_active <= 1'b1; 77 | line_count <= 0; 78 | last_line <= 0; 79 | last_out <= 0; 80 | state <= PH_DECODE; 81 | end 82 | else if(eof_id) begin 83 | frame_active <= 1'b0; 84 | line_count <= 0; 85 | last_line <= 0; 86 | last_out <= 0; 87 | state <= PH_DECODE; 88 | end 89 | else if(pxdata_id) begin 90 | if(frame_active) begin 91 | byte_count <= 0; 92 | packet_size <= ph_stream[23:8]; 93 | line_count <= line_count + 1; 94 | if((line_count + 1) == lines_per_frame) last_line <= 1'b1; 95 | else last_line <= 1'b0; 96 | state <= REC_DATA; 97 | end 98 | else state <= WAIT_EOT; 99 | end 100 | end 101 | else if(valid_stream && ~ph_select) state <= WAIT_EOT; 102 | else state <= PH_DECODE; 103 | end 104 | WAIT_EOT: begin 105 | if(valid_stream) state <= WAIT_EOT; 106 | else state <= PH_DECODE; 107 | end 108 | REC_DATA: begin 109 | if(byte_count < packet_size) begin 110 | frame_valid <= 1'b1; 111 | out_stream <= data_stream; 112 | byte_count <= byte_count + 2; 113 | state <= REC_DATA; 114 | if(((byte_count + 2) >= packet_size) && last_line) last_out <= 1'b1; 115 | else last_out <= 1'b0; 116 | end 117 | else begin 118 | frame_valid <= 1'b0; 119 | out_stream <= 0; 120 | last_out <= 0; 121 | state <= WAIT_EOT; 122 | end 123 | end 124 | endcase 125 | end 126 | end 127 | 128 | endmodule -------------------------------------------------------------------------------- /hdl/ph_finder.v: -------------------------------------------------------------------------------- 1 | /* Packet Header Finder: this module searches for the packet header in a stream of data 2 | * Gedeon Nyengele 3 | * 08 January 2018 4 | */ 5 | 6 | /* 7 | * @param rxbyteclkhs the byte clock to synchrnize to (input) 8 | * @param reset an active-high synchronous reset signal (input) 9 | * @param din 16-bit word input. MSB = lane1_byte, LSB = lane2_byte (input) 10 | * @param din_valid defines if word_in is valid (input) 11 | * @param dout 32-bit output containing either the packet header or forwarded data stream (output) 12 | * PH is formatted as [ECC, WC_MSB, WC_LSB, DATA_ID] 13 | * forwarded data stream format: MSB = lane1_byte, LSB = lane2_byte 14 | * @param dout_valid defines if dout is valid (output) 15 | * @param ph_select defines whether 'dout' contains the PH or not 16 | */ 17 | 18 | module ph_finder(rxbyteclkhs, reset, din, din_valid, dout, dout_valid, ph_select); 19 | 20 | /* inputs */ 21 | input wire rxbyteclkhs, reset; 22 | input wire [15:0] din; // { lane0[7:0], lane1[7:0] } 23 | input wire din_valid; 24 | 25 | /* outputs */ 26 | output reg [31:0] dout; 27 | output reg dout_valid; 28 | output reg ph_select; 29 | 30 | /* internal decl */ 31 | parameter STATE_HALF_PH = 2'b00; 32 | parameter STATE_FULL_PH = 2'b01; 33 | parameter STATE_BYPASS = 2'b10; 34 | 35 | reg [7:0] prev_byte1, prev_byte2; 36 | reg [1:0] state; 37 | 38 | /* state machine */ 39 | always @(posedge rxbyteclkhs) begin 40 | if(reset | ~din_valid) begin 41 | dout <= 32'd0; 42 | dout_valid <= 1'b0; 43 | ph_select <= 1'b0; 44 | prev_byte1 <= 8'd0; 45 | prev_byte2 <= 8'd0; 46 | state <= STATE_HALF_PH; 47 | end 48 | else begin 49 | case(state) 50 | STATE_HALF_PH: begin 51 | prev_byte1 <= din[15:8]; 52 | prev_byte2 <= din[7:0]; 53 | state <= STATE_FULL_PH; 54 | end 55 | 56 | STATE_FULL_PH: begin 57 | dout <= {din[7:0], din[15:8], prev_byte2, prev_byte1}; 58 | dout_valid <= 1'b1; 59 | ph_select <= 1'b1; 60 | state <= STATE_BYPASS; 61 | end 62 | 63 | STATE_BYPASS: begin 64 | dout <= {din, 16'd0}; 65 | ph_select <= 1'b0; 66 | state <= STATE_BYPASS; 67 | end 68 | 69 | default: begin 70 | dout <= 32'd0; 71 | dout_valid <= 1'b0; 72 | ph_select <= 1'b0; 73 | end 74 | endcase 75 | end 76 | end 77 | endmodule 78 | -------------------------------------------------------------------------------- /hdl/raw10_decoder.v: -------------------------------------------------------------------------------- 1 | /* RAW10 data decoder 2 | * Gedeon Nyengele 3 | * 22 January 2018 4 | */ 5 | 6 | /* 7 | * @param rxbyteclkhs byte clock to synchronize to 8 | * @param reset an active-high reset line 9 | * @param data_in 16-bit input data (byte1, byte2) 10 | * @param data_out 64-bit (4pixels: [pixel4, pixel3, pixel2, pixel1]) 11 | * @param out_valid 1-bit output to indicate whether the 64-bit output is valid or not 12 | * @param last_packet_in input signal to indicate if data_in contains the last packet for the frame 13 | * @param last_packet_out output signal to indicate that data_out contains the last packet for the frame 14 | */ 15 | 16 | module raw10_decoder(rxbyteclkhs, reset, data_in, frame_active, frame_valid, data_out, out_valid, last_packet_in, last_packet_out); 17 | 18 | // parameters 19 | parameter IN_DATA_WIDTH = 16; 20 | parameter OUT_DATA_WIDTH = 64; 21 | 22 | // inputs 23 | input wire rxbyteclkhs, reset, frame_active, frame_valid; 24 | input [(IN_DATA_WIDTH-1):0] data_in; 25 | input last_packet_in; 26 | 27 | // outputs 28 | output out_valid; 29 | output [(OUT_DATA_WIDTH-1):0] data_out; 30 | output reg last_packet_out; 31 | 32 | // internal decls 33 | reg out_valid; 34 | reg [(OUT_DATA_WIDTH-1):0] data_out; 35 | 36 | reg [7:0] buff[3:0]; 37 | reg [2:0] state; 38 | 39 | wire valid = frame_active & frame_valid; 40 | 41 | always @(posedge rxbyteclkhs) begin 42 | if(reset | ~valid) last_packet_out <= 0; 43 | else last_packet_out <= last_packet_in; 44 | end 45 | 46 | always @(posedge rxbyteclkhs) begin 47 | if(reset | ~valid) begin 48 | out_valid <= 0; 49 | data_out <= 0; 50 | state <= 3'b000; 51 | end 52 | else begin 53 | case(state) 54 | 3'b000: begin 55 | data_out <= 0; 56 | out_valid <= 0; 57 | buff[0] <= data_in[15:8]; 58 | buff[1] <= data_in[7:0]; 59 | state <= 3'b001; 60 | end 61 | 3'b001: begin 62 | buff[2] <= data_in[15:8]; 63 | buff[3] <= data_in[7:0]; 64 | state <= 3'b010; 65 | end 66 | 3'b010: begin 67 | data_out <= { 6'd0, buff[3], data_in[15:14], // 4th pixel data (16 bits) 68 | 6'd0, buff[2], data_in[13:12], // 3rd pixel data (16 bits) 69 | 6'd0, buff[1], data_in[11:10], // 2nd pixel data (16 bits) 70 | 6'd0, buff[0], data_in[9:8] // 1st pixel data (16 bits) 71 | }; 72 | out_valid <= 1'b1; 73 | buff[0] <= data_in[7:0]; 74 | state <= 3'b011; 75 | end 76 | 3'b011: begin 77 | data_out <= 0; 78 | out_valid <= 0; 79 | buff[1] <= data_in[15:8]; 80 | buff[2] <= data_in[7:0]; 81 | state <= 3'b100; 82 | end 83 | 3'b100: begin 84 | data_out <= { 6'd0, data_in[15:8], data_in[7:6], // 4th pixel data (16 bits) 85 | 6'd0, buff[2], data_in[5:4], // 3rd pixel data (16 bits) 86 | 6'd0, buff[1], data_in[3:2], // 2nd pixel data (16 bits) 87 | 6'd0, buff[0], data_in[1:0] // 1st pixel data (16 bits) 88 | }; 89 | out_valid <= 1'b1; 90 | state <= 3'b000; 91 | end 92 | endcase 93 | end 94 | end 95 | endmodule -------------------------------------------------------------------------------- /hdl/wordalign.v: -------------------------------------------------------------------------------- 1 | /* Align two data channels based on their sync signals, so that each 16-bit 2 | * output word has a corresponding byte from each channel, and the whole word 3 | * becomes valid/invalid at the same time. 4 | * 5 | * This is loosely based on David Shah's work: 6 | * https://github.com/daveshah1/CSI2Rx/blob/master/mipi-csi-rx/csi_rx_word_align.vhd 7 | * 8 | * Steven Bell 9 | * 2 January 2018 10 | */ 11 | 12 | module wordalign # ( 13 | parameter integer MAX_CHANNEL_DELAY = 2 14 | ) 15 | ( 16 | input wire clk, 17 | input wire resetn, 18 | // We just use the valid line to generate the sync 19 | input wire dl0_rxvalidhs, // Lane 0 valid 20 | input wire dl1_rxvalidhs, // Lane 1 valid 21 | input wire [7:0] dl0_rxdatahs, // Lane 0 data 22 | input wire [7:0] dl1_rxdatahs, // Lane 1 data 23 | output wire [15:0] word_out, // { lane 0[7:0], lane 1[7:0] } 24 | output reg word_valid 25 | ); 26 | 27 | // Delayed copies of the input word, which is the concatenation of the input bytes 28 | reg[15:0] word_delay[MAX_CHANNEL_DELAY+1:0]; 29 | // Delayed copies of the sync lines, which form a set of one-hot delay counters 30 | reg[1:0] sync_delay[MAX_CHANNEL_DELAY+1:0]; 31 | // Delayed copies of the valid bits, so the output invalidation is synced 32 | reg[1:0] valid_delay[MAX_CHANNEL_DELAY+1:0]; 33 | 34 | wire locked; // Whether we have aquired a sync pulse from all channels 35 | reg[7:0] byte_lane0; 36 | reg[7:0] byte_lane1; 37 | 38 | integer i; // Loop counter 39 | 40 | always @(posedge clk) begin 41 | if(~resetn) begin 42 | byte_lane0 <= 0; 43 | byte_lane1 <= 0; 44 | for(i = 0; i <= MAX_CHANNEL_DELAY; i = i+1) begin 45 | word_delay[i] <= 0; 46 | sync_delay[i] <= 2'b00; 47 | valid_delay[i] <= 2'b00; 48 | end 49 | word_valid <= 1'b0; 50 | end 51 | else begin 52 | // Push the incoming data and valid bits down the chain 53 | word_delay[0] <= {dl0_rxdatahs, dl1_rxdatahs}; 54 | word_delay[1] <= word_delay[0]; 55 | word_delay[2] <= word_delay[1]; 56 | 57 | valid_delay[0] <= {dl0_rxvalidhs, dl1_rxvalidhs}; 58 | valid_delay[1] <= valid_delay[0]; 59 | valid_delay[2] <= valid_delay[1]; 60 | 61 | // If we haven't yet gotten a sync from all the channels, 62 | // then keep pushing them back. 63 | // Once we have a sync from each channel, the position of those bits 64 | // represents the delay that we need to apply to each data stream. 65 | if(~locked) begin 66 | sync_delay[0] <= {dl0_rxvalidhs != valid_delay[0][1], 67 | dl1_rxvalidhs != valid_delay[0][0]}; 68 | sync_delay[1] <= sync_delay[0]; 69 | sync_delay[2] <= sync_delay[1]; 70 | end 71 | 72 | // Output is valid one cycle after locking 73 | word_valid <= locked; 74 | 75 | // Select the appropriate bytes from the delay chain based on the sync delays 76 | if(sync_delay[0][1]) 77 | byte_lane0 <= word_delay[0][15:8]; 78 | else if(sync_delay[1][1]) 79 | byte_lane0 <= word_delay[1][15:8]; 80 | else if(sync_delay[2][1]) 81 | byte_lane0 <= word_delay[2][15:8]; 82 | else 83 | byte_lane0 <= 0; 84 | 85 | if(sync_delay[0][0]) 86 | byte_lane1 <= word_delay[0][7:0]; 87 | else if(sync_delay[1][0]) 88 | byte_lane1 <= word_delay[1][7:0]; 89 | else if(sync_delay[2][0]) 90 | byte_lane1 <= word_delay[2][7:0]; 91 | else 92 | byte_lane1 <= 0; 93 | end // else (~reset) 94 | end 95 | 96 | // We're locked (i.e., have a valid set of delays in sync_delay) if each 97 | // lane has a sync pulse, and the corresponding valid bit is set (to handle desync) 98 | // This is a continuous assignment since we need to stop the sync on the next cycle 99 | assign locked = ((sync_delay[0][0] & valid_delay[0][0]) | 100 | (sync_delay[1][0] & valid_delay[1][0]) | 101 | (sync_delay[2][0] & valid_delay[2][0])) & 102 | ((sync_delay[0][1] & valid_delay[0][1]) | 103 | (sync_delay[1][1] & valid_delay[1][1]) | 104 | (sync_delay[2][1] & valid_delay[2][1])); 105 | 106 | assign word_out = {byte_lane0, byte_lane1}; 107 | 108 | endmodule 109 | 110 | -------------------------------------------------------------------------------- /unit_tests/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT ?= testbench 2 | ROOT = ../ 3 | FLAGS = -g2005 -y $(ROOT) 4 | 5 | pckthandler: pckthandler_tb.v 6 | iverilog $(FLAGS) $^ -o $(OUTPUT) 7 | 8 | pckthandler2: pckthandler_tb2.v 9 | iverilog $(FLAGS) $^ -o $(OUTPUT) 10 | 11 | pckthandler_fsm: pckthandler_fsm_tb.v 12 | iverilog $(FLAGS) $^ -o $(OUTPUT) 13 | 14 | ph_finder: ph_finder_tb.v 15 | iverilog $(FLAGS) $^ -o $(OUTPUT) 16 | 17 | ecc_block: ecc_block_tb.v 18 | iverilog $(FLAGS) $^ -o $(OUTPUT) 19 | 20 | raw10_decoder: raw10_decoder_tb.v 21 | iverilog $(FLAGS) $^ -o $(OUTPUT) 22 | 23 | .PHONY: run, clean 24 | run: $(OUTPUT) 25 | vvp $(OUTPUT) 26 | clean: 27 | rm -rf $(OUTPUT) -------------------------------------------------------------------------------- /unit_tests/csirx_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module csirx_tb # 4 | ( 5 | parameter integer N_DATA_LANES = 2 6 | ) 7 | (); 8 | 9 | reg clk; 10 | reg resetn; 11 | 12 | // PPI input simulating Xilinx D-PHY core 13 | reg cl_stopstate; 14 | reg dl0_rxactivehs; // Whether high-speed receive is in progress 15 | reg dl1_rxactivehs; 16 | reg dl0_rxsynchs; // Pulse at the beginning of high-speed transmission 17 | reg dl1_rxsynchs; 18 | wire cl_enable; // Clock enable 19 | wire dl0_enable; // Data lane 0 enable 20 | wire dl1_enable; // Data lane 1 enables 21 | wire dl0_forcerxmode; 22 | wire dl1_forcerxmode; 23 | reg dl0_rxvalidhs; // Lane 0 valid 24 | reg dl1_rxvalidhs; // Lane 1 valid 25 | reg [7:0] dl0_rxdatahs; // Lane 0 data 26 | reg [7:0] dl1_rxdatahs; // Lane 1 data 27 | 28 | // AXI-stream master output 29 | wire m_axis_tvalid; 30 | wire [(N_DATA_LANES*8)-1 : 0] m_axis_tdata; 31 | wire [N_DATA_LANES-1 : 0] m_axis_tstrb; 32 | wire m_axis_tlast; 33 | reg m_axis_tready; 34 | 35 | // Simulation control variables 36 | integer d0_start; 37 | integer d1_start; 38 | integer datalen; 39 | integer n_cycles; 40 | 41 | // Simulation control 42 | initial begin 43 | $display("Starting the test..."); 44 | $dumpfile("csirx_test.vcd"); 45 | $dumpvars; // Dump everything 46 | #500 $finish; // End after N ticks 47 | end 48 | 49 | // Initialization 50 | initial begin 51 | clk = 1'b0; 52 | resetn = 1'b1; 53 | 54 | d0_start = 4; 55 | d1_start = 2; 56 | datalen = 16; 57 | n_cycles = 0; 58 | end 59 | 60 | // Reset signal 61 | initial begin 62 | #5 63 | resetn = 1'b0; 64 | #10 65 | resetn = 1'b1; 66 | end 67 | 68 | 69 | always begin 70 | #10 71 | 72 | clk = 1'b1; 73 | 74 | // Sync pulse once at the start 75 | dl0_rxsynchs = (n_cycles == d0_start-1); 76 | dl1_rxsynchs = (n_cycles == d1_start-1); 77 | 78 | // If the start time has passed, then set the data valid bit 79 | // and set the data to a counting value 80 | if(n_cycles >= d0_start && n_cycles < d0_start + datalen) begin 81 | dl0_rxdatahs = n_cycles - d0_start; 82 | dl0_rxvalidhs = 1'b1; 83 | end 84 | else begin 85 | dl0_rxdatahs = 8'hxx; 86 | dl0_rxvalidhs = 1'b0; 87 | end 88 | 89 | if(n_cycles >= d1_start && n_cycles < d1_start + datalen) begin 90 | dl1_rxdatahs = n_cycles - d1_start + 8'h10; 91 | dl1_rxvalidhs = 1'b1; 92 | end 93 | else begin 94 | dl1_rxdatahs = 8'hxx; 95 | dl1_rxvalidhs = 1'b0; 96 | end 97 | 98 | 99 | #10 100 | clk = 1'b0; 101 | 102 | n_cycles += 1; 103 | end 104 | 105 | // DUT 106 | csirx csirx_dut( 107 | .cl_stopstate(cl_stopstate), 108 | .dl0_rxactivehs(dl0_rxactivehs), 109 | .dl1_rxactivehs(dl1_rxactivehs), 110 | .dl0_rxsynchs(dl0_rxsynchs), 111 | .dl1_rxsynchs(dl1_rxsynchs), 112 | .cl_enable(cl_enable), 113 | .dl0_enable(dl0_enable), 114 | .dl1_enable(dl1_enable), 115 | .dl0_forcerxmode(dl0_forcerxmode), 116 | .dl1_forcerxmode(dl1_forcerxmode), 117 | .dl0_rxvalidhs(dl0_rxvalidhs), 118 | .dl1_rxvalidhs(dl1_rxvalidhs), 119 | .dl0_rxdatahs(dl0_rxdatahs), 120 | .dl1_rxdatahs(dl1_rxdatahs), 121 | .rxbyteclkhs(clk), 122 | .rxbyteclkhs_resetn(resetn), 123 | .m_axis_tvalid(m_axis_tvalid), 124 | .m_axis_tdata(m_axis_tdata), 125 | .m_axis_tstrb(m_axis_tstrb), 126 | .m_axis_tlast(m_axis_tlast), 127 | .m_axis_tready(m_axis_tready) 128 | ); 129 | 130 | endmodule 131 | 132 | -------------------------------------------------------------------------------- /unit_tests/ecc_block_tb.v: -------------------------------------------------------------------------------- 1 | module ecc_block_tb; 2 | reg [31:0] PH_in; 3 | 4 | wire [23:0] PH_out; 5 | wire no_error, corrected_error, error; 6 | 7 | reg [23:0] PH_out_exp; 8 | reg error_exp; 9 | 10 | reg clk; 11 | integer fd, status; 12 | 13 | ecc_block DUT(PH_in, PH_out, no_error, corrected_error, error); 14 | 15 | // clock 16 | initial clk = 0; 17 | always #10 clk=~clk; 18 | 19 | // files 20 | initial fd = $fopen("ecc_block_testvec.txt", "r"); 21 | 22 | // data provider 23 | initial begin 24 | PH_in = 0; 25 | //@(posedge clk); 26 | while(!$feof(fd)) begin 27 | @(posedge clk); 28 | #1 status = $fscanf(fd, "%h, %h, %h\n",PH_in, PH_out_exp, error_exp); 29 | #4 $display("PH_in=%h, PH_out=%h, PH_out_exp=%h, error=%b, error_exp=%b", PH_in, PH_out, PH_out_exp, error, error_exp); 30 | end 31 | @(posedge clk); 32 | $fclose(fd); 33 | $finish; 34 | end 35 | 36 | endmodule -------------------------------------------------------------------------------- /unit_tests/ecc_block_testvec.txt: -------------------------------------------------------------------------------- 1 | 0x3400042b, 0x00042b, 0x0 2 | 0x3400042a, 0x00042b, 0x0 3 | 0x3400042c, 0x00042c, 0x1 4 | 0x3400142b, 0x00042b, 0x0 5 | 0x3410042b, 0x00042b, 0x0 6 | 0x3401043b, 0x01043b, 0x1 -------------------------------------------------------------------------------- /unit_tests/image4.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevenbell/csirx/2c37eb0e8ec25d011185fbc1c5a678123e198c7f/unit_tests/image4.bin -------------------------------------------------------------------------------- /unit_tests/image4_out.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevenbell/csirx/2c37eb0e8ec25d011185fbc1c5a678123e198c7f/unit_tests/image4_out.bin -------------------------------------------------------------------------------- /unit_tests/pckthandler_fsm_tb.v: -------------------------------------------------------------------------------- 1 | module pckthandler_fsm_tb; 2 | reg clk, reset; 3 | reg [15:0] data_stream; 4 | reg [23:0] ph_stream; 5 | reg ph_select, valid_stream, ecc_error; 6 | 7 | wire [15:0] out_stream; 8 | wire frame_active, frame_valid; 9 | 10 | integer fd, status; 11 | 12 | reg [15:0] out_exp; 13 | reg fr_active_exp, fr_valid_exp; 14 | 15 | pckthandler_fsm DUT(clk, reset, data_stream, ph_stream, ph_select, valid_stream, 16 | ecc_error, out_stream, frame_active, frame_valid); 17 | 18 | // clock & reset 19 | initial begin 20 | clk = 0; reset =1; 21 | repeat(4) #10 clk=~clk; 22 | reset = 0; 23 | forever #10 clk=~clk; 24 | end 25 | 26 | // test vector files 27 | initial begin 28 | fd = $fopen("pckthandler_fsm_testvec.txt", "r"); 29 | end 30 | 31 | // data provider 32 | initial begin 33 | data_stream = 0; ph_stream= 0; ph_select = 0; valid_stream=0; ecc_error=0; 34 | @(negedge reset); 35 | while(!$feof(fd)) begin 36 | status = $fscanf(fd, "%h, %h, %h, %h, %h, %h, %h\n", data_stream, ph_stream, valid_stream, ph_select, 37 | out_exp, fr_active_exp, fr_valid_exp); 38 | @(posedge clk); 39 | #1 $display("out=%h, out_exp=%h, fr_active=%h, fr_active_exp=%h, fr_valid=%h, fr_valid_exp=%h", 40 | out_stream, out_exp, frame_active, fr_active_exp, frame_valid, fr_valid_exp); 41 | end 42 | repeat(20) @(posedge clk); 43 | $fclose(fd); 44 | $finish; 45 | end 46 | endmodule -------------------------------------------------------------------------------- /unit_tests/pckthandler_fsm_testvec.txt: -------------------------------------------------------------------------------- 1 | 0x0000, 0x000000, 0x1, 0x1, 0x0000, 0x1, 0x0 2 | 0x0000, 0x000412, 0x1, 0x1, 0x0000, 0x1, 0x0 3 | 0xeeff, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 4 | 0xffee, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 5 | 0xeeff, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 6 | 0xffee, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 7 | 0x0000, 0x000000, 0x0, 0x0, 0x0000, 0x1, 0x0 8 | 0x0000, 0x000412, 0x1, 0x1, 0x0000, 0x1, 0x0 9 | 0xeeff, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 10 | 0xffee, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 11 | 0xeeff, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 12 | 0xffee, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 13 | 0x0000, 0x000000, 0x0, 0x0, 0x0000, 0x1, 0x0 14 | 0x0000, 0x00062b, 0x1, 0x1, 0x0000, 0x1, 0x0 15 | 0x1122, 0x000000, 0x1, 0x0, 0x1122, 0x1, 0x1 16 | 0x3344, 0x000000, 0x1, 0x0, 0x3344, 0x1, 0x1 17 | 0x5566, 0x000000, 0x1, 0x0, 0x5566, 0x1, 0x1 18 | 0x1122, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 19 | 0x1342, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 20 | 0x1562, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 21 | 0x0000, 0x000000, 0x0, 0x0, 0x0000, 0x1, 0x0 22 | 0x0000, 0x00062b, 0x1, 0x1, 0x0000, 0x1, 0x0 23 | 0x1122, 0x000000, 0x1, 0x0, 0x1122, 0x1, 0x1 24 | 0x3344, 0x000000, 0x1, 0x0, 0x3344, 0x1, 0x1 25 | 0x5566, 0x000000, 0x1, 0x0, 0x5566, 0x1, 0x1 26 | 0x1122, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 27 | 0x1342, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 28 | 0x1562, 0x000000, 0x1, 0x0, 0x0000, 0x1, 0x0 29 | 0x0000, 0x000000, 0x0, 0x0, 0x0000, 0x1, 0x0 30 | 0x0000, 0x000001, 0x1, 0x1, 0x0000, 0x0, 0x0 -------------------------------------------------------------------------------- /unit_tests/pckthandler_tb.v: -------------------------------------------------------------------------------- 1 | /* Vector-based testbench for pckthandler.v 2 | * The first part of the test uses a set of test vectors in the text file 3 | * pckthandler_testvec.txt, and exercises all the basic functionality. 4 | * See also pckthandler_tb2.v 5 | * 6 | * Gedeon Nyengele 7 | * January 2018 8 | */ 9 | 10 | module pckthandler_tb; 11 | reg clk, reset, din_valid; 12 | reg [15:0] din; 13 | wire dout_valid, fr_active, fr_valid; 14 | wire [15:0] dout; 15 | 16 | reg [15:0] dout_exp; 17 | reg fr_valid_exp, fr_active_exp; 18 | integer fd, status; 19 | reg [128*8-1:0] vecstr; 20 | 21 | pckthandler DUT(clk, reset, din, din_valid, dout, fr_active, fr_valid); 22 | 23 | // clock & reset 24 | initial begin 25 | clk = 0; reset = 1; 26 | repeat(4) #10 clk = ~clk; 27 | reset = 0; 28 | forever #10 clk = ~clk; 29 | end 30 | 31 | // files 32 | initial begin 33 | fd = $fopen("pckthandler_testvec.txt", "r"); 34 | end 35 | 36 | // data provider 37 | initial begin 38 | din = 0; din_valid = 0; 39 | @(negedge reset); 40 | while(!$feof(fd)) begin 41 | status = $fgets(vecstr, fd); 42 | if($sscanf(vecstr, "%h, %h, %h, %h, %h\n", din, din_valid, dout_exp, fr_active_exp, fr_valid_exp) == 5) begin 43 | @(posedge clk); 44 | #1 $display("din=%h, din_valid=%h, dout=%h, dout_exp=%h, fr_active=%h, fr_active_exp=%h, fr_valid=%h, fr_valid_exp=%h", 45 | din, din_valid, dout, dout_exp, fr_active, fr_active_exp, fr_valid, fr_valid_exp); 46 | end 47 | 48 | end 49 | repeat(25) @(posedge clk); 50 | $fclose(fd); 51 | $finish; 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /unit_tests/pckthandler_tb2.v: -------------------------------------------------------------------------------- 1 | /* Data-based testbench for pckthandler.v 2 | * This test pushes part of a real data dump from the byte aligner through. 3 | * We have to manually confirm that the output appears in whole frames and that 4 | * the header/footer is stripped off correctly. 5 | * 6 | * Steven Bell 7 | * 22 January 2018 8 | */ 9 | 10 | module pckthandler_tb2; 11 | 12 | reg clk, reset, din_valid; 13 | reg [7:0] char_in; // Used to get data byte-by-byte 14 | reg [15:0] din; 15 | wire dout_valid, fr_active, fr_valid; 16 | wire [15:0] dout; 17 | 18 | reg [15:0] dout_exp; 19 | reg fr_valid_exp, fr_active_exp; 20 | integer infile, outfile, count, stat; 21 | 22 | pckthandler DUT(clk, reset, din, din_valid, dout, fr_active, fr_valid); 23 | 24 | // clock & reset 25 | initial begin 26 | clk = 0; reset = 1; 27 | repeat(4) #10 clk = ~clk; 28 | reset = 0; 29 | forever #10 clk = ~clk; 30 | end 31 | 32 | // files 33 | initial begin 34 | infile = $fopen("image4.bin", "r"); 35 | outfile = $fopen("image4_out.bin", "w"); 36 | end 37 | 38 | 39 | // data provider 40 | initial begin 41 | din = 0; din_valid = 0; 42 | count = 0; 43 | @(negedge reset); // Wait until (active-high) reset goes low 44 | 45 | while(!$feof(infile)) begin 46 | stat = $fread(char_in, infile); // Read the first input byte 47 | din[15:8] = char_in; 48 | stat = $fread(char_in, infile); // Read the second byte 49 | din[7:0] = char_in; 50 | 51 | din_valid = 1; // Always valid 52 | 53 | // Wait for the next cycle 54 | @(posedge clk); 55 | #1 56 | 57 | // Write the output bits if they are valid 58 | if(dout_valid) begin 59 | $fwrite(outfile, "%s", dout); 60 | end 61 | 62 | // Print some progress 63 | if(count % 16'h1000 == 0) begin 64 | $display("count: %x din: %x fr_active: %d, fr_valid: %d, dout_valid: %d", 65 | count, din, fr_active, fr_valid, dout_valid); 66 | end 67 | count = count+1; 68 | end 69 | $fclose(infile); 70 | $fclose(outfile); 71 | $finish; 72 | end 73 | endmodule -------------------------------------------------------------------------------- /unit_tests/pckthandler_testvec.txt: -------------------------------------------------------------------------------- 1 | # send SOF short packet 2 | 0x0000, 0x1, 0x0000, 0x0, 0x0 3 | 0x0000, 0x1, 0x0000, 0x0, 0x0 4 | 5 | # end of packet 6 | 0x0000, 0x0, 0x0000, 0x1, 0x0 7 | 8 | # send a 4-byte pixel data packet 9 | # with additional trailing bytes 10 | 0x2b04, 0x1, 0x0000, 0x1, 0x0 11 | 0x0034, 0x1, 0x0000, 0x1, 0x0 12 | 0x1122, 0x1, 0x0000, 0x1, 0x0 13 | 0x3344, 0x1, 0x1122, 0x1, 0x1 14 | 0x5566, 0x1, 0x3344, 0x1, 0x1 15 | 0x7788, 0x1, 0x0000, 0x1, 0x0 16 | 0x99aa, 0x1, 0x0000, 0x1, 0x0 17 | 18 | # end of packet 19 | 0x0000, 0x0, 0x0000, 0x1, 0x0 20 | 21 | # send an EoF short packet 22 | 0x0100, 0x1, 0x0000, 0x1, 0x0 23 | 0x0007, 0x1, 0x0000, 0x1, 0x0 24 | 25 | # end of packet 26 | 0x0000, 0x0, 0x0000, 0x0, 0x0 -------------------------------------------------------------------------------- /unit_tests/ph_finder_tb.v: -------------------------------------------------------------------------------- 1 | /* testbench for ph_finder module 2 | * Gedeon Nyengele 3 | * Jan 12 2018 4 | */ 5 | 6 | module ph_finder_tb; 7 | reg clk, reset, din_valid; 8 | reg [15:0] din; 9 | wire [31:0] dout; 10 | wire dout_valid, ph_select; 11 | 12 | integer fd, status; 13 | reg [31:0] d_exp; 14 | reg v_exp, ph_exp; 15 | 16 | ph_finder DUT(clk, reset, din, din_valid, dout, dout_valid, ph_select); 17 | 18 | // clock 19 | initial begin 20 | clk = 0; reset = 1; 21 | repeat(4) #10 clk = ~clk; 22 | reset = 0; 23 | forever #10 clk = ~clk; 24 | end 25 | 26 | // files 27 | initial begin 28 | fd = $fopen("ph_finder_testvec.txt", "r"); 29 | end 30 | 31 | // data provider 32 | initial begin 33 | din = 0; din_valid = 1; 34 | @(negedge reset); 35 | while(!$feof(fd)) begin 36 | status = $fscanf(fd, "%h, %h, %h, %h, %h\n", din, din_valid, d_exp, v_exp, ph_exp); 37 | @(posedge clk); 38 | #1 $display("input=%h, output=%h, output_exp=%h, v=%b, v_exp=%b, ph_sel=%b, ph_sel_exp=%b", 39 | din, dout, d_exp, dout_valid, v_exp, ph_select, ph_exp); 40 | end 41 | @(posedge clk); 42 | $fclose(fd); 43 | $finish; 44 | end 45 | endmodule -------------------------------------------------------------------------------- /unit_tests/ph_finder_testvec.txt: -------------------------------------------------------------------------------- 1 | 0x0102, 0x1, 0x00000000, 0x0, 0x0 2 | 0x0304, 0x1, 0x04030201, 0x1, 0x1 3 | 0x0506, 0x1, 0x05060000, 0x1, 0x0 4 | 0x0708, 0x1, 0x07080000, 0x1, 0x0 5 | 0x090a, 0x1, 0x090a0000, 0x1, 0x0 6 | 0x0b0c, 0x0, 0x00000000, 0x0, 0x0 7 | 0x0d0e, 0x1, 0x00000000, 0x0, 0x0 8 | 0x0f10, 0x1, 0x100f0e0d, 0x1, 0x1 9 | 0x0f20, 0x1, 0x0f200000, 0x1, 0x0 10 | 0x0f30, 0x1, 0x0f300000, 0x1, 0x0 -------------------------------------------------------------------------------- /unit_tests/raw10_decoder_tb.v: -------------------------------------------------------------------------------- 1 | module raw10_decoder_tb; 2 | reg clk, reset, frame_active, frame_valid; 3 | reg [15:0] din; 4 | 5 | wire [63:0] dout; 6 | wire valid; 7 | 8 | reg [63:0] dout_exp; 9 | reg valid_exp; 10 | 11 | integer fd, status; 12 | reg [128*8-1:0] vecstr; // Line of file for input vector 13 | 14 | raw10_decoder DUT(clk, reset, din, frame_active, frame_valid, dout, valid); 15 | 16 | // clock and reset 17 | initial begin 18 | clk = 0; reset = 1; 19 | repeat(4) #10 clk=~clk; 20 | reset = 0; 21 | forever #10 clk=~clk; 22 | end 23 | 24 | // files 25 | initial begin 26 | fd = $fopen("raw10_decoder_testvec.txt", "r"); 27 | end 28 | 29 | 30 | // data provider 31 | initial begin 32 | din = 0; frame_valid = 0; frame_active = 0; 33 | @(negedge reset); 34 | while(!$feof(fd)) begin 35 | status = $fgets(vecstr, fd); 36 | if($sscanf(vecstr, "%h, %h, %h, %h, %h\n", din, frame_active, frame_valid, dout_exp, valid_exp) == 5) begin 37 | @(posedge clk); 38 | #1 $display("din=%h, fr_active=%b, fr_valid=%b, dout=%h, dout_exp=%h, valid=%b, valid_exp=%b", 39 | din, frame_active, frame_valid, dout, dout_exp, valid, valid_exp); 40 | end 41 | end 42 | @(posedge clk); 43 | $fclose(fd); 44 | $finish; 45 | end 46 | endmodule 47 | -------------------------------------------------------------------------------- /unit_tests/raw10_decoder_testvec.txt: -------------------------------------------------------------------------------- 1 | /* RAW10 decoder - Test vectors 2 | * 3 | * Gedeon Nyengele 4 | * Jan 22, 2018 5 | */ 6 | 7 | # test 1: send and receive the following 10-bit raw pixels: 8 | # 0x17B, 0x308, 0x283, 0x2AC 9 | 10 | (data format: din, fr_active, fr_valid, dout_exp, valid_exp) 11 | 0x5EC2, 0x1, 0x1, 0x0000000000000000, 0x0 12 | 0xA0AB, 0x1, 0x1, 0x0000000000000000, 0x0 13 | 0x335E, 0x1, 0x1, 0x02AC02830308017B, 0x1 14 | 0xC2A0, 0x1, 0x1, 0x0000000000000000, 0x0 15 | 0xAB33, 0x1, 0x1, 0x02AC02830308017B, 0x1 16 | 0x6DEC, 0x0, 0x0, 0x0000000000000000, 0x0 17 | 0x5EC2, 0x1, 0x1, 0x0000000000000000, 0x0 18 | 0xA0AB, 0x1, 0x1, 0x0000000000000000, 0x0 19 | 0x335E, 0x1, 0x1, 0x02AC02830308017B, 0x1 20 | 0xC2A0, 0x1, 0x1, 0x0000000000000000, 0x0 21 | 0xAB33, 0x1, 0x1, 0x02AC02830308017B, 0x1 22 | 0x6DEC, 0x0, 0x0, 0x0000000000000000, 0x0 -------------------------------------------------------------------------------- /unit_tests/viewdump.py: -------------------------------------------------------------------------------- 1 | # Decode a binary blob from the camera into something resembling an image 2 | # Steven Bell 3 | # 29 December 2017 4 | 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from IPython import embed 8 | 9 | # Load the data 10 | blob = np.fromfile('image4.bin', dtype=np.uint8) 11 | 12 | # Flip the channels 13 | ch1 = blob[0::2] 14 | ch2 = blob[1::2] 15 | 16 | merged = np.zeros(len(ch1) + len(ch2)) 17 | merged[1::2] = ch1 18 | merged[0::2] = ch2 19 | 20 | #merged = np.delete(merged, np.s_[1::5]) # Throw out the packed low 2 bits 21 | 22 | # This looks like 1640 pixels wide 23 | w = 1040*2; # 832*2; #832*4 # 1040 includes the low-order bits 24 | h = len(merged) / w 25 | 26 | im = merged[0:w*h].reshape(h, w) 27 | 28 | #plt.imshow(im[1000:2000,0:1200]) 29 | plt.imshow(im) 30 | plt.show() 31 | 32 | #embed() 33 | 34 | -------------------------------------------------------------------------------- /xgui/axi_csi_v1_1.tcl: -------------------------------------------------------------------------------- 1 | # Definitional proc to organize widgets for parameters. 2 | proc init_gui { IPINST } { 3 | ipgui::add_param $IPINST -name "Component_Name" 4 | #Adding Page 5 | ipgui::add_page $IPINST -name "Page 0" 6 | 7 | 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /xgui/axi_csi_v1_1_v1_0.tcl: -------------------------------------------------------------------------------- 1 | # Definitional proc to organize widgets for parameters. 2 | proc init_gui { IPINST } { 3 | ipgui::add_param $IPINST -name "Component_Name" 4 | #Adding Page 5 | set Page_0 [ipgui::add_page $IPINST -name "Page 0"] 6 | ipgui::add_param $IPINST -name "C_RegSpace_S_AXI_ADDR_WIDTH" -parent ${Page_0} 7 | ipgui::add_param $IPINST -name "C_RegSpace_S_AXI_DATA_WIDTH" -parent ${Page_0} 8 | ipgui::add_param $IPINST -name "N_DATA_LANES" -parent ${Page_0} 9 | 10 | 11 | } 12 | 13 | proc update_PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH { PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH } { 14 | # Procedure called to update C_RegSpace_S_AXI_ADDR_WIDTH when any of the dependent parameters in the arguments change 15 | } 16 | 17 | proc validate_PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH { PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH } { 18 | # Procedure called to validate C_RegSpace_S_AXI_ADDR_WIDTH 19 | return true 20 | } 21 | 22 | proc update_PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH { PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH } { 23 | # Procedure called to update C_RegSpace_S_AXI_DATA_WIDTH when any of the dependent parameters in the arguments change 24 | } 25 | 26 | proc validate_PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH { PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH } { 27 | # Procedure called to validate C_RegSpace_S_AXI_DATA_WIDTH 28 | return true 29 | } 30 | 31 | proc update_PARAM_VALUE.N_DATA_LANES { PARAM_VALUE.N_DATA_LANES } { 32 | # Procedure called to update N_DATA_LANES when any of the dependent parameters in the arguments change 33 | } 34 | 35 | proc validate_PARAM_VALUE.N_DATA_LANES { PARAM_VALUE.N_DATA_LANES } { 36 | # Procedure called to validate N_DATA_LANES 37 | return true 38 | } 39 | 40 | 41 | proc update_MODELPARAM_VALUE.N_DATA_LANES { MODELPARAM_VALUE.N_DATA_LANES PARAM_VALUE.N_DATA_LANES } { 42 | # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value 43 | set_property value [get_property value ${PARAM_VALUE.N_DATA_LANES}] ${MODELPARAM_VALUE.N_DATA_LANES} 44 | } 45 | 46 | proc update_MODELPARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH { MODELPARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH } { 47 | # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value 48 | set_property value [get_property value ${PARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH}] ${MODELPARAM_VALUE.C_RegSpace_S_AXI_DATA_WIDTH} 49 | } 50 | 51 | proc update_MODELPARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH { MODELPARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH } { 52 | # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value 53 | set_property value [get_property value ${PARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH}] ${MODELPARAM_VALUE.C_RegSpace_S_AXI_ADDR_WIDTH} 54 | } 55 | 56 | --------------------------------------------------------------------------------