├── .gitignore ├── Labs ├── 01. Tcl │ ├── pic │ │ ├── tcl.png │ │ ├── tcl2.png │ │ ├── tcl3.png │ │ ├── tcl4.png │ │ ├── tcl5.png │ │ ├── tcl6.png │ │ └── tcl_add.png │ ├── demoproject │ │ ├── build_project.bat │ │ ├── rtl │ │ │ ├── demo_wrapper_nexys_a7.sv │ │ │ └── demo.sv │ │ └── tb │ │ │ └── tb_demo.sv │ └── README.md ├── 03. DSP │ ├── pic │ │ ├── dsp48.png │ │ ├── mac.drawio.png │ │ ├── simd.drawio.png │ │ ├── pre_adder.drawio.png │ │ ├── mult_compare.drawio.png │ │ ├── mult_simple.drawio.png │ │ └── mult_simple_async.drawio.png │ └── examples │ │ ├── 02_mult_dsp │ │ ├── clk.xdc │ │ ├── mult_dsp_async.sv │ │ ├── mult_dsp.sv │ │ └── mult_dsp_wrapper.sv │ │ ├── 01_mult_no_dsp │ │ ├── clk.xdc │ │ └── mult_no_dsp.sv │ │ ├── 03_pre_adder │ │ └── pre_adder.sv │ │ ├── 05_alu_simd │ │ └── alu_simd.sv │ │ ├── 04_mult_accumulate │ │ └── mult_accumulate.sv │ │ └── 06_pattern_detect │ │ └── mult_compare.sv ├── 09. gcc make │ └── pic │ │ ├── pic1.png │ │ └── pic2.png ├── 02. LUT and FF │ ├── pic │ │ ├── adder.jpg │ │ └── carry4.png │ └── README.md ├── 06.AXI-Stream │ ├── pic │ │ ├── fork_1.png │ │ ├── fork_2.png │ │ ├── join_1.png │ │ ├── join_2.png │ │ ├── join_3.png │ │ ├── join_4.png │ │ ├── rr_arb.png │ │ ├── wave_1.png │ │ ├── wave_2.png │ │ ├── wave_3.png │ │ ├── crossbar_1.png │ │ ├── credit_flow_control.png │ │ └── credit_flow_control_ff.png │ └── examples │ │ ├── credit_counter.sv │ │ ├── skid_buffer.sv │ │ ├── tb │ │ ├── counter_tb.sv │ │ ├── top_credit_pipelined_tb.sv │ │ ├── skid_buffer_tb.sv │ │ └── fifo_ready_valid_tb.sv │ │ ├── top_credit_pipelined.sv │ │ ├── fifo_ready_valid.sv │ │ └── pow5_pipelined_valid.sv ├── 08. APB and CRC │ ├── pic │ │ ├── pic1.png │ │ ├── pic2.png │ │ ├── pic3.png │ │ ├── pic4.png │ │ ├── pic5.png │ │ ├── pic6.png │ │ ├── pic7.png │ │ ├── pic8.png │ │ ├── pic9.png │ │ ├── pic10.png │ │ ├── pic11.png │ │ ├── pic14.png │ │ ├── pic15.png │ │ ├── pic16.png │ │ ├── pic17.png │ │ ├── pic18.png │ │ ├── read_no_wait.png │ │ └── read_with_wait.png │ └── examples │ │ ├── example9.sv │ │ ├── example12.sv │ │ ├── example4.sv │ │ ├── example8.sv │ │ ├── example2.sv │ │ ├── example6.sv │ │ ├── example3.sv │ │ ├── example11.v │ │ ├── example7.sv │ │ ├── example5.sv │ │ ├── example10.sv │ │ ├── wrapper_crc8.sv │ │ └── example1.sv ├── 07. PLL and CDC │ └── pic │ │ ├── pll_vco.png │ │ ├── pll_filter.png │ │ ├── pll_phasedetector.png │ │ ├── graycode_animation.gif │ │ ├── pll_instantiation_1.png │ │ ├── pll_instantiation_2.png │ │ ├── pll_instantiation_3.png │ │ ├── pll_instantiation_4.png │ │ ├── vivado_simulator_settings_1.png │ │ ├── vivado_simulator_settings_2.png │ │ ├── pll_typical_scheme.svg │ │ ├── flag_sync_fail.svg │ │ ├── fifo_normal.svg │ │ ├── ff2_sync.svg │ │ ├── flag_sync_noloop.svg │ │ ├── metastability.svg │ │ ├── fifo_async.svg │ │ ├── graycode_sync.svg │ │ └── flag_sync_loop.svg ├── 05. Pipelines and Systolic arrays │ ├── pic │ │ ├── 1.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ ├── 9.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 15.png │ │ ├── 16.png │ │ ├── 17.png │ │ ├── 18.png │ │ ├── 20.png │ │ ├── comb.gif │ │ ├── sta.png │ │ ├── syst.gif │ │ └── pipeline.gif │ └── examples │ │ ├── 01_pow5_single_cycle │ │ └── pow5_mult_single_cycle.sv │ │ ├── 05_syst_ws │ │ ├── syst_node.sv │ │ └── syst_ws.sv │ │ ├── 02_pow5_pipelined │ │ └── pow5_pipelined.sv │ │ └── 03_pow5_pipelined_valid │ │ └── pow5_pipelined_valid.sv └── 04. LUTRAM BRAM │ └── examples │ ├── 01_lutram │ ├── lutram.png │ ├── lutram.sv │ └── lutram_tb.sv │ ├── 04_bram_dp_true │ ├── bram_dp_true_1clk.png │ ├── bram_dp_true_2clk.png │ ├── bram_dp_true_1clk.sv │ ├── bram_dp_true_2clk.sv │ ├── bram_dp_true_2clk_tb.sv │ └── bram_dp_true_1clk_tb.sv │ ├── 02_bram_1p │ ├── pictures │ │ ├── bram_1p_byte_en.png │ │ ├── bram_1p_no_change.png │ │ ├── bram_1p_out_reg.png │ │ ├── bram_1p_read_first.png │ │ └── bram_1p_write_first.png │ ├── bram_1p_no_change_memory.txt │ ├── bram_1p_read_first.sv │ ├── bram_1p_no_change.sv │ ├── bram_1p_write_first.sv │ ├── bram_1p_byte_en.sv │ ├── bram_1p_out_reg.sv │ ├── bram_1p_no_change_init.sv │ ├── bram_1p_no_change_init_tb.sv │ ├── bram_1p_no_change_tb.sv │ ├── bram_1p_write_first_tb.sv │ ├── bram_1p_read_first_tb.sv │ ├── bram_1p_byte_en_tb.sv │ └── bram_1p_out_reg_tb.sv │ └── 03_bram_dp_simple │ ├── bram_dp_simple_1clk.png │ ├── bram_dp_simple_2clk.png │ ├── bram_dp_simple_1clk.sv │ ├── bram_dp_simple_2clk.sv │ ├── bram_dp_simple_2clk_tb.sv │ └── bram_dp_simple_1clk_tb.sv ├── Other ├── Vivado STA │ ├── pic │ │ ├── f4.png │ │ ├── sh.png │ │ ├── sta.png │ │ ├── wns.png │ │ ├── delay.png │ │ ├── impl.png │ │ └── paths.png │ └── README.md └── exam_questions.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_store 2 | -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl2.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl3.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl4.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl5.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl6.png -------------------------------------------------------------------------------- /Labs/03. DSP/pic/dsp48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/dsp48.png -------------------------------------------------------------------------------- /Labs/01. Tcl/pic/tcl_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/01. Tcl/pic/tcl_add.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/f4.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/sh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/sh.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/sta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/sta.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/wns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/wns.png -------------------------------------------------------------------------------- /Labs/03. DSP/pic/mac.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/mac.drawio.png -------------------------------------------------------------------------------- /Labs/09. gcc make/pic/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/09. gcc make/pic/pic1.png -------------------------------------------------------------------------------- /Labs/09. gcc make/pic/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/09. gcc make/pic/pic2.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/delay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/delay.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/impl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/impl.png -------------------------------------------------------------------------------- /Other/Vivado STA/pic/paths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Other/Vivado STA/pic/paths.png -------------------------------------------------------------------------------- /Labs/02. LUT and FF/pic/adder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/02. LUT and FF/pic/adder.jpg -------------------------------------------------------------------------------- /Labs/03. DSP/pic/simd.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/simd.drawio.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/fork_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/fork_1.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/fork_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/fork_2.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/join_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/join_1.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/join_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/join_2.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/join_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/join_3.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/join_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/join_4.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/rr_arb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/rr_arb.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/wave_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/wave_1.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/wave_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/wave_2.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/wave_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/wave_3.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic1.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic2.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic3.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic4.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic5.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic6.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic7.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic8.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic9.png -------------------------------------------------------------------------------- /Labs/02. LUT and FF/pic/carry4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/02. LUT and FF/pic/carry4.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_vco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_vco.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic10.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic11.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic14.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic15.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic16.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic17.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/pic18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/pic18.png -------------------------------------------------------------------------------- /Labs/03. DSP/pic/pre_adder.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/pre_adder.drawio.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/crossbar_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/crossbar_1.png -------------------------------------------------------------------------------- /Labs/03. DSP/examples/02_mult_dsp/clk.xdc: -------------------------------------------------------------------------------- 1 | create_clock -period 10.000 -name clk_i -waveform {0.000 5.000} -add [get_ports clk_i] 2 | -------------------------------------------------------------------------------- /Labs/03. DSP/pic/mult_compare.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/mult_compare.drawio.png -------------------------------------------------------------------------------- /Labs/03. DSP/pic/mult_simple.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/mult_simple.drawio.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_filter.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/read_no_wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/read_no_wait.png -------------------------------------------------------------------------------- /Labs/03. DSP/examples/01_mult_no_dsp/clk.xdc: -------------------------------------------------------------------------------- 1 | create_clock -period 10.000 -name clk_i -waveform {0.000 5.000} -add [get_ports clk_i] 2 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/pic/read_with_wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/08. APB and CRC/pic/read_with_wait.png -------------------------------------------------------------------------------- /Labs/03. DSP/pic/mult_simple_async.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/03. DSP/pic/mult_simple_async.drawio.png -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/credit_flow_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/credit_flow_control.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_phasedetector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_phasedetector.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/1.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/3.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/4.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/5.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/6.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/7.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/8.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/9.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/graycode_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/graycode_animation.gif -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_instantiation_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_instantiation_1.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_instantiation_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_instantiation_2.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_instantiation_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_instantiation_3.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_instantiation_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/pll_instantiation_4.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/01_lutram/lutram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/01_lutram/lutram.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/10.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/11.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/12.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/13.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/15.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/16.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/17.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/18.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/20.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/comb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/comb.gif -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/sta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/sta.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/syst.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/syst.gif -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/pic/credit_flow_control_ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/06.AXI-Stream/pic/credit_flow_control_ff.png -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/pic/pipeline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/05. Pipelines and Systolic arrays/pic/pipeline.gif -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/vivado_simulator_settings_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/vivado_simulator_settings_1.png -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/vivado_simulator_settings_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/07. PLL and CDC/pic/vivado_simulator_settings_2.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example9.sv: -------------------------------------------------------------------------------- 1 | initial 2 | begin 3 | p_clk_i=0; 4 | forever #50 p_clk_i = ~p_clk_i; // Сигнал инвертируется каждые 50нс 5 | end 6 | -------------------------------------------------------------------------------- /Labs/01. Tcl/demoproject/build_project.bat: -------------------------------------------------------------------------------- 1 | call C:\Xilinx\Vivado\2016.4\settings64.bat 2 | rd /s /q demo 3 | vivado -mode=batch -nojournal -nolog -source build_project.tcl -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_1clk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_1clk.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_2clk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_2clk.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example12.sv: -------------------------------------------------------------------------------- 1 | initial 2 | begin 3 | write_register(32'd0, 32'hAA); 4 | #1200 write_register(32'd0, 32'h33); 5 | #1200 read_register(32'd4); 6 | end 7 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_byte_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_byte_en.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_no_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_no_change.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_out_reg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_out_reg.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_1clk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_1clk.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_2clk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_2clk.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_read_first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_read_first.png -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_write_first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPSU/FPGA_pract/HEAD/Labs/04. LUTRAM BRAM/examples/02_bram_1p/pictures/bram_1p_write_first.png -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example4.sv: -------------------------------------------------------------------------------- 1 | logic cs_1_ff; 2 | logic cs_2_ff; 3 | 4 | // Формирование строба cs цикла чтения или записи по системной шине 5 | always_ff @ (posedge p_clk_i) 6 | begin 7 | cs_1_ff <= p_enable_i & p_sel_i; 8 | cs_2_ff <= cs_1_ff; 9 | end 10 | 11 | logic cs; 12 | assign cs = cs_1_ff & (~cs_2_ff); 13 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example8.sv: -------------------------------------------------------------------------------- 1 | initial 2 | begin 3 | p_dat_i = 'hz; 4 | p_enable_i = 0; 5 | p_sel_i = 0; 6 | p_we_i = 'hz; 7 | p_adr_i = 'hz; 8 | p_rstn_i = 0; 9 | #200 10 | p_rstn_i = 1; // Запись #200 обозначает что смена значения сигнала сброса произойдет через 200нс. 11 | end 12 | -------------------------------------------------------------------------------- /Labs/01. Tcl/demoproject/rtl/demo_wrapper_nexys_a7.sv: -------------------------------------------------------------------------------- 1 | module demo_wrapper_nexys_a7 ( 2 | input logic CLK100MHZ, 3 | input logic BTNR, 4 | input logic [15:0] SW, 5 | output logic [15:0] LED 6 | ); 7 | 8 | 9 | demo demo_inst ( 10 | .clk_i (CLK100MHZ), 11 | .rst_i (BTNR), 12 | .sw_i (SW), 13 | .led_o (LED) 14 | ); 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_no_change_memory.txt: -------------------------------------------------------------------------------- 1 | 17767 2 | 9158 3 | 39017 4 | 18547 5 | 56401 6 | 23807 7 | 37962 8 | 22764 9 | 7977 10 | 31949 11 | 22714 12 | 55211 13 | 16882 14 | 7931 15 | 43491 16 | 57670 17 | 124 18 | 25282 19 | 2132 20 | 10232 21 | 8987 22 | 59880 23 | 52711 24 | 17293 25 | 3958 26 | 9562 27 | 63790 28 | 29283 29 | 49715 30 | 55199 31 | 50377 32 | 1946 -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example2.sv: -------------------------------------------------------------------------------- 1 | module wrapper_crc8 2 | ( 3 | input logic p_clk_i, 4 | input logic p_rstn_i, 5 | input logic [31:0] p_dat_i, 6 | output logic [31:0] p_dat_o, 7 | input logic p_sel_i, 8 | input logic p_enable_i, 9 | input logic p_we_i, 10 | input logic [31:0] p_adr_i, 11 | output logic p_ready 12 | ); 13 | -------------------------------------------------------------------------------- /Labs/03. DSP/examples/02_mult_dsp/mult_dsp_async.sv: -------------------------------------------------------------------------------- 1 | module mult_dsp_async 2 | #( 3 | parameter A_WIDTH = 25, 4 | parameter B_WIDTH = 18, 5 | parameter R_WIDTH = A_WIDTH + B_WIDTH 6 | ) 7 | ( 8 | input logic signed [A_WIDTH-1:0] a_i, 9 | input logic signed [B_WIDTH-1:0] b_i, 10 | output logic signed [R_WIDTH-1:0] res_o 11 | ); 12 | 13 | assign res_o = a_i * b_i; 14 | 15 | endmodule 16 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example6.sv: -------------------------------------------------------------------------------- 1 | logic cs_ack1_ff; 2 | logic cs_ack2_ff; 3 | 4 | // Формирование сигнала готовности системной шины p_ready 5 | always_ff @ (posedge p_clk_i) 6 | begin 7 | cs_ack1_ff <= cs_2_ff; 8 | cs_ack2_ff <= cs_ack1_ff; 9 | end 10 | 11 | logic p_ready_ff; 12 | 13 | always_ff @ (posedge p_clk_i) 14 | begin 15 | p_ready_ff <= (cs_ack1_ff & (~cs_ack2_ff)); 16 | end 17 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example3.sv: -------------------------------------------------------------------------------- 1 | logic [7:0] din_i; // Объявляем провода, которые будут подключаться к сигналам модуля 2 | logic [7:0] crc_o; 3 | logic crc_rd; 4 | logic data_valid_i; 5 | 6 | crc8 7 | i_crc8 8 | ( 9 | .clk_i (p_clk_i), // При подключении модуля указываем имя и название модуля name module_name (... 10 | .rstn_i (p_rstn_i), // Подключаем к каждому сигналу модуля провод .signal_name(wire_name), ... 11 | .din_i (din_i), 12 | .data_valid_i (data_valid_i), 13 | .crc_rd (crc_rd), 14 | .crc_o (crc_o) 15 | ); 16 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example11.v: -------------------------------------------------------------------------------- 1 | task read_register; 2 | input [31:0] reg_addr; 3 | begin 4 | @ (posedge p_clk_i); 5 | 6 | p_adr_i = reg_addr; 7 | p_enable_i = 0; 8 | p_sel_i = 1; 9 | p_we_i = 0; 10 | 11 | @ (posedge p_clk_i); 12 | 13 | p_enable_i = 1; 14 | 15 | wait (p_ready); 16 | 17 | $display("(%0t) Reading register [%0d] = 0x%0x", $time, p_adr_i, p_dat_o); 18 | 19 | @ (posedge p_clk_i); 20 | 21 | p_adr_i = 'hz; 22 | p_enable_i = 0; 23 | p_sel_i = 0; 24 | p_we_i = 'hz; 25 | end 26 | endtask 27 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example7.sv: -------------------------------------------------------------------------------- 1 | logic p_clk_; 2 | logic p_rstn_i; 3 | logic [31:0] p_dat_i; 4 | logic [31:0] p_dat_o; 5 | logic p_enable_i; 6 | logic p_sel_i; 7 | logic p_we_i; 8 | logic [31:0] p_adr_i; 9 | logic p_ready; 10 | 11 | wrapper_crc8 12 | dut_wrapper_crc8 13 | ( 14 | .p_clk_i (p_clk_i), 15 | .p_rstn_i (p_rstn_i), 16 | .p_dat_i (p_dat_i), 17 | .p_dat_o (p_dat_o), 18 | .p_enable_i (p_enable_i), 19 | .p_sel_i (p_sel_i), 20 | .p_we_i (p_we_i), 21 | .p_adr_i (p_adr_i), 22 | .p_ready (p_ready) 23 | ); 24 | -------------------------------------------------------------------------------- /Labs/01. Tcl/demoproject/tb/tb_demo.sv: -------------------------------------------------------------------------------- 1 | module tb_demo (); 2 | 3 | logic clk; 4 | logic rst; 5 | logic [15:0] sw; 6 | logic [15:0] led; 7 | 8 | initial begin 9 | clk <= 1'b0; 10 | sw <= 16'b0000_0000_0000_0000; 11 | end 12 | 13 | 14 | initial begin 15 | rst <= 1'b0; 16 | #1 17 | rst <= 1'b1; 18 | #50 19 | rst <= 1'b0; 20 | end 21 | 22 | 23 | always begin 24 | #10 25 | clk <= ~clk; 26 | end 27 | 28 | 29 | demo 30 | #(.TIMER_TICK(10)) 31 | DUT 32 | (.clk_i (clk), 33 | .rst_i (rst), 34 | .sw_i (sw), 35 | .led_o (led)); 36 | 37 | 38 | endmodule 39 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/example5.sv: -------------------------------------------------------------------------------- 1 | // Формирование выходных данных системной шины 2 | always_comb 3 | begin //Для чтения crc используем адрес 1 4 | if (cs & (~p_we_i) & (p_adr_i[3:0] == 4'd4)) 5 | p_dat_o <= {24'd0, crc_o}; 6 | end 7 | 8 | // Формирование сигналов на модуль-вычислитель 9 | 10 | //Для записи данных для расчета crc используем адрес 0 11 | assign data_valid_i = (cs & p_we_i & (p_adr_i[3:0] == 4'd0)); 12 | 13 | //Для записи данных для расчета crc используем адрес 0 14 | assign din_i = (cs & p_we_i & (p_adr_i[3:0] == 4'd0)); 15 | 16 | //Для чтения crc используем адрес 4 17 | assign crc_rd = (cs & ~p_we_i & (p_adr_i[3:0] == 4'd4)); 18 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/01_lutram/lutram.sv: -------------------------------------------------------------------------------- 1 | module lutram 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 5 5 | ) 6 | ( 7 | input logic clk_i, 8 | input logic [RAM_WIDTH-1:0] wdata_i, 9 | input logic [RAM_ADDR_BITS-1:0] waddr_i, 10 | input logic we_i, 11 | 12 | input logic [RAM_ADDR_BITS-1:0] raddr_i, 13 | output logic [RAM_WIDTH-1:0] rdata_o 14 | ); 15 | 16 | (* ram_style="distributed" *) 17 | logic [RAM_WIDTH-1:0] lutram [(2**RAM_ADDR_BITS)-1:0]; 18 | 19 | always_ff @(posedge clk_i) begin 20 | if (we_i) 21 | lutram[waddr_i] <= wdata_i; 22 | end 23 | 24 | assign rdata_o = lutram[raddr_i]; 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/examples/credit_counter.sv: -------------------------------------------------------------------------------- 1 | module credit_counter #( 2 | parameter int DEPTH = 10 3 | ) ( 4 | input logic clk_i, 5 | input logic rst_i, 6 | 7 | input logic valid_i, //from upstream 8 | input logic pop, //from downstream 9 | output logic ready_cred 10 | ); 11 | 12 | logic [$clog2(DEPTH+1) - 1 : 0] counter; 13 | 14 | always_ff @(posedge clk_i) begin 15 | if(rst_i) 16 | counter <= DEPTH; 17 | else if(pop & valid_i) 18 | counter <= counter; 19 | else begin 20 | if(valid_i) 21 | counter <= counter - 1; 22 | if(pop) 23 | counter <= counter + 1; 24 | end 25 | end 26 | 27 | assign ready_cred = (counter == 0)? 1'b0 : 1'b1; // ready for next writing in FIFO until counter != 0 28 | 29 | endmodule 30 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_read_first.sv: -------------------------------------------------------------------------------- 1 | module bram_1p_read_first 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 10 5 | ) 6 | ( 7 | input logic clk_i, 8 | input logic [RAM_ADDR_BITS-1:0] addr_i, 9 | input logic [RAM_WIDTH-1:0] data_i, 10 | input logic we_i, 11 | input logic en_i, 12 | output logic [RAM_WIDTH-1:0] data_o 13 | ); 14 | 15 | localparam RAM_DEPTH = 2**RAM_ADDR_BITS; 16 | 17 | logic [RAM_WIDTH-1:0] bram [RAM_DEPTH-1:0]; 18 | logic [RAM_WIDTH-1:0] data_out_ff; 19 | 20 | always_ff @(posedge clk_i) begin 21 | if (en_i) begin 22 | if (we_i) 23 | bram[addr_i] <= data_i; 24 | 25 | data_out_ff <= bram[addr_i]; 26 | end 27 | end 28 | 29 | assign data_o = data_out_ff; 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_no_change.sv: -------------------------------------------------------------------------------- 1 | module bram_1p_no_change 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 10 5 | ) 6 | ( 7 | input logic clk_i, 8 | input logic [RAM_ADDR_BITS-1:0] addr_i, 9 | input logic [RAM_WIDTH-1:0] data_i, 10 | input logic we_i, 11 | input logic en_i, 12 | output logic [RAM_WIDTH-1:0] data_o 13 | ); 14 | 15 | localparam RAM_DEPTH = 2**RAM_ADDR_BITS; 16 | 17 | logic [RAM_WIDTH-1:0] bram [RAM_DEPTH-1:0]; 18 | logic [RAM_WIDTH-1:0] data_out_ff; 19 | 20 | always_ff @(posedge clk_i) begin 21 | if (en_i) begin 22 | if (we_i) 23 | bram[addr_i] <= data_i; 24 | else 25 | data_out_ff <= bram[addr_i]; 26 | end 27 | end 28 | 29 | assign data_o = data_out_ff; 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_1clk.sv: -------------------------------------------------------------------------------- 1 | module bram_dp_simple_1clk 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 10 5 | ) 6 | ( 7 | input logic clk_i, 8 | input logic [RAM_ADDR_BITS-1:0] addr_a_i, 9 | input logic [RAM_ADDR_BITS-1:0] addr_b_i, 10 | input logic [RAM_WIDTH-1:0] data_a_i, 11 | input logic we_a_i, 12 | input logic en_b_i, 13 | output logic [RAM_WIDTH-1:0] data_b_o 14 | ); 15 | 16 | localparam RAM_DEPTH = 2**RAM_ADDR_BITS; 17 | 18 | logic [RAM_WIDTH-1:0] bram [RAM_DEPTH-1:0]; 19 | logic [RAM_WIDTH-1:0] ram_data_ff; 20 | 21 | always_ff @(posedge clk_i) begin 22 | if (we_a_i) 23 | bram[addr_a_i] <= data_a_i; 24 | if (en_b_i) 25 | ram_data_ff <= bram[addr_b_i]; 26 | end 27 | 28 | assign data_b_o = ram_data_ff; 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_write_first.sv: -------------------------------------------------------------------------------- 1 | module bram_1p_write_first 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 10 5 | ) 6 | ( 7 | input logic clk_i, 8 | input logic [RAM_ADDR_BITS-1:0] addr_i, 9 | input logic [RAM_WIDTH-1:0] data_i, 10 | input logic we_i, 11 | input logic en_i, 12 | output logic [RAM_WIDTH-1:0] data_o 13 | ); 14 | 15 | localparam RAM_DEPTH = 2**RAM_ADDR_BITS; 16 | 17 | logic [RAM_WIDTH-1:0] bram [RAM_DEPTH-1:0]; 18 | logic [RAM_WIDTH-1:0] data_out_ff; 19 | 20 | always_ff @(posedge clk_i) begin 21 | if (en_i) begin 22 | if (we_i) begin 23 | bram[addr_i] <= data_i; 24 | data_out_ff <= data_i; 25 | end else 26 | data_out_ff <= bram[addr_i]; 27 | end 28 | end 29 | 30 | assign data_o = data_out_ff; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /Labs/03. DSP/examples/03_pre_adder/pre_adder.sv: -------------------------------------------------------------------------------- 1 | module pre_adder 2 | ( 3 | input logic clk_i, 4 | input logic rst_i, 5 | input logic signed [23:0] a_i, 6 | input logic signed [17:0] b_i, 7 | input logic signed [23:0] c_i, 8 | output logic signed [42:0] res_o 9 | ); 10 | 11 | logic signed [23:0] a_ff; 12 | logic signed [17:0] b_ff; 13 | logic signed [23:0] c_ff; 14 | logic signed [42:0] res_ff; 15 | logic signed [42:0] mult; 16 | 17 | always_ff @(posedge clk_i) begin 18 | if (rst_i) begin 19 | a_ff <= '0; 20 | b_ff <= '0; 21 | c_ff <= '0; 22 | end 23 | else begin 24 | a_ff <= a_i; 25 | b_ff <= b_i; 26 | c_ff <= c_i; 27 | end 28 | end 29 | 30 | assign mult = (a_ff + c_ff) * b_ff; 31 | 32 | always_ff @(posedge clk_i) begin 33 | if (rst_i) 34 | res_ff <= '0; 35 | else 36 | res_ff <= mult; 37 | end 38 | 39 | assign res_o = res_ff; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_2clk.sv: -------------------------------------------------------------------------------- 1 | module bram_dp_simple_2clk 2 | #( 3 | parameter RAM_WIDTH = 8, 4 | parameter RAM_ADDR_BITS = 10 5 | ) 6 | ( 7 | input logic clk_a_i, 8 | input logic clk_b_i, 9 | input logic [RAM_ADDR_BITS-1:0] addr_a_i, 10 | input logic [RAM_ADDR_BITS-1:0] addr_b_i, 11 | input logic [RAM_WIDTH-1:0] data_a_i, 12 | input logic we_a_i, 13 | input logic en_b_i, 14 | output logic [RAM_WIDTH-1:0] data_b_o 15 | ); 16 | 17 | localparam RAM_DEPTH = 2**RAM_ADDR_BITS; 18 | 19 | logic [RAM_WIDTH-1:0] bram [RAM_DEPTH-1:0]; 20 | logic [RAM_WIDTH-1:0] ram_data_ff; 21 | 22 | always_ff @(posedge clk_a_i) 23 | if (we_a_i) 24 | bram[addr_a_i] <= data_a_i; 25 | 26 | always_ff @(posedge clk_b_i) 27 | if (en_b_i) 28 | ram_data_ff <= bram[addr_b_i]; 29 | 30 | assign data_b_o = ram_data_ff; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /Labs/01. Tcl/demoproject/rtl/demo.sv: -------------------------------------------------------------------------------- 1 | module demo 2 | #(parameter TIMER_TICK = 20000000) 3 | 4 | (input logic clk_i, 5 | input logic rst_i, 6 | input logic [15:0] sw_i, 7 | output logic [15:0] led_o 8 | ); 9 | 10 | logic [31:0] clk_timer_ff; 11 | 12 | logic timer_tick; 13 | assign timer_tick = (clk_timer_ff == TIMER_TICK); 14 | 15 | always_ff @(posedge clk_i or posedge rst_i) begin 16 | if (rst_i) 17 | clk_timer_ff <= 32'd0; 18 | else begin 19 | if(timer_tick) 20 | clk_timer_ff <= 32'd0; 21 | else 22 | clk_timer_ff <= clk_timer_ff + 1; 23 | end 24 | end 25 | 26 | 27 | logic [15:0] led_reg_ff; 28 | 29 | always_ff @(posedge clk_i or posedge rst_i) begin 30 | if (rst_i) begin 31 | led_reg_ff <= 16'b1000_0000_0000_0000; 32 | end 33 | else 34 | if (timer_tick) 35 | led_reg_ff <= {led_reg_ff[0], led_reg_ff[15:1]}; 36 | end 37 | 38 | assign led_o = sw_i ^ led_reg_ff; 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /Labs/03. DSP/examples/05_alu_simd/alu_simd.sv: -------------------------------------------------------------------------------- 1 | (* use_dsp = "simd" *) 2 | module alu_simd 3 | #( 4 | parameter N = 4, // Number of Adders 5 | parameter W = 10 // Width of the Adders 6 | ) 7 | ( 8 | input logic clk_i, 9 | input logic rst_i, 10 | input logic [W-1:0] a_i [N-1:0], 11 | input logic [W-1:0] b_i [N-1:0], 12 | output logic [W-1:0] res_o [N-1:0] 13 | ); 14 | 15 | integer i; 16 | logic [W-1:0] a_ff [N-1:0]; 17 | logic [W-1:0] b_ff [N-1:0]; 18 | logic [W-1:0] res_ff [N-1:0]; 19 | 20 | 21 | always_ff @(posedge clk_i) begin 22 | for(i=0; i credit counter + 1 21 | assign pow_valid_i = valid_i & ready_cred;// if pow_valid_i => credit counter - 1 22 | 23 | pow5_pipelined_valid # ( 24 | .DATA_WIDTH ( DATA_WIDTH ) 25 | ) 26 | pow5_pipelined_valid_inst ( 27 | .clk_i ( clk_i ), 28 | .rst_i ( rst_i ), 29 | .pow_data_i ( data_i ), 30 | .data_valid_i ( pow_valid_i ), 31 | .pow_data_o ( pow_data_o ), 32 | .data_valid_o ( pow_valid_o ) 33 | ); 34 | 35 | // FIFO 36 | 37 | fifo_ready_valid # ( 38 | .DATA_WIDTH( 5*DATA_WIDTH ), 39 | .DEPTH ( DEPTH ) 40 | ) 41 | fifo_ready_valid_inst ( 42 | .clk_i ( clk_i ), 43 | .rst_i ( rst_i ), 44 | .write_data_i ( pow_data_o ), 45 | .valid_i ( pow_valid_o ), 46 | .ready_o ( ), 47 | .ready_i ( ready_i ), 48 | .valid_o ( valid_o ), 49 | .read_data_o ( data_o ) 50 | ); 51 | // credit 52 | 53 | credit_counter # ( 54 | .DEPTH( DEPTH ) 55 | ) 56 | credit_counter_inst ( 57 | .clk_i ( clk_i ), 58 | .rst_i ( rst_i ), 59 | .valid_i ( pow_valid_i ), 60 | .pop ( pop ), 61 | .ready_cred ( ready_cred ) 62 | ); 63 | 64 | endmodule 65 | -------------------------------------------------------------------------------- /Labs/08. APB and CRC/examples/wrapper_crc8.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module wrapper_crc8 4 | ( 5 | input logic p_clk_i, 6 | input logic p_rstn_i, 7 | input logic [31:0] p_dat_i, 8 | output logic [31:0] p_dat_o, 9 | input logic p_sel_i, 10 | input logic p_enable_i, 11 | input logic p_we_i, 12 | input logic [31:0] p_adr_i, 13 | output logic p_ready, 14 | output logic p_slverr 15 | ); 16 | 17 | logic [7:0] din_i; 18 | logic [7:0] crc_o; 19 | logic [1:0] state; 20 | logic crc_rd; 21 | logic data_valid_i; 22 | 23 | assign p_slverr = 1'b0; 24 | 25 | crc8 26 | i_crc8 27 | ( 28 | .clk_i (p_clk_i), 29 | .rstn_i (p_rstn_i), 30 | .din_i (din_i), 31 | .data_valid_i (data_valid_i), 32 | .crc_rd (crc_rd), 33 | .crc_o (crc_o) 34 | ); 35 | 36 | logic cs_1_ff; 37 | logic cs_2_ff; 38 | 39 | logic cs_ack1_ff; 40 | logic cs_ack2_ff; 41 | 42 | always_ff @ (posedge p_clk_i) 43 | begin 44 | cs_1_ff <= p_enable_i & p_sel_i; 45 | cs_2_ff <= cs_1_ff; 46 | end 47 | 48 | logic cs; 49 | assign cs = cs_1_ff & (~cs_2_ff); 50 | 51 | always_ff @ (posedge p_clk_i) 52 | begin 53 | cs_ack1_ff <= cs_2_ff; 54 | cs_ack2_ff <= cs_ack1_ff; 55 | end 56 | 57 | // Generating acknowledge signal 58 | logic p_ready_ff; 59 | 60 | always_ff @ (posedge p_clk_i) 61 | begin 62 | p_ready_ff <= (cs_ack1_ff & (~cs_ack2_ff)); 63 | end 64 | 65 | assign p_ready = p_ready_ff; 66 | 67 | always_comb 68 | begin 69 | p_dat_o = '0; 70 | if (cs & (~p_we_i) & (p_adr_i[3:0] == 4'd4)) 71 | p_dat_o = {24'd0, crc_o}; 72 | else if (cs & (~p_we_i)& (p_adr_i[3:0] == 4'd8)) 73 | p_dat_o = {24'd0, state}; 74 | end 75 | 76 | assign data_valid_i = (cs & p_we_i & p_adr_i[3:0] == 4'd0); 77 | assign din_i = (cs & p_we_i & p_adr_i[3:0] == 4'd0) ? p_dat_i[7:0]: 8'd0; 78 | assign crc_rd = (cs & ~p_we_i & p_adr_i[3:0] == 4'd4); 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/examples/tb/fifo_ready_valid_tb.sv: -------------------------------------------------------------------------------- 1 | module fifo_ready_valid_tb; 2 | 3 | localparam int CLK_TIME = 5; 4 | localparam int CYCLE = 2*CLK_TIME; 5 | 6 | parameter int DATA_WIDTH = 4; 7 | parameter int DEPTH = 10; 8 | 9 | 10 | logic clk_i; 11 | logic rst_i; 12 | 13 | logic ready_o; 14 | logic ready_i; 15 | 16 | logic valid_i; 17 | logic valid_o; 18 | 19 | logic [DATA_WIDTH - 1 : 0] data_i; 20 | logic [DATA_WIDTH - 1 : 0] data_o; 21 | 22 | fifo_ready_valid # ( 23 | .DATA_WIDTH( DATA_WIDTH ), 24 | .DEPTH ( DEPTH ) 25 | ) 26 | fifo_ready_valid_inst ( 27 | .clk_i ( clk_i ), 28 | .rst_i ( rst_i ), 29 | .write_data_i ( data_i ), 30 | .valid_i ( valid_i ), 31 | .ready_o ( ready_o ), 32 | .ready_i ( ready_i ), 33 | .valid_o ( valid_o ), 34 | .read_data_o ( data_o ) 35 | ); 36 | 37 | initial begin 38 | rst_i = 1'b1; 39 | #CYCLE; rst_i = 1'b0; 40 | end 41 | 42 | initial begin // clk_i and rst_i 43 | clk_i = 1'b1; 44 | forever begin 45 | clk_i = ~clk_i; #CLK_TIME; 46 | end 47 | end 48 | 49 | initial begin 50 | ready_i <= 1'b0; 51 | valid_i <= 1'b0; 52 | #CYCLE; 53 | for(int i = 0;i pop, rd_pointer + 1 33 | assign push = ~full & valid_i; // we writing => push, wr_pointer + 1 34 | 35 | 36 | always_ff @(posedge clk_i) begin 37 | if(rst_i)begin 38 | wr_pointer <= '0; 39 | wr_odd_circle <= '0; 40 | end else if (push) begin 41 | if(wr_pointer == max_pointer)begin 42 | wr_pointer <= '0; // in case that if max pointer != DEPTH 43 | wr_odd_circle <= ~wr_odd_circle; // Занятие 17 школа синтеза {23:40} 44 | end else 45 | wr_pointer <= wr_pointer + 1; 46 | end 47 | end 48 | 49 | always_ff @(posedge clk_i) begin 50 | if(rst_i)begin 51 | rd_pointer <= '0; 52 | rd_odd_circle <= '0; 53 | end else if(pop) begin 54 | if(rd_pointer == max_pointer)begin 55 | rd_pointer <= '0; // in case that if max pointer != DEPTH 56 | rd_odd_circle <= ~rd_odd_circle; // Занятие 17 школа синтеза {23:40} 57 | end else 58 | rd_pointer <= rd_pointer + 1; 59 | end 60 | end 61 | 62 | always_ff @(posedge clk_i) begin : writing_data 63 | if(push) 64 | fifo[wr_pointer] <= write_data_i; 65 | end 66 | 67 | assign read_data_o = fifo[rd_pointer]; // reading data 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_no_change_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data() 2 | // затем чтение requset_read() 3 раза 3 | // затем запись requset_write() 3 раза 4 | 5 | module bram_1p_no_change_tb(); 6 | 7 | localparam int RAM_WIDTH = 16; 8 | localparam int RAM_ADDR_BITS = 3; 9 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 10 | 11 | logic clk_i; 12 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_i; 13 | logic [ RAM_WIDTH - 1 : 0 ] data_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_o; 15 | logic we_i; 16 | logic en_i; 17 | 18 | bram_1p_no_change # ( 19 | .RAM_WIDTH ( RAM_WIDTH ), 20 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 21 | ) 22 | bram_1p_no_change_inst ( 23 | .clk_i ( clk_i ), 24 | .addr_i ( addr_i ), 25 | .we_i ( we_i ), 26 | .en_i ( en_i ), 27 | .data_i ( data_i ), 28 | .data_o ( data_o ) 29 | ); 30 | //------------------------------------------------- clk_i 31 | initial begin 32 | clk_i = 1'b0; 33 | forever begin 34 | clk_i = ~clk_i; #5; 35 | end 36 | end 37 | //------------------------------------------------- WRITE MODULE 38 | int p; 39 | event end_of_fill; 40 | 41 | initial begin 42 | #10; 43 | p = 0; 44 | we_i = '0; 45 | 46 | repeat(RAM_DEPTH)begin// заполнение памяти 47 | fill_data(); #5; 48 | p = p + 1; 49 | end 50 | 51 | ->end_of_fill; 52 | wait(end_of_read.triggered) // ждем окончания чтения 53 | 54 | #10; // запись в память 55 | requset_write(); 56 | #30; 57 | requset_write(); 58 | #30; 59 | requset_write(); 60 | #30; 61 | $finish; 62 | end 63 | 64 | task fill_data(); 65 | @(posedge clk_i) 66 | we_i = '1; 67 | en_i = '1; 68 | addr_i = p; 69 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 70 | #5; @(posedge clk_i) 71 | en_i = '0; 72 | we_i = '0; 73 | endtask 74 | 75 | task requset_write(); 76 | @(posedge clk_i) 77 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 78 | we_i = '1; 79 | en_i = '1; 80 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 81 | #5; @(posedge clk_i) 82 | en_i = '0; 83 | we_i = '0; 84 | endtask 85 | //------------------------------------------------- READ MODULE 86 | event end_of_read; 87 | initial begin 88 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 89 | #10; // чтение из памяти 90 | requset_read(); 91 | #30; 92 | requset_read(); 93 | #30; 94 | requset_read(); 95 | #30; 96 | ->end_of_read; 97 | end 98 | 99 | task requset_read(); 100 | @(posedge clk_i) 101 | en_i = 1'b1; 102 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 103 | #5; @(posedge clk_i); 104 | en_i = 1'b0; 105 | endtask 106 | 107 | endmodule 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Курс "Практикум по ПЛИС на основе Verilog" 2 | 3 | Курс посвящен изучению продвинутых тем, связанных с проектированием устройств на языках описания аппаратуры (SysytemVerilog) и внутренней структурой FPGA на примере семейства Xilinx 7. 4 | 5 | Однажды тут появится красивое и вдохновляющее описание, но пока только так. 6 | 7 | 8 | ## Список материалов 9 | * [Лабораторная работа 1. Tcl](./Labs/01.%20Tcl/README.md) 10 | * [Лабораторная работа 2. LUT, FF, Carry](./Labs/02.%20LUT%20and%20FF/README.md) 11 | * [Лабораторная работа 3. DSP ячейки](./Labs/03.%20DSP/README.md) 12 | * [Лабораторная работа 4. LUTRAM, BRAM](./Labs/04.%20LUTRAM%20BRAM/README.md) 13 | * [Лабораторная работа 5. Конвейеры и систолические массивы](./Labs/05.%20Pipelines%20and%20Systolic%20arrays/README.md) 14 | * [Лабораторная работа 6. Шина AXI-Stream, Valid-Ready, Credit Flow control](./Labs/06.AXI-Stream/README.md) 15 | * [Лабораторная работа 7. PLL, пересечение доменов тактовых частот](./Labs/07.%20PLL%20and%20CDC/README.md) 16 | * [Лабораторная работа 8. Системная шина APB, разработка периферийного устройства](./Labs/08.%20APB%20and%20CRC/README.md) 17 | * [Лабораторная работа 9. GCC, Makefile](./Labs/09.%20gcc%20make/README.md) 18 | * Лабораторная работа 10. СнК Pulpino, интеграция периферийного устройства, разработка драйвера 19 | 20 | * [Вопросы на зачёт](./Other/exam_questions.md) 21 | 22 | ## Bug bounty 23 | Материалы курса находятся в активной разработке и наверняка содержат ошибки, опечатки, плохие формулировки, недостаточно подробные объяснения и тому подобное. 24 | 25 | Вы можете помочь с разработкой курса и предлагать свои правки и улучшения через механизм [Pull Request](https://github.com/MPSU/FPGA_pract/pulls). 26 | 27 | Почему вы можете захотеть помогать? Думаю, что на это есть несколько причин: 28 | * Моральное удовлетворение. Согласитесь, приятно внести свой вклад во какое-то общее дело. 29 | * Дополнительные баллы. Тут всё понятно, за помощь можно получить некоторое количество благодарностей от преподавателя - от "спасибо" до автомата на зачёте. Зависит от объёма этой самой помощи. Конечно, оценка объёма это субъективная штука, но мы постараемся активных студентов не обижать. 30 | * Включение в список создателей курса. Круто же, когда на протяжении многих лет следующие поколения студентов будут видеть ваше имя в списках людей, приложивших свои силы к созданию курса? 31 | 32 | Последний пункт требует некоторых пояснений. Список создателей курса состоит из двух категорий: 33 | * Автор - человек, который: 34 | * Написал хотя-бы одну лабораторную работу 35 | * Выполнил капитальную переработку хотя-бы одной лабораторной работы 36 | * Готовый материал которого лёг в основу лабораторной работы 37 | * Участник - человек, который внёс вклад в доработки лабораторной работы: 38 | * Исправления ошибок и опечаток 39 | * Улучшения формулировок 40 | * Добавление абзацев поясняющего текста 41 | * Добавление картинок и иллюстраций 42 | 43 | По мере накопления (субъективно) достаточно большого вклада в проект Участник может быть переведён в Авторы. 44 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_write_first_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data() 2 | // затем чтение requset_read() 3 раза 3 | // затем запись requset_write() 3 раза 4 | // (при записи автоматически читается что записываем) 5 | 6 | module bram_1p_write_first_tb(); 7 | 8 | 9 | localparam int RAM_WIDTH = 16; 10 | localparam int RAM_ADDR_BITS = 3; 11 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 12 | 13 | logic clk_i; 14 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_i; 16 | logic [ RAM_WIDTH - 1 : 0 ] data_o; 17 | logic we_i; 18 | logic en_i; 19 | 20 | bram_1p_write_first # ( 21 | .RAM_WIDTH ( RAM_WIDTH ), 22 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 23 | ) 24 | bram_1p_write_first_inst ( 25 | .clk_i ( clk_i ), 26 | .addr_i ( addr_i ), 27 | .we_i ( we_i ), 28 | .en_i ( en_i ), 29 | .data_i ( data_i ), 30 | .data_o ( data_o ) 31 | ); 32 | //------------------------------------------------- clk_i 33 | initial begin 34 | clk_i = 1'b0; 35 | forever begin 36 | clk_i = ~clk_i; #5; 37 | end 38 | end 39 | //------------------------------------------------- WRITE MODULE 40 | int p; 41 | event end_of_fill; 42 | 43 | initial begin 44 | #10; 45 | p = 0; 46 | we_i = '0; 47 | 48 | repeat(RAM_DEPTH)begin // заполнение памяти 49 | fill_data(); #5; 50 | p = p + 1; 51 | end 52 | 53 | ->end_of_fill; 54 | wait(end_of_read.triggered) // ждем окончания чтения 55 | 56 | #10; // запись в память 57 | requset_write(); 58 | #30; 59 | requset_write(); 60 | #30; 61 | requset_write(); 62 | #30; 63 | $finish; 64 | end 65 | 66 | task fill_data(); 67 | @(posedge clk_i) 68 | we_i = '1; 69 | en_i = '1; 70 | addr_i = p; 71 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 72 | #5; @(posedge clk_i) 73 | en_i = '0; 74 | we_i = '0; 75 | endtask 76 | 77 | task requset_write(); 78 | @(posedge clk_i) 79 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 80 | we_i = '1; 81 | en_i = '1; 82 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 83 | #5; @(posedge clk_i) 84 | en_i = '0; 85 | we_i = '0; 86 | endtask 87 | //------------------------------------------------- READ MODULE 88 | event end_of_read; 89 | initial begin 90 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 91 | #10; // чтение из памяти 92 | requset_read(); 93 | #30; 94 | requset_read(); 95 | #30; 96 | requset_read(); 97 | #30; 98 | ->end_of_read; 99 | end 100 | 101 | task requset_read(); 102 | @(posedge clk_i) 103 | en_i = 1'b1; 104 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 105 | #5; @(posedge clk_i); 106 | en_i = 1'b0; 107 | endtask 108 | 109 | endmodule 110 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_read_first_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data() 2 | // затем чтение requset_read() 3 раза 3 | // затем запись requset_write() 3 раза 4 | // (при записи автоматически читается вымещенное зачение) 5 | 6 | module bram_1p_read_first_tb(); 7 | 8 | localparam int RAM_WIDTH = 16; 9 | localparam int RAM_ADDR_BITS = 3; 10 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 11 | 12 | logic clk_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_o; 16 | logic we_i; 17 | logic en_i; 18 | 19 | bram_1p_read_first # ( 20 | .RAM_WIDTH ( RAM_WIDTH ), 21 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 22 | ) 23 | bram_1p_read_first_inst ( 24 | .clk_i ( clk_i ), 25 | .addr_i ( addr_i ), 26 | .we_i ( we_i ), 27 | .en_i ( en_i ), 28 | .data_i ( data_i ), 29 | .data_o ( data_o ) 30 | ); 31 | //------------------------------------------------- clk_i 32 | initial begin 33 | clk_i = 1'b0; 34 | forever begin 35 | clk_i = ~clk_i; #5; 36 | end 37 | end 38 | //------------------------------------------------- WRITE MODULE 39 | int p; 40 | event end_of_fill; 41 | 42 | initial begin 43 | #10; 44 | p = 0; 45 | we_i = '0; 46 | 47 | repeat(RAM_DEPTH)begin // заполнение памяти 48 | fill_data(); #5; 49 | p = p + 1; 50 | end 51 | 52 | ->end_of_fill; 53 | wait(end_of_read.triggered) // ждем окончания чтения 54 | 55 | #10; // запись в память 56 | requset_write(); 57 | #30; 58 | requset_write(); 59 | #30; 60 | requset_write(); 61 | #30; 62 | $finish; 63 | end 64 | 65 | task fill_data(); 66 | @(posedge clk_i) 67 | we_i = '1; 68 | en_i = '1; 69 | addr_i = p; 70 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 71 | #5; @(posedge clk_i) 72 | en_i = '0; 73 | we_i = '0; 74 | endtask 75 | 76 | task requset_write(); 77 | @(posedge clk_i) 78 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 79 | we_i = '1; 80 | en_i = '1; 81 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 82 | #5; @(posedge clk_i) 83 | en_i = '0; 84 | we_i = '0; 85 | endtask 86 | //------------------------------------------------- READ MODULE 87 | event end_of_read; 88 | initial begin 89 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 90 | #10; // чтение из памяти 91 | requset_read(); 92 | #30; 93 | requset_read(); 94 | #30; 95 | requset_read(); 96 | #30; 97 | ->end_of_read; 98 | end 99 | 100 | task requset_read(); 101 | @(posedge clk_i) 102 | en_i = 1'b1; 103 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 104 | #5; @(posedge clk_i); 105 | en_i = 1'b0; 106 | endtask 107 | 108 | endmodule 109 | 110 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_byte_en_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data() 2 | // затем чтение requset_read() 3 раза 3 | // затем запись requset_replace_byte() 3 раза 4 | 5 | module bram_1p_byte_en_tb(); 6 | 7 | localparam int NB_COL = 2; 8 | localparam int COL_WIDTH = 8; 9 | localparam int RAM_ADDR_BITS = 3; 10 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 11 | 12 | logic clk_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_i; 14 | logic [ (NB_COL*COL_WIDTH) - 1 : 0 ] data_i; 15 | logic [ (NB_COL*COL_WIDTH) - 1 : 0 ] data_o; 16 | logic [ NB_COL - 1 : 0 ] we_i; 17 | logic en_i; 18 | 19 | bram_1p_byte_en # ( 20 | .NB_COL ( NB_COL ), 21 | .COL_WIDTH ( COL_WIDTH ), 22 | .RAM_ADDR_BITS( RAM_ADDR_BITS ) 23 | ) 24 | bram_1p_byte_en_inst ( 25 | .clk_i ( clk_i ), 26 | .addr_i ( addr_i ), 27 | .we_i ( we_i ), 28 | .en_i ( en_i ), 29 | .data_i ( data_i ), 30 | .data_o ( data_o ) 31 | ); 32 | //------------------------------------------------- clk_i 33 | initial begin 34 | clk_i = 1'b0; 35 | forever begin 36 | clk_i = ~clk_i; #5; 37 | end 38 | end 39 | //------------------------------------------------- WRITE MODULE 40 | int p; 41 | event end_of_fill; 42 | 43 | initial begin 44 | #10; 45 | p = 0; 46 | we_i = '0; 47 | 48 | repeat(RAM_DEPTH)begin // заполнение памяти 49 | fill_data(); #5; 50 | p = p + 1; 51 | end 52 | 53 | ->end_of_fill; 54 | wait(end_of_read.triggered) // ждем окончания чтения 55 | 56 | #10; // запись в память 57 | requset_replace_byte(); 58 | #30; 59 | requset_replace_byte(); 60 | #30; 61 | requset_replace_byte(); 62 | #30; 63 | $finish; 64 | end 65 | 66 | task fill_data(); 67 | @(posedge clk_i) 68 | we_i = '1; 69 | en_i = '1; 70 | addr_i = p; 71 | data_i = $urandom_range(0, 2**(NB_COL*COL_WIDTH) - 1); 72 | #5; @(posedge clk_i) 73 | en_i = '0; 74 | we_i = '0; 75 | endtask 76 | 77 | int temp; 78 | task requset_replace_byte(); 79 | @(posedge clk_i) 80 | addr_i = $urandom_range(0, RAM_DEPTH ); 81 | temp = $urandom_range(0, NB_COL - 1); 82 | we_i[temp] = '1; 83 | en_i = '1; 84 | data_i = $urandom_range(0, 2**(NB_COL*COL_WIDTH) - 1); 85 | #5; @(posedge clk_i) 86 | en_i = '0; 87 | we_i = '0; 88 | endtask 89 | //------------------------------------------------- READ MODULE 90 | event end_of_read; 91 | initial begin 92 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 93 | #10; // чтение из памяти 94 | requset_read(); 95 | #30; 96 | requset_read(); 97 | #30; 98 | requset_read(); 99 | #30; 100 | ->end_of_read; 101 | end 102 | 103 | task requset_read(); 104 | @(posedge clk_i) 105 | en_i = 1'b1; 106 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 107 | #5; @(posedge clk_i); 108 | en_i = 1'b0; 109 | endtask 110 | 111 | endmodule 112 | -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/examples/05_syst_ws/syst_ws.sv: -------------------------------------------------------------------------------- 1 | module syst_ws 2 | ( 3 | input logic clk_i, 4 | input logic rst_i, 5 | 6 | input logic [7:0] x1_i, 7 | input logic [7:0] x2_i, 8 | input logic [7:0] x3_i, 9 | 10 | output logic [18:0] y1_o, 11 | output logic [18:0] y2_o 12 | ); 13 | 14 | localparam W11 = 8'd2; 15 | localparam W12 = 8'd3; 16 | localparam W13 = 8'd4; 17 | localparam W21 = 8'd5; 18 | localparam W22 = 8'd6; 19 | localparam W23 = 8'd7; 20 | 21 | 22 | localparam W_WIDTH = 8; 23 | localparam X_WIDTH = 8; 24 | 25 | logic [7:0] x1_pipe; 26 | logic [7:0] x2_pipe; 27 | logic [7:0] x3_pipe; 28 | logic [16:0] psumm11; 29 | logic [17:0] psumm12; 30 | logic [18:0] psumm13; 31 | logic [16:0] psumm21; 32 | logic [17:0] psumm22; 33 | logic [18:0] psumm23; 34 | 35 | syst_node #( 36 | .W_WIDTH (8), 37 | .X_WIDTH (8), 38 | .SI_WIDTH (1), 39 | .SO_WIDTH (17) 40 | ) node_11 ( 41 | .clk_i (clk_i), 42 | .rst_i (rst_i), 43 | .weight_i (W11), 44 | .psumm_i ('0), 45 | .x_i (x1_i), 46 | .psumm_o (psumm11), 47 | .x_o (x1_pipe) 48 | ); 49 | 50 | 51 | syst_node #( 52 | .W_WIDTH (8), 53 | .X_WIDTH (8), 54 | .SI_WIDTH (17), 55 | .SO_WIDTH (18) 56 | ) node_12 ( 57 | .clk_i (clk_i), 58 | .rst_i (rst_i), 59 | .weight_i (W12), 60 | .psumm_i (psumm11), 61 | .x_i (x2_i), 62 | .psumm_o (psumm12), 63 | .x_o (x2_pipe) 64 | ); 65 | 66 | // Exercise: Add nodes 13 and 23 to systolic array 67 | 68 | // syst_node #( 69 | // .W_WIDTH (8), 70 | // .X_WIDTH (8), 71 | // .SI_WIDTH (18), 72 | // .SO_WIDTH (19) 73 | // ) node_13 ( 74 | // .clk_i (clk_i), 75 | // .rst_i (rst_i), 76 | // .weight_i (), 77 | // .psumm_i (), 78 | // .x_i (), 79 | // .psumm_o (), 80 | // .x_o () 81 | // ); 82 | 83 | 84 | syst_node #( 85 | .W_WIDTH (8), 86 | .X_WIDTH (8), 87 | .SI_WIDTH (1), 88 | .SO_WIDTH (17) 89 | ) node_21 ( 90 | .clk_i (clk_i), 91 | .rst_i (rst_i), 92 | .weight_i (W21), 93 | .psumm_i ('0), 94 | .x_i (x1_pipe), 95 | .psumm_o (psumm21), 96 | .x_o () 97 | ); 98 | 99 | 100 | syst_node #( 101 | .W_WIDTH (8), 102 | .X_WIDTH (8), 103 | .SI_WIDTH (17), 104 | .SO_WIDTH (18) 105 | ) node_22 ( 106 | .clk_i (clk_i), 107 | .rst_i (rst_i), 108 | .weight_i (W22), 109 | .psumm_i (psumm21), 110 | .x_i (x2_pipe), 111 | .psumm_o (psumm22), 112 | .x_o () 113 | ); 114 | 115 | // Exercise: Add nodes 13 and 23 to systolic array 116 | 117 | // syst_node #( 118 | // .W_WIDTH (8), 119 | // .X_WIDTH (8), 120 | // .SI_WIDTH (18), 121 | // .SO_WIDTH (19) 122 | // ) node_23 ( 123 | // .clk_i (clk_i), 124 | // .rst_i (rst_i), 125 | // .weight_i (), 126 | // .psumm_i (), 127 | // .x_i (), 128 | // .psumm_o (), 129 | // .x_o () 130 | // ); 131 | 132 | 133 | assign y1_o = psumm12; 134 | assign y2_o = psumm22; 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_2clk_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data () 2 | // затем чтение requset_read () 3 раза 3 | // затем запись requset_write () 3 раза 4 | 5 | module bram_dp_simple_2clk_tb(); 6 | localparam int RAM_WIDTH = 16; 7 | localparam int RAM_ADDR_BITS = 3; 8 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 9 | 10 | logic clk_a_i; 11 | logic clk_b_i; 12 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_a_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_b_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_a_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_b_o; 16 | logic we_a_i; 17 | logic en_b_i; 18 | 19 | bram_dp_simple_2clk # ( 20 | .RAM_WIDTH ( RAM_WIDTH ), 21 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 22 | ) 23 | bram_dp_simple_2clk_inst ( 24 | .clk_a_i ( clk_a_i ), 25 | .clk_b_i ( clk_b_i ), 26 | .addr_a_i ( addr_a_i ), 27 | .addr_b_i ( addr_b_i ), 28 | .data_a_i ( data_a_i ), 29 | .we_a_i ( we_a_i ), 30 | .en_b_i ( en_b_i ), 31 | .data_b_o ( data_b_o ) 32 | ); 33 | //------------------------------------------------- clk_a_i и clk_b_i 34 | initial begin 35 | clk_a_i = 1'b0; 36 | forever begin 37 | clk_a_i = ~clk_a_i; #5; 38 | end 39 | end 40 | 41 | initial begin 42 | clk_b_i = 1'b1; #2.5; 43 | forever begin 44 | clk_b_i = ~clk_b_i; #5; 45 | end 46 | end 47 | //------------------------------------------------- WRITE MODULE 48 | int p; 49 | event end_of_fill; 50 | 51 | initial begin 52 | #10; 53 | p = 0; 54 | we_a_i = '0; 55 | 56 | repeat(RAM_DEPTH)begin // заполнение памяти 57 | fill_data(); #5; 58 | p = p + 1; 59 | end 60 | 61 | ->end_of_fill; 62 | wait(end_of_read.triggered)// ждем окончания чтения 63 | #10; 64 | requset_write(); // запись в память 65 | #30; 66 | requset_write(); 67 | #30; 68 | requset_write(); 69 | #30; 70 | $finish; 71 | end 72 | 73 | task fill_data(); 74 | @(posedge clk_a_i) 75 | we_a_i = '1; 76 | addr_a_i = p; 77 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 78 | #5; @(posedge clk_a_i) 79 | we_a_i = '0; 80 | endtask 81 | 82 | task requset_write(); 83 | @(posedge clk_a_i) 84 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 85 | we_a_i = '1; 86 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 87 | #5; @(posedge clk_a_i) 88 | we_a_i = '0; 89 | endtask 90 | //------------------------------------------------- READ MODULE 91 | event end_of_read; 92 | initial begin 93 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 94 | #10; // чтение памяти 95 | requset_read(); 96 | #30; 97 | requset_read(); 98 | #30; 99 | requset_read(); 100 | #30; 101 | ->end_of_read; 102 | end 103 | 104 | task requset_read(); 105 | @(posedge clk_b_i) 106 | en_b_i = 1'b1; 107 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 108 | #5; @(posedge clk_b_i); 109 | en_b_i = 1'b0; 110 | endtask 111 | 112 | endmodule 113 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/02_bram_1p/bram_1p_out_reg_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data() 2 | // затем чтение requset_read() 3 раза 3 | // затем запись requset_write() 3 раза 4 | 5 | module bram_1p_out_reg_tb(); 6 | 7 | localparam int RAM_WIDTH = 16; 8 | localparam int RAM_ADDR_BITS = 3; 9 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 10 | 11 | logic clk_i; 12 | logic rst_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_o; 16 | logic we_i; 17 | logic reg_en_i; 18 | logic en_i; 19 | 20 | bram_1p_out_reg # ( 21 | .RAM_WIDTH ( RAM_WIDTH ), 22 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 23 | ) 24 | bram_1p_out_reg_inst ( 25 | .clk_i ( clk_i ), 26 | .rst_i ( rst_i ), 27 | .addr_i ( addr_i ), 28 | .reg_en_i ( reg_en_i ), 29 | .we_i ( we_i ), 30 | .en_i ( en_i ), 31 | .data_i ( data_i ), 32 | .data_o ( data_o ) 33 | ); 34 | //------------------------------------------------- clk_i and rst_i 35 | initial begin 36 | clk_i = 1'b0; 37 | forever begin 38 | clk_i = ~clk_i; #5; 39 | end 40 | end 41 | initial begin 42 | rst_i = 1'b1; 43 | #10; 44 | rst_i = 1'b0; 45 | end 46 | //------------------------------------------------- WRITE MODULE 47 | int p; 48 | event end_of_fill; 49 | 50 | initial begin 51 | #10; 52 | p = 0; 53 | we_i = '0; 54 | 55 | repeat(RAM_DEPTH)begin// заполнение памяти 56 | fill_data(); #5; 57 | p = p + 1; 58 | end 59 | 60 | ->end_of_fill; 61 | wait(end_of_read.triggered)// ждем окончания чтения 62 | 63 | #10; // запись в память 64 | requset_write(); 65 | #30; 66 | requset_write(); 67 | #30; 68 | requset_write(); 69 | #30; 70 | $finish; 71 | end 72 | 73 | task fill_data(); 74 | @(posedge clk_i) 75 | we_i = '1; 76 | en_i = '1; 77 | addr_i = p; 78 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 79 | #5; @(posedge clk_i) 80 | en_i = '0; 81 | we_i = '0; 82 | endtask 83 | 84 | task requset_write(); 85 | @(posedge clk_i) 86 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 87 | we_i = '1; 88 | en_i = '1; 89 | data_i = $urandom_range(0, 2**RAM_WIDTH - 1); 90 | #5; @(posedge clk_i) 91 | en_i = '0; 92 | we_i = '0; 93 | endtask 94 | //------------------------------------------------- READ MODULE 95 | event end_of_read; 96 | initial begin 97 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 98 | #10; // чтение из памяти 99 | requset_read(); 100 | #10; 101 | requset_read(); 102 | #10; 103 | requset_read(); 104 | #10; 105 | ->end_of_read; 106 | end 107 | 108 | task requset_read(); 109 | @(posedge clk_i) 110 | en_i = 1'b1; 111 | addr_i = $urandom_range(0, RAM_DEPTH - 1); 112 | #5; @(posedge clk_i); 113 | en_i = 1'b0; 114 | addr_i = 'x; 115 | #15; @(posedge clk_i); 116 | reg_en_i = 1'b1; 117 | #5; @(posedge clk_i); 118 | reg_en_i = 1'b0; 119 | endtask 120 | 121 | endmodule 122 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/01_lutram/lutram_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data () 2 | // затем чтение requset_read () 3 раза 3 | // затем чтение и запись read_and_write() 3 раза 4 | // затем просто запись requset_write () 3 раза 5 | 6 | module lutram_tb(); 7 | 8 | 9 | localparam int RAM_WIDTH = 16; 10 | localparam int RAM_ADDR_BITS = 3; 11 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 12 | 13 | logic clk_i; 14 | logic [ RAM_ADDR_BITS - 1 : 0 ] waddr_i; 15 | logic [ RAM_ADDR_BITS - 1 : 0 ] raddr_i; 16 | logic [ RAM_WIDTH - 1 : 0 ] wdata_i; 17 | logic [ RAM_WIDTH - 1 : 0 ] rdata_o; 18 | logic we_i; 19 | 20 | lutram # ( 21 | .RAM_WIDTH ( RAM_WIDTH ), 22 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 23 | ) 24 | lutram_inst ( 25 | .clk_i ( clk_i ), 26 | .wdata_i ( wdata_i ), 27 | .waddr_i ( waddr_i ), 28 | .we_i ( we_i ), 29 | .raddr_i ( raddr_i ), 30 | .rdata_o ( rdata_o ) 31 | ); 32 | //------------------------------------------------- clk_i 33 | initial begin 34 | clk_i = 1'b0; 35 | forever begin 36 | clk_i = ~clk_i; #5; 37 | end 38 | end 39 | //------------------------------------------------- WRITE MODULE 40 | int p; 41 | event end_of_fill; 42 | 43 | initial begin 44 | #10; 45 | p = 0; 46 | we_i = '0; 47 | 48 | repeat(RAM_DEPTH)begin// заполнение памяти 49 | fill_data(); #5; 50 | p = p + 1; 51 | end 52 | 53 | ->end_of_fill; 54 | wait(end_of_read_write.triggered)// ждем окончания чтения и записи 55 | 56 | #10; // запись в память 57 | requset_write(); 58 | #30; 59 | requset_write(); 60 | #30; 61 | requset_write(); 62 | #30; 63 | $finish; 64 | end 65 | 66 | task fill_data(); 67 | @(posedge clk_i) 68 | we_i = '1; 69 | waddr_i = p; 70 | wdata_i = $urandom_range(0, 2**RAM_WIDTH - 1); 71 | #5; @(posedge clk_i) 72 | we_i = '0; 73 | endtask 74 | 75 | task requset_write(); 76 | @(posedge clk_i) 77 | waddr_i = $urandom_range(0, RAM_DEPTH - 1); 78 | we_i = '1; 79 | wdata_i = $urandom_range(0, 2**RAM_WIDTH - 1); 80 | #5; @(posedge clk_i) 81 | we_i = '0; 82 | endtask 83 | //------------------------------------------------- READ MODULE 84 | event end_of_read; 85 | initial begin 86 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 87 | #10; // чтение из памяти 88 | requset_read(); 89 | #30; 90 | requset_read(); 91 | #30; 92 | requset_read(); 93 | #30; 94 | ->end_of_read; 95 | end 96 | 97 | task requset_read(); 98 | @(posedge clk_i);#2.5; 99 | raddr_i = $urandom_range(0, RAM_DEPTH - 1); 100 | endtask 101 | //------------------------------------------------- Read and write at the same time 102 | event end_of_read_write; 103 | 104 | initial begin 105 | wait(end_of_read.triggered)// ждем окончания чтения 106 | #10; // запись в память и чтение одновременно 107 | read_and_write(); 108 | #30; 109 | read_and_write(); 110 | #30; 111 | read_and_write(); 112 | #30; 113 | ->end_of_read_write; 114 | end 115 | 116 | task read_and_write(); 117 | @(posedge clk_i) 118 | waddr_i = $urandom_range(0, RAM_DEPTH - 1); 119 | raddr_i = $urandom_range(0, RAM_DEPTH - 1); 120 | wdata_i = $urandom_range(0, 2**RAM_WIDTH - 1); 121 | we_i = '1; 122 | #5; @(posedge clk_i) 123 | we_i = '0; 124 | endtask 125 | endmodule 126 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/pll_typical_scheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Делитель 20 | Q 21 | 22 | 23 | 24 | Фазовый 25 | детектор 26 | ГУН 27 | Делитель 28 | N 29 | 30 | Делитель 31 | P 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Опорная 44 | частота 45 | Выходная 46 | частота 47 | 48 | Фильтр 49 | интегратор 50 | 51 | 52 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/03_bram_dp_simple/bram_dp_simple_1clk_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data () 2 | // затем чтение requset_read () 3 раза 3 | // затем чтение и запись read_and_write() 3 раза 4 | // затем просто запись requset_write () 3 раза 5 | 6 | module bram_dp_simple_1clk_tb(); 7 | localparam int RAM_WIDTH = 16; 8 | localparam int RAM_ADDR_BITS = 3; 9 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 10 | 11 | logic clk_i; 12 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_a_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_b_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_a_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_b_o; 16 | logic we_a_i; 17 | logic en_b_i; 18 | 19 | bram_dp_simple_1clk # ( 20 | .RAM_WIDTH ( RAM_WIDTH ), 21 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 22 | ) 23 | bram_dp_simple_1clk_inst ( 24 | .clk_i ( clk_i ), 25 | .addr_a_i ( addr_a_i ), 26 | .addr_b_i ( addr_b_i ), 27 | .data_a_i ( data_a_i ), 28 | .we_a_i ( we_a_i ), 29 | .en_b_i ( en_b_i ), 30 | .data_b_o ( data_b_o ) 31 | ); 32 | //------------------------------------------------- clk_i 33 | initial begin 34 | clk_i = 1'b0; 35 | forever begin 36 | clk_i = ~clk_i; #5; 37 | end 38 | end 39 | //------------------------------------------------- WRITE MODULE 40 | int p; 41 | event end_of_fill; 42 | 43 | initial begin 44 | #10; 45 | p = 0; 46 | we_a_i = '0; 47 | 48 | repeat(RAM_DEPTH)begin // заполнение памяти 49 | fill_data(); #5; 50 | p = p + 1; 51 | end 52 | 53 | ->end_of_fill; 54 | wait(end_of_read_write.triggered)// ждем окончания чтения и записи 55 | #10; 56 | requset_write(); // запись в память 57 | #30; 58 | requset_write(); 59 | #30; 60 | requset_write(); 61 | #30; 62 | $finish; 63 | end 64 | 65 | task fill_data(); 66 | @(posedge clk_i) 67 | we_a_i = '1; 68 | addr_a_i = p; 69 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 70 | #5; @(posedge clk_i) 71 | we_a_i = '0; 72 | endtask 73 | 74 | task requset_write(); 75 | @(posedge clk_i) 76 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 77 | we_a_i = '1; 78 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 79 | #5; @(posedge clk_i) 80 | we_a_i = '0; 81 | endtask 82 | //------------------------------------------------- READ MODULE 83 | event end_of_read; 84 | initial begin 85 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 86 | #10; // чтение памяти 87 | requset_read(); 88 | #30; 89 | requset_read(); 90 | #30; 91 | requset_read(); 92 | #30; 93 | ->end_of_read; 94 | end 95 | 96 | task requset_read(); 97 | @(posedge clk_i) 98 | en_b_i = 1'b1; 99 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 100 | #5; @(posedge clk_i); 101 | en_b_i = 1'b0; 102 | endtask 103 | //------------------------------------------------- Read and write at the same time 104 | event end_of_read_write; 105 | 106 | initial begin 107 | wait(end_of_read.triggered) // ждем окончания чтения 108 | #10; 109 | read_and_write(); // чтение и запись одновременно 110 | #30; 111 | read_and_write(); 112 | #30; 113 | read_and_write(); 114 | #30; 115 | ->end_of_read_write; 116 | end 117 | 118 | task read_and_write(); 119 | @(posedge clk_i) 120 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 121 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 122 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 123 | we_a_i = '1; 124 | en_b_i = '1; 125 | #5; @(posedge clk_i) 126 | en_b_i = '0; 127 | we_a_i = '0; 128 | endtask 129 | 130 | endmodule 131 | -------------------------------------------------------------------------------- /Other/exam_questions.md: -------------------------------------------------------------------------------- 1 | ### Внутренняя структура FPGA 2 | 1. Что такое FPGA? 3 | 2. Что такое LE? Из каких частей состоит простой LE? 4 | 3. Что такое LUT, зачем он нужен? 5 | 4. Какие режимы работы есть у LE? 6 | 5. Что такое Slice в Xilinx 7? 7 | 6. Как работают ресурсы маршрутизации в FPGA? 8 | 9 | ### DSP ячейки 10 | 7. Что такое DSP ячейка, зачем она нужна? 11 | 8. Что эффективнее использовать для выполнения операции умножения: LUT или DSP? Почему? 12 | 9. Какие составные части есть у DSP ячейки Xilinx 7? 13 | 10. Как можно реализовать умножение с накоплением на базе DSP ячейки? 14 | 11. Что такое SIMD? Зачем такой режим нужен в DSP ячейке? 15 | 12. Какой тип сброса может быть реализован в регистрах DSP ячейки Xilinx 7? 16 | 13. Что такое обнаружитель паттернов и зачем он может быть использован? 17 | 18 | ### LUTRAM и BRAM 19 | 14. Что такое LUTRAM? 20 | 15. Что такое BRAM? 21 | 16. Чем отличается LUTRAM от BRAM? 22 | 17. Что такое синхронное и асинхронное чтение из памяти? 23 | 18. Что такое byte enable? 24 | 19. Что такое инициализация памяти? 25 | 20. Что такое политика чтения No Change? 26 | 27 | ### Что такое политика чтения Read First? 28 | 21. Что такое политика чтения Write First? 29 | 22. Что такое однопортовая память? 30 | 23. Зачем может быть полезен дополнительный регистр на выходе чтения BRAM? 31 | 24. Что такое простая двухпортовая память (Simple Dual Port)? Чем она отличается от однопортовой? 32 | 25. Что такое настоящая двухпортовая память (True Dual Port)? Чем она отличается от однопортовой? 33 | 26. Что такое память с двумя тактовыми частотами? Как сделать такую память на базе двухпортовой памяти? 34 | 35 | ### Конвейеры и систолические массивы 36 | 27. Что такое критический путь? 37 | 28. Что такое конвейер в цифровой технике? 38 | 29. Что такое латентность конвейера? 39 | 30. Из чего складывается энергопотребление цифровой микросхемы? Опишите составляющие. 40 | 31. Что такое Clock gating? Какие виды Clock gating вы знаете? 41 | 32. Что такое free running регистры? 42 | 33. Зачем может быть полезен флаг валидности данных в конвейере? 43 | 34. Чем синхронный сброс отличается от асинхронного? 44 | 35. Почему в ASIC лучше использовать регистры без асинхронного сброса там, где это возможно? 45 | 36. Что такое систолический массив? Зачем он может применяться? 46 | 37. Что такое узел систолического массива? Как он работает? 47 | 38. Как происходит распространение данных и результатов вычислений в систолическом массиве? 48 | 49 | ### Шина AXI-Stream, Valid-Ready, Credit Flow control 50 | 39. Зачем нужен сигнал ready в интерфейсе valid-ready? 51 | 40. Что такое рукопожатие (handshake)? 52 | 41. Что такой обратное давление (backpressure)? 53 | 42. Какая проблема возникает с сигналом ready при соединении большого количества модулей в конвейер? 54 | 43. Какие способы развязки критического пути по backpressure вы знаете? Опишите их. 55 | 44. Что такое кредитный механизм? Для чего он нужен? Как он работает? 56 | 45. Что такое интерфейс AXI Stream? Чем он отличается от интерфейса valid-ready? 57 | 46. Какие сигналы есть в интерфейсе AXI Stream? 58 | 47. Объясните принцип разветвления потоков данных (fork) 59 | 48. Объясните принцип слияния потоков данных (join). Какие сложности возникают при слиянии потоков данных? 60 | 49. Что такое алгоритм арбитража? Какие алгоритмы арбитража вы знаете? Опишите их. 61 | 50. Что такое коммутатор? Из каких частей состоит коммутатор и как он построен? 62 | 63 | ### PLL, пересечение доменов тактовых частот 64 | 51. Что такое PLL? 65 | 52. Из каких компонентов состоит PLL? 66 | 53. Объясните принцип работы PLL? 67 | 54. На что влияют делители в цепи PLL? 68 | 55. Метастабильность, что это? 69 | 56. Можно ли полностью избежать явления метастабильности? 70 | 57. Какие есть способы пересечения частотных доменов одиночным сигналом? 71 | 58. Какими способами можно шину данных передать в другой частотный домен? 72 | 73 | ### APB 74 | 59. Дайте определение системной шины. Назначение системной шины. 75 | 60. Классификация системных шин. 76 | 61. Каким образом различаются контроллеры в адресном пространстве? Что такое базовый адрес контроллера? Что такое карта памяти (memory map)? 77 | 62. Системная шина APB. Каково назначение каждого из сигналов системной шины? 78 | 63. Системная шина APB. Изобразить цикл записи с задержкой. 79 | 64. Системная шина APB. Изобразить цикл чтения без задержки. 80 | -------------------------------------------------------------------------------- /Labs/06.AXI-Stream/examples/pow5_pipelined_valid.sv: -------------------------------------------------------------------------------- 1 | module pow5_pipelined_valid 2 | #( 3 | parameter int DATA_WIDTH = 8 4 | ) 5 | ( 6 | input logic clk_i, 7 | input logic rst_i, 8 | input logic [DATA_WIDTH-1:0] pow_data_i, 9 | input logic data_valid_i, 10 | output logic [(5*DATA_WIDTH)-1:0] pow_data_o, 11 | output logic data_valid_o 12 | ); 13 | 14 | 15 | logic [DATA_WIDTH-1:0] pow_input_ff; 16 | 17 | logic [(2*DATA_WIDTH)-1:0] pow_mul_stage_1; 18 | logic [(3*DATA_WIDTH)-1:0] pow_mul_stage_2; 19 | logic [(4*DATA_WIDTH)-1:0] pow_mul_stage_3; 20 | logic [(5*DATA_WIDTH)-1:0] pow_mul_stage_4; 21 | 22 | logic [(2*DATA_WIDTH)-1:0] pow_data_stage_1_ff; 23 | logic [(3*DATA_WIDTH)-1:0] pow_data_stage_2_ff; 24 | logic [(4*DATA_WIDTH)-1:0] pow_data_stage_3_ff; 25 | 26 | logic [DATA_WIDTH-1:0] pow_input_stage_1_ff; 27 | logic [DATA_WIDTH-1:0] pow_input_stage_2_ff; 28 | logic [DATA_WIDTH-1:0] pow_input_stage_3_ff; 29 | 30 | logic [(5*DATA_WIDTH)-1:0] pow_output_ff; 31 | 32 | 33 | logic input_valid_ff; 34 | logic data_valid_stage_1_ff; 35 | logic data_valid_stage_2_ff; 36 | logic data_valid_stage_3_ff; 37 | logic output_valid_ff; 38 | 39 | 40 | // "Valid" flags 41 | always_ff @ (posedge clk_i or posedge rst_i) 42 | if (rst_i) 43 | input_valid_ff <= '0; 44 | else 45 | input_valid_ff <= data_valid_i; 46 | 47 | always_ff @ (posedge clk_i or posedge rst_i) 48 | if (rst_i) begin 49 | data_valid_stage_1_ff <= '0; 50 | data_valid_stage_2_ff <= '0; 51 | data_valid_stage_3_ff <= '0; 52 | end 53 | else begin 54 | data_valid_stage_1_ff <= input_valid_ff; 55 | data_valid_stage_2_ff <= data_valid_stage_1_ff; 56 | data_valid_stage_3_ff <= data_valid_stage_2_ff; 57 | end 58 | 59 | always_ff @ (posedge clk_i or posedge rst_i) 60 | if (rst_i) 61 | output_valid_ff <= '0; 62 | else 63 | output_valid_ff <= data_valid_stage_3_ff; 64 | 65 | 66 | // Input data pipeline 67 | 68 | // Exercise: 1) remove unnecessary resets here to reduce ASIC area 69 | // 2) use clock gating to reduce pipeline power consumption 70 | 71 | always_ff @ (posedge clk_i or posedge rst_i) 72 | if (rst_i) 73 | pow_input_ff <= '0; 74 | else 75 | pow_input_ff <= pow_data_i; 76 | 77 | always_ff @ (posedge clk_i or posedge rst_i) 78 | if (rst_i) 79 | pow_input_stage_1_ff <= '0; 80 | else 81 | pow_input_stage_1_ff <= pow_input_ff; 82 | 83 | always_ff @ (posedge clk_i or posedge rst_i) 84 | if (rst_i) 85 | pow_input_stage_2_ff <= '0; 86 | else 87 | pow_input_stage_2_ff <= pow_input_stage_1_ff; 88 | 89 | always_ff @ (posedge clk_i or posedge rst_i) 90 | if (rst_i) 91 | pow_input_stage_3_ff <= '0; 92 | else 93 | pow_input_stage_3_ff <= pow_input_stage_2_ff; 94 | 95 | 96 | // Multiply numbers 97 | assign pow_mul_stage_1 = pow_input_ff * pow_input_ff; 98 | assign pow_mul_stage_2 = pow_data_stage_1_ff * pow_input_stage_1_ff; 99 | assign pow_mul_stage_3 = pow_data_stage_2_ff * pow_input_stage_2_ff; 100 | assign pow_mul_stage_4 = pow_data_stage_3_ff * pow_input_stage_3_ff; 101 | 102 | 103 | // Exercise: 1) remove unnecessary resets here to reduce ASIC area 104 | // 2) use clock gating to reduce pipeline power consumption 105 | 106 | always_ff @ (posedge clk_i or posedge rst_i) 107 | if (rst_i) 108 | pow_data_stage_1_ff <= '0; 109 | else 110 | pow_data_stage_1_ff <= pow_mul_stage_1; 111 | 112 | always_ff @ (posedge clk_i or posedge rst_i) 113 | if (rst_i) 114 | pow_data_stage_2_ff <= '0; 115 | else 116 | pow_data_stage_2_ff <= pow_mul_stage_2; 117 | 118 | always_ff @ (posedge clk_i or posedge rst_i) 119 | if (rst_i) 120 | pow_data_stage_3_ff <= '0; 121 | else 122 | pow_data_stage_3_ff <= pow_mul_stage_3; 123 | 124 | always_ff @ (posedge clk_i or posedge rst_i) 125 | if (rst_i) 126 | pow_output_ff <= '0; 127 | else 128 | pow_output_ff <= pow_mul_stage_4; 129 | 130 | 131 | assign pow_data_o = pow_output_ff; 132 | assign data_valid_o = output_valid_ff; 133 | 134 | endmodule 135 | -------------------------------------------------------------------------------- /Labs/05. Pipelines and Systolic arrays/examples/03_pow5_pipelined_valid/pow5_pipelined_valid.sv: -------------------------------------------------------------------------------- 1 | module pow5_pipelined_valid 2 | #( 3 | parameter DATA_WIDTH = 8 4 | ) 5 | ( 6 | input logic clk_i, 7 | input logic rst_i, 8 | input logic [DATA_WIDTH-1:0] pow_data_i, 9 | input logic data_valid_i, 10 | output logic [(5*DATA_WIDTH)-1:0] pow_data_o, 11 | output logic data_valid_o 12 | ); 13 | 14 | 15 | logic [DATA_WIDTH-1:0] pow_input_ff; 16 | 17 | logic [(2*DATA_WIDTH)-1:0] pow_mul_stage_1; 18 | logic [(3*DATA_WIDTH)-1:0] pow_mul_stage_2; 19 | logic [(4*DATA_WIDTH)-1:0] pow_mul_stage_3; 20 | logic [(5*DATA_WIDTH)-1:0] pow_mul_stage_4; 21 | 22 | logic [(2*DATA_WIDTH)-1:0] pow_data_stage_1_ff; 23 | logic [(3*DATA_WIDTH)-1:0] pow_data_stage_2_ff; 24 | logic [(4*DATA_WIDTH)-1:0] pow_data_stage_3_ff; 25 | 26 | logic [DATA_WIDTH-1:0] pow_input_stage_1_ff; 27 | logic [DATA_WIDTH-1:0] pow_input_stage_2_ff; 28 | logic [DATA_WIDTH-1:0] pow_input_stage_3_ff; 29 | 30 | logic [(5*DATA_WIDTH)-1:0] pow_output_ff; 31 | 32 | 33 | logic input_valid_ff; 34 | logic data_valid_stage_1_ff; 35 | logic data_valid_stage_2_ff; 36 | logic data_valid_stage_3_ff; 37 | logic output_valid_ff; 38 | 39 | 40 | // "Valid" flags 41 | always_ff @ (posedge clk_i or posedge rst_i) 42 | if (rst_i) 43 | input_valid_ff <= '0; 44 | else 45 | input_valid_ff <= data_valid_i; 46 | 47 | always_ff @ (posedge clk_i or posedge rst_i) 48 | if (rst_i) begin 49 | data_valid_stage_1_ff <= '0; 50 | data_valid_stage_2_ff <= '0; 51 | data_valid_stage_3_ff <= '0; 52 | end 53 | else begin 54 | data_valid_stage_1_ff <= input_valid_ff; 55 | data_valid_stage_2_ff <= data_valid_stage_1_ff; 56 | data_valid_stage_3_ff <= data_valid_stage_2_ff; 57 | end 58 | 59 | always_ff @ (posedge clk_i or posedge rst_i) 60 | if (rst_i) 61 | output_valid_ff <= '0; 62 | else 63 | output_valid_ff <= data_valid_stage_3_ff; 64 | 65 | 66 | // Input data pipeline 67 | 68 | // Exercise: 1) remove unnecessary resets here to reduce ASIC area 69 | // 2) use clock gating to reduce pipeline power consumption 70 | 71 | always_ff @ (posedge clk_i or posedge rst_i) 72 | if (rst_i) 73 | pow_input_ff <= '0; 74 | else 75 | pow_input_ff <= pow_data_i; 76 | 77 | always_ff @ (posedge clk_i or posedge rst_i) 78 | if (rst_i) 79 | pow_input_stage_1_ff <= '0; 80 | else 81 | pow_input_stage_1_ff <= pow_input_ff; 82 | 83 | always_ff @ (posedge clk_i or posedge rst_i) 84 | if (rst_i) 85 | pow_input_stage_2_ff <= '0; 86 | else 87 | pow_input_stage_2_ff <= pow_input_stage_1_ff; 88 | 89 | always_ff @ (posedge clk_i or posedge rst_i) 90 | if (rst_i) 91 | pow_input_stage_3_ff <= '0; 92 | else 93 | pow_input_stage_3_ff <= pow_input_stage_2_ff; 94 | 95 | 96 | // Multiply numbers 97 | assign pow_mul_stage_1 = pow_input_ff * pow_input_ff; 98 | assign pow_mul_stage_2 = pow_data_stage_1_ff * pow_input_stage_1_ff; 99 | assign pow_mul_stage_3 = pow_data_stage_2_ff * pow_input_stage_2_ff; 100 | assign pow_mul_stage_4 = pow_data_stage_3_ff * pow_input_stage_3_ff; 101 | 102 | 103 | // Exercise: 1) remove unnecessary resets here to reduce ASIC area 104 | // 2) use clock gating to reduce pipeline power consumption 105 | 106 | always_ff @ (posedge clk_i or posedge rst_i) 107 | if (rst_i) 108 | pow_data_stage_1_ff <= '0; 109 | else 110 | pow_data_stage_1_ff <= pow_mul_stage_1; 111 | 112 | always_ff @ (posedge clk_i or posedge rst_i) 113 | if (rst_i) 114 | pow_data_stage_2_ff <= '0; 115 | else 116 | pow_data_stage_2_ff <= pow_mul_stage_2; 117 | 118 | always_ff @ (posedge clk_i or posedge rst_i) 119 | if (rst_i) 120 | pow_data_stage_3_ff <= '0; 121 | else 122 | pow_data_stage_3_ff <= pow_mul_stage_3; 123 | 124 | always_ff @ (posedge clk_i or posedge rst_i) 125 | if (rst_i) 126 | pow_output_ff <= '0; 127 | else 128 | pow_output_ff <= pow_mul_stage_4; 129 | 130 | 131 | assign pow_data_o = pow_output_ff; 132 | assign data_valid_o = output_valid_ff; 133 | 134 | endmodule 135 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_2clk_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data () 2 | // затем чтение requset_read () 2 раза (1 для каждого случая) 3 | // затем запись requset_write () 2 раза (1 для каждого случая) 4 | 5 | module bram_dp_true_2clk_tb(); 6 | localparam int RAM_WIDTH = 16; 7 | localparam int RAM_ADDR_BITS = 3; 8 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 9 | 10 | logic clk_a_i; 11 | logic clk_b_i; 12 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_a_i; 13 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_b_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_a_i; 15 | logic [ RAM_WIDTH - 1 : 0 ] data_b_i; 16 | logic we_a_i; 17 | logic we_b_i; 18 | logic en_a_i; 19 | logic en_b_i; 20 | logic [ RAM_WIDTH - 1 : 0 ] data_a_o; 21 | logic [ RAM_WIDTH - 1 : 0 ] data_b_o; 22 | 23 | bram_dp_true_2clk # ( 24 | .RAM_WIDTH ( RAM_WIDTH ), 25 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 26 | ) 27 | bram_dp_true_2clk_inst ( 28 | .clk_a_i ( clk_a_i ), 29 | .clk_b_i ( clk_b_i ), 30 | .addr_a_i ( addr_a_i ), 31 | .addr_b_i ( addr_b_i ), 32 | .data_a_i ( data_a_i ), 33 | .data_b_i ( data_b_i ), 34 | .we_a_i ( we_a_i ), 35 | .we_b_i ( we_b_i ), 36 | .en_a_i ( en_a_i ), 37 | .en_b_i ( en_b_i ), 38 | .data_a_o ( data_a_o ), 39 | .data_b_o ( data_b_o ) 40 | ); 41 | //------------------------------------------------- clk 42 | initial begin 43 | clk_a_i = 1'b0; 44 | forever begin 45 | clk_a_i = ~clk_a_i; #5; 46 | end 47 | end 48 | 49 | initial begin 50 | clk_b_i = 1'b1; #2.5; 51 | forever begin 52 | clk_b_i = ~clk_b_i; #5; 53 | end 54 | end 55 | //------------------------------------------------- WRITE MODULE 56 | int p; 57 | event end_of_fill; 58 | 59 | initial begin 60 | #10; 61 | p = 0; 62 | we_a_i = '0; 63 | 64 | repeat(RAM_DEPTH/2)begin // заполнение памяти сразу 2 ячеек 65 | fill_data(); #5; 66 | p = p + 2; 67 | end 68 | 69 | ->end_of_fill; 70 | wait(end_of_read.triggered)// ждем окончания чтения 71 | #10; 72 | requset_write_a(); // запись в память 73 | #30; 74 | requset_write_b(); 75 | #30; 76 | $finish; 77 | end 78 | 79 | task fill_data(); 80 | @(posedge clk_a_i) 81 | addr_a_i = p; 82 | we_a_i = '1; 83 | en_a_i = '1; 84 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 85 | @(posedge clk_b_i) 86 | addr_b_i = p + 1; 87 | we_b_i = '1; 88 | en_b_i = '1; 89 | data_b_i = $urandom_range(0, 2**RAM_WIDTH - 1); 90 | @(posedge clk_a_i) 91 | we_a_i = '0; 92 | en_a_i = '0; 93 | @(posedge clk_b_i); 94 | en_b_i = '0; 95 | we_b_i = '0; 96 | endtask 97 | 98 | task requset_write_a(); 99 | @(posedge clk_a_i) 100 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 101 | we_a_i = '1; 102 | en_a_i = '1; 103 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 104 | #5; @(posedge clk_a_i) 105 | we_a_i = '0; 106 | en_a_i = '0; 107 | endtask 108 | 109 | task requset_write_b(); 110 | @(posedge clk_b_i) 111 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 112 | we_b_i = '1; 113 | en_b_i = '1; 114 | data_b_i = $urandom_range(0, 2**RAM_WIDTH - 1); 115 | #5; @(posedge clk_b_i) 116 | en_b_i = '0; 117 | we_b_i = '0; 118 | endtask 119 | //------------------------------------------------- READ MODULE 120 | event end_of_read; 121 | initial begin 122 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 123 | #10; // чтение памяти 124 | requset_read_a(); 125 | #30; 126 | requset_read_b(); 127 | #30; 128 | ->end_of_read; 129 | end 130 | 131 | task requset_read_a(); 132 | @(posedge clk_a_i) 133 | en_a_i = 1'b1; 134 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 135 | #5; @(posedge clk_a_i); 136 | en_a_i = 1'b0; 137 | endtask 138 | 139 | task requset_read_b(); 140 | @(posedge clk_b_i) 141 | en_b_i = 1'b1; 142 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 143 | #5; @(posedge clk_b_i); 144 | en_b_i = 1'b0; 145 | endtask 146 | 147 | endmodule 148 | -------------------------------------------------------------------------------- /Other/Vivado STA/README.md: -------------------------------------------------------------------------------- 1 | Для корректной работы последовательностных устройств предъявляются ряд требований. Информационный вход схемы должен оставаться стабильным в течение времени предустановки (tsetup) до прихода активного уровня фронта тактового сигнала и не должен изменяться в течение времени удержания (thold) после прихода активного уровня фронта тактового сигнала. (Рисунок 1) 2 | 3 | ![sh](./pic/sh.png) 4 | ##### Рисунок 1 Времена предустановки и удержания (tsetup и thold) ##### 5 | 6 | Последовательностные устройства можно условно представить в виде регистров, которые разделены между собой комбинационной логикой. (Рисунок 2) 7 | 8 | ![rg](./pic/sta.png) 9 | ##### Рисунок 2 Условное изображение последовательностных устройств ##### 10 | 11 | 12 | По фронту CLK данные защёлкиваются и попадают на выход Q1 . Далее они распространяются через блок комбинационной логики, и попадают на вход D2. Как показано на рисунке 3 сигнал на входе D2 принимает окончательное значение спустя максимальное время задержки распространения .Серые стрелки указывают минимальную задержку с учетом регистра R1 и комбинационной логики, синие - максимальную. Время tpd - это задержка на комбинационной логике 13 | 14 | ![delay](./pic/delay.png) 15 | ##### Рисунок 3 Временная диаграмма распространения данных между двумя триггерами ##### 16 | 17 | 18 | В итоге мы получаем два ограничения. Во-первых данные с выхода Q1 должны распространятся достаточно быстро, чтобы успеть дойти до входа D2 раньше фронта CLK. (tsetup). Во-вторых следующие данные с выхода Q1 должны распространятся достаточно медленно, чтобы по фронту CLK захватились предыдущие данные (thold). 19 | 20 | Допустим, что у нас в проекте есть .xdc файл следующего содержания: 21 | ``` 22 | create_clock -period 1.000 -name clk_i -waveform {0.000 0.500} -add [get_ports clk_i] 23 | 24 | ``` 25 | 26 | Этот файл задаёт частоту с периодом в 1 наносекунду, то есть это 1 ГГц. Это много и на практике достичь таких частот в FPGA трудно, если не невозможно. Для примера это как раз то, что нужно. 27 | 28 | STA проводит анализ tsetup и thold, опираясь на частоту(период), заданную в файле ограничений (constraints) проекта. В данном примере задан период в 1 нс. Результатом STA является значение Slack, **которое является разностью между периодом из файла ограничений ( то есть 1 нс ) и значением периода на котором проект работает без нарушений временных ограничений ( setup time и hold time)**. Так как период, заданный в ограничениях заведомо выбран малым, значения Slack будут получаться отрицательными. 29 | 30 | Для получения Slack нужно запустить имплементацию проекта (Рисунок 4). Имплементация проводится после синтеза, то есть после неё могут анализироваться задержки на логических элементах и трассировочных ресурсах 31 | 32 | 33 | ![impl](./pic/impl.png) 34 | ##### Рисунок 4 Запуск имплементации ##### 35 | 36 | 37 | После имплементации получим значение Slack для худшего критического пути. (Рисунок 5) В данном примере он равен -9,607. 38 | 39 | Сейчас важно навсегда запомнить следующее: 40 | 41 | * **Если Slack отрицательный и красный, то дизайн не в состоянии работать на требуемой тактовой частоте** 42 | * Если вы зашьёте такой дизайн в реальную FPGA, то он может даже с виду заработать (особенно, если Slack совсем немного "не дотянул" до положительного), но ваш дизайн может сломаться в произвольный момент, начать работать некорректно. Хорошей аналогией тут может являться разгон процессора или видеокарты: оно может работать исправно месяцами, но в определенный (самый неподходящий, конечно же) момент зависнет. 43 | * В таком случае вам, как разработчику, необходимо оптимизировать дизайн (устранить критические пути) или уменьшить тактовую частоту. 44 | 45 | ![wns](./pic/wns.png) 46 | ##### Рисунок 5 Значение Slack для худшего критического пути ##### 47 | 48 | 49 | Данная информация поможет обнаружить слабые места дизайна. Набор действий сводится к внесению изменений в проект и анализу изменения Slack. Кликнув по значению Slack для худшего критического пути появится информация о Slack для всех критических путей. (Рисунок 6) 50 | 51 | ![paths](./pic/paths.png) 52 | ##### Рисунок 6 Значение Slack для всех критических путей ##### 53 | 54 | Удобной опцией является просмотр критического пути на уровне структурной схемы. Для этого находясь в окне просмотра значений Slack для всех критических путей (Рисунок 6), кликните на интересующий Вас критический путь и нажмите на клавишу F4 . В данном примере мы кликнули на критический путь Path1 (Рисунок 7). 55 | 56 | 57 | ![f4](./pic/f4.png) 58 | ##### Рисунок 7 Просмотр критического пути на уровне структурной схемы ##### 59 | 60 | 61 | Сделаем расчёт частоты , на которой проект заработает без нарушений временных ограничений. Для этого нужно из периода тактовой частоты (значение из файла ограничений .xdc ) вычесть Slack для худшего критического пути (-9,607нс) и найти обратную величину получившегося значения: 62 | 63 | ``` 1/(1нс - (-9,607нс)) = 94,277 МГц ``` 64 | 65 | В данном примере в .xdc файле задана тактовая частота с периодом в 1 нс. 66 | -------------------------------------------------------------------------------- /Labs/04. LUTRAM BRAM/examples/04_bram_dp_true/bram_dp_true_1clk_tb.sv: -------------------------------------------------------------------------------- 1 | // в модуле сначало идет заполнение памяти fill_data () 2 | // затем чтение requset_read () 3 раза (1 для каждого случая) 3 | // затем запись requset_write () 3 раза (1 для каждого случая) 4 | 5 | module bram_dp_true_1clk_tb(); 6 | localparam int RAM_WIDTH = 16; 7 | localparam int RAM_ADDR_BITS = 3; 8 | localparam int RAM_DEPTH = 2**RAM_ADDR_BITS; 9 | 10 | logic clk_i; 11 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_a_i; 12 | logic [ RAM_ADDR_BITS - 1 : 0 ] addr_b_i; 13 | logic [ RAM_WIDTH - 1 : 0 ] data_a_i; 14 | logic [ RAM_WIDTH - 1 : 0 ] data_b_i; 15 | logic we_a_i; 16 | logic we_b_i; 17 | logic en_a_i; 18 | logic en_b_i; 19 | logic [ RAM_WIDTH - 1 : 0 ] data_a_o; 20 | logic [ RAM_WIDTH - 1 : 0 ] data_b_o; 21 | 22 | bram_dp_true_1clk # ( 23 | .RAM_WIDTH ( RAM_WIDTH ), 24 | .RAM_ADDR_BITS ( RAM_ADDR_BITS ) 25 | ) 26 | bram_dp_true_1clk_inst ( 27 | .clk_i ( clk_i ), 28 | .addr_a_i ( addr_a_i ), 29 | .addr_b_i ( addr_b_i ), 30 | .data_a_i ( data_a_i ), 31 | .data_b_i ( data_b_i ), 32 | .we_a_i ( we_a_i ), 33 | .we_b_i ( we_b_i ), 34 | .en_a_i ( en_a_i ), 35 | .en_b_i ( en_b_i ), 36 | .data_a_o ( data_a_o ), 37 | .data_b_o ( data_b_o ) 38 | ); 39 | //------------------------------------------------- clk_i 40 | initial begin 41 | clk_i = 1'b0; 42 | forever begin 43 | clk_i = ~clk_i; #5; 44 | end 45 | end 46 | //------------------------------------------------- WRITE MODULE 47 | int p; 48 | event end_of_fill; 49 | 50 | initial begin 51 | #10; 52 | p = 0; 53 | we_a_i = '0; 54 | 55 | repeat(RAM_DEPTH/2)begin // заполнение памяти сразу 2 ячеек 56 | fill_data(); #5; 57 | p = p + 2; 58 | end 59 | 60 | ->end_of_fill; 61 | wait(end_of_read.triggered)// ждем окончания чтения 62 | #10; 63 | requset_write_a(); // запись в память 64 | #30; 65 | requset_write_b(); 66 | #30; 67 | requset_write_both(); 68 | #30 69 | $finish; 70 | end 71 | 72 | task fill_data(); 73 | @(posedge clk_i) 74 | addr_a_i = p; 75 | we_a_i = '1; 76 | en_a_i = '1; 77 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 78 | if(addr_a_i < RAM_DEPTH + 2)begin 79 | addr_b_i = addr_a_i + 1; 80 | we_b_i = '1; 81 | en_b_i = '1; 82 | data_b_i = $urandom_range(0, 2**RAM_WIDTH - 1); 83 | end 84 | #5; @(posedge clk_i) 85 | we_a_i = '0; 86 | en_a_i = '0; 87 | en_b_i = '0; 88 | we_b_i = '0; 89 | endtask 90 | 91 | task requset_write_both(); 92 | @(posedge clk_i) 93 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 94 | we_a_i = '1; 95 | en_a_i = '1; 96 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 97 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 98 | if(addr_b_i == addr_a_i) 99 | addr_b_i = addr_b_i + 1; 100 | we_b_i = '1; 101 | en_b_i = '1; 102 | data_b_i = $urandom_range(0, 2**RAM_WIDTH - 1); 103 | #5; @(posedge clk_i) 104 | en_a_i = '0; 105 | en_b_i = '0; 106 | we_a_i = '0; 107 | we_b_i = '0; 108 | endtask 109 | 110 | task requset_write_a(); 111 | @(posedge clk_i) 112 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 113 | we_a_i = '1; 114 | en_a_i = '1; 115 | data_a_i = $urandom_range(0, 2**RAM_WIDTH - 1); 116 | #5; @(posedge clk_i) 117 | en_a_i = '0; 118 | we_a_i = '0; 119 | endtask 120 | 121 | task requset_write_b(); 122 | @(posedge clk_i) 123 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 124 | we_b_i = '1; 125 | en_b_i = '1; 126 | data_b_i = $urandom_range(0, 2**RAM_WIDTH - 1); 127 | #5; @(posedge clk_i) 128 | en_b_i = '0; 129 | we_b_i = '0; 130 | endtask 131 | //------------------------------------------------- READ MODULE 132 | event end_of_read; 133 | initial begin 134 | wait(end_of_fill.triggered) // ждем окончания заполнения памяти 135 | #10; // чтение памяти 136 | requset_read_a(); 137 | #30; 138 | requset_read_b(); 139 | #30; 140 | requset_read_both(); 141 | #30; 142 | ->end_of_read; 143 | end 144 | 145 | task requset_read_both(); 146 | @(posedge clk_i) 147 | en_a_i = 1'b1; 148 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 149 | en_b_i = 1'b1; 150 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 151 | #5; @(posedge clk_i); 152 | en_a_i = 1'b0; 153 | en_b_i = 1'b0; 154 | endtask 155 | 156 | task requset_read_a(); 157 | @(posedge clk_i) 158 | en_a_i = 1'b1; 159 | addr_a_i = $urandom_range(0, RAM_DEPTH - 1); 160 | #5; @(posedge clk_i); 161 | en_a_i = 1'b0; 162 | endtask 163 | 164 | task requset_read_b(); 165 | @(posedge clk_i) 166 | en_b_i = 1'b1; 167 | addr_b_i = $urandom_range(0, RAM_DEPTH - 1); 168 | #5; @(posedge clk_i); 169 | en_b_i = 1'b0; 170 | endtask 171 | 172 | endmodule 173 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/flag_sync_fail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | D 29 | Q 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | D 41 | Q 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | clkA 57 | clkB 58 | flagA 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | D 69 | Q 70 | 71 | 72 | flagB 73 | 74 | 75 | 76 | 77 | 78 | 79 | 82 | 84 | 85 | 86 | clkA 87 | clkB 88 | flagA 89 | 90 | flagB 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/fifo_normal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Memory 27 | cell 28 | 29 | 30 | 31 | 32 | Write 33 | counter 34 | 35 | 36 | 37 | 38 | 39 | Read 40 | counter 41 | 42 | 43 | 44 | 45 | 46 | Full 47 | flag 48 | 49 | 50 | 51 | 52 | 53 | Empty 54 | flag 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Write Data 154 | Read Data 155 | Write 156 | Signal 157 | Read 158 | Signal 159 | 160 | 161 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/ff2_sync.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | D 30 | Q 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | D 42 | Q 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | clkA 58 | clkB 59 | dat 60 | datA 61 | dFF1 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | D 72 | Q 73 | 74 | 75 | datB 76 | 77 | 78 | 79 | 80 | 81 | 85 | Logic 86 | 87 | 88 | 89 | 92 | 94 | 95 | 96 | 97 | clkA 98 | clkB 99 | datA 100 | dFF1 101 | 102 | datB 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/flag_sync_noloop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | clkA 25 | clkB 26 | flagA 27 | 28 | flagB 29 | 32 | 33 | datA 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | D 65 | Q 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | clkA 75 | clkB 76 | flagA 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | D 93 | Q 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | D 105 | Q 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | D 117 | Q 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | flagB 133 | 134 | 135 | 136 | 137 | datA 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /Labs/02. LUT and FF/README.md: -------------------------------------------------------------------------------- 1 | # Лабораторная работа 2. Таблицы истинности LUT и FF. 2 | 3 | Данная лабораторная работа посвящена низкоуровневому проектированию логики для FPGA Xilinx 7. Не то, чтобы в этом было много практического смысла, но если мы можем, то почему бы и нет? 4 | 5 | ## Подготовка к лабораторной работе 6 | * Вам необходимо прослушать первую половину лекции о внутренней структуре FPGA ([Запись на YouTube](https://www.youtube.com/watch?v=fdJiGdp5eVc)) 7 | 8 | Xilinx Vivado предоставляет возможность описывать логику с использованием так называемых примитивов. Давайте мы условимся называть в этой лабораторной работе примитивом "вшитый в Vivado" модуль, который вы можете подключать в своём дизайне и использовать. Если использовать более корректную терминологию, то это библиотечные элементы, из которых в итоге САПР собирает ваш дизайн в процессе синтеза. 9 | 10 | Xilinx прилагает [хорошую документацию к своим библиотечным элементам](https://docs.xilinx.com/v/u/2020.1-English/ug953-vivado-7series-libraries). Настоятельно рекомендую отвлечься от данного текста и потратить несколько минут на ознакомление с документом. В частности, стоит по диагонали просмотреть страницы 259-588, там на самом деле можно найти очень много интересного, особенно, если вы внимательно и целиком смотрели лекцию вживую или в записи. 11 | 12 | ### Примитивы LUT 13 | Для нас сейчас наиболее интересны примитивы LUT1-LUT6. Они позволяют использовать соответствующие элементы логических ячеек FPGA. При этом важно понимать, что в семействе Xilinx 7 физически существуют либо LUT6, либо LUT5 с двумя выходными сигналами, соответственно, LUT с меньшим числом входов будут реализованы на существующих ресурсах, при этом некоторые входы LUT5/LUT6 окажутся незадействованными. 14 | 15 | Давайте рассмотрим пример использования LUT6. Этот примитив имеет один параметр `INIT` шириной 64 бита. По сути это таблица истинности LUT'a. Нулевой бит соответствует значению выхода `O` при входном векторе `6'b000000`. 16 | Бит 63 соответствует значению выхода `O` при входном векторе `6'b111111`. 17 | 18 | ```verilog 19 | // LUT6: 6-input Look-Up Table with general output 20 | // 7 Series 21 | // Xilinx HDL Language Template, version 2020.1 22 | LUT6 #( 23 | .INIT(64'h0000000000000000) // Specify LUT Contents 24 | ) LUT6_inst ( 25 | .O(O), // LUT general output 26 | .I0(I0), // LUT input 27 | .I1(I1), // LUT input 28 | .I2(I2), // LUT input 29 | .I3(I3), // LUT input 30 | .I4(I4), // LUT input 31 | .I5(I5) // LUT input 32 | ); 33 | // End of LUT6_inst instantiation 34 | ``` 35 | 36 | ### Примитив CARRY4 37 | 38 | Другим интересным примитивом является цепочка переноса CARRY4. По сути этот примитив предоставляет нам доступ к цепочки переноса в рамках одного Slice. 39 | 40 | ![carry4](pic/carry4.png) 41 | 42 | Cхема выглядит пугающе и непонятно, особенно странным выглядит нижний мультиплексор, которым мы с первого взгляда не можем управлять. Всё становится значительно проще, если взглянуть на [поведенческую модель этого примитива](https://github.com/Xilinx/XilinxUnisimLibrary/blob/master/verilog/src/unisims/CARRY4.v): 43 | 44 | ```verilog 45 | module CARRY4 46 | ( 47 | output [3:0] CO, 48 | output [3:0] O, 49 | 50 | input CI, 51 | input CYINIT, 52 | input [3:0] DI, 53 | input [3:0] S 54 | ); 55 | 56 | wire CI_in; 57 | wire CYINIT_in; 58 | 59 | assign CI_in = (CI !== 1'bz) && CI; // rv 0 60 | assign CYINIT_in = (CYINIT !== 1'bz) && CYINIT; // rv 0 61 | 62 | // begin behavioral model 63 | 64 | wire [3:0] CO_fb; 65 | assign CO_fb = {CO[2:0], CI_in || CYINIT_in}; 66 | assign O = S ^ CO_fb; 67 | assign CO = (S & CO_fb) | (~S & DI); 68 | 69 | endmodule 70 | ``` 71 | С помощью этого примитива можно реализовать быстрые цепочки переноса для арифметических операций. 72 | 73 | * Сигналы `CI_in` и `CYINIT_in` отвечают за входной перенос сумматора, причем входной перенос формируется как логическое "ИЛИ" между двумя сигналами, и можно использовать один из них. Предлагается использовать `CI_in`. 74 | * Сигнал `CO_fb` представляет из себя непосредственно биты переноса. 0 бит это входной перенос, а 3 бит будет являться выходным переносом для 4-бит сумматора. 75 | 76 | 77 | Давайте рассмотрим работу цепочки переноса в сумматоре. Ниже представлена знакомая картинка из курса АПС c однобитным сумматором. 78 | 79 | ![adder](pic/adder.jpg) 80 | 81 | Мы сразу видим несколько аналогий: 82 | * Сигнал `s` в сумматоре эквивалентен сигналу `O` в примитиве CARRY4 83 | * Сигнал `cout` в сумматоре логически эквивалентен сигналу `CO` в примитиве CARRY4 84 | * Сигнал `cin` эквивалентен сигналу `CI_in` в CARRY4 85 | * Сигнал `g` эквивалентен `DI` в CARRY4 86 | * Сигнал `p` эквивалентен `S` в CARRY4 87 | 88 | Таким образом, чтобы построить сумматор с использованием CARRY4, необходимо сформировать сигналы `CI_in`, `DI` и `S` по аналогии с сигналами `cin`, `g` и `p` в полном сумматоре. 89 | 90 | ### Примитивы D триггеров 91 | 92 | Последним типом рассмотренных примитивов будут D-триггеры. 93 | * FDCE - D-триггер с сигналом Clock Enable и асинхронным сбросом 94 | * FDPE - D-триггер с сигналом Clock Enable и асинхронным возведением (как сброс, но в 1 вместо 0) 95 | * FDRE - D-триггер с сигналом Clock Enable и синхронным сбросом 96 | * FDSE - D-триггер с сигналом Clock Enable и синхронным возведением 97 | 98 | При рассмотрении данных примитивов нужно помнить, что они на самом деле реализуют разные режимы функционирования одних и тех же D-триггеров, которые физически присутствуют в FPGA. 99 | 100 | Использование данных примитивов не представляет существенной сложности, в случае необходимости обратитесь к документации за объяснением логики работы, примерами подключения и таблицами истинности. 101 | 102 | Также вскользь стоит упомянуть наличие защелок, для которых присутствуют примитивы LDCE и LDPE. 103 | 104 | > Обратите внимание на то, что такие примитивы D-триггеров при моделировании не запоминают данные в течение первых ~100 наносекунд, это нормально и должно быть так. Вы можете подавать данные на них не сразу, а к моменту, когда они "проснутся". 105 | 106 | ## Задания лабораторной работы 107 | 108 | **Часть 1: Реализовать комбинаторную логику согласно варианту индивидуального задания. Написать простой testbench на "initial" блоках и проверить выполнение задания.** 109 | 110 | 0. Реализовать функцию y[3:0] = a[3:0] ^ (b[3:0] | c[3:0]) с помощью примитивов LUT 111 | 1. Реализовать функцию y[3:0] = a[3:0] & (~c[3:0]) с помощью примитивов LUT 112 | 2. Реализовать функцию y[3:0] = a[3:0] - b[3:0] с использованием примитива цепочки переноса CARRY4 113 | 3. Реализовать функцию y[3:0] = (~a[3:0]) | (~c[3:0]) с помощью примитивов LUT 114 | 4. Реализовать функцию y[3:0] = a[3:0] & b[3:0] & c[3:0] с помощью примитивов LUT 115 | 5. Реализовать функцию y[3:0] = a[3:0] | b[3:0] | c[3:0] с помощью примитивов LUT 116 | 6. Реализовать функцию y[3:0] = a[3:0] ^ b[3:0] ^ (~c[3:0]) с помощью примитивов LUT 117 | 7. Реализовать функцию y[3:0] = a[3:0] + b[3:0] с использованием примитива цепочки переноса CARRY4 118 | 119 | Номер индивидуального варианта вычисляется как остаток от деления вашего номера в группе на 8. 120 | 121 | **Часть 2: Реализуйте запоминание данных с помощью одного из примитивов D-триггера. Написать простой testbench на "initial" блоках и проверить выполнение задания.** 122 | 123 | 0. Реализуйте запоминание результата выполнения первой части задания с помощью примитива FDCE 124 | 1. Реализуйте запоминание результата выполнения первой части задания с помощью примитива FDPE 125 | 2. Реализуйте запоминание результата выполнения первой части задания с помощью примитива FDRE 126 | 3. Реализуйте запоминание результата выполнения первой части задания с помощью примитива FDSE 127 | 128 | Номер индивидуального варианта вычисляется как остаток от деления вашего номера в группе на 4. 129 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/metastability.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | D 34 | Q 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | D 46 | Q 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | clkA 62 | clkB 63 | dat 64 | datA 65 | datB 66 | 67 | 68 | 69 | 70 | 71 | 73 | 75 | 76 | 77 | 78 | clkA 79 | clkB 80 | 81 | datA 82 | datB 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | Частоты clkA и 97 | clkB являются 98 | асинхронными 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 131 | 132 | Изменение 133 | значения 134 | 135 | 136 | 137 | 139 | 140 | 141 | 144 | 145 | Период 146 | метастабильности 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/fifo_async.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Write Clock Domain 33 | Read Clock Domain 34 | Metastability 35 | region 36 | 37 | 38 | 39 | 40 | Memory 41 | cell 42 | 43 | 44 | 45 | 46 | Write 47 | counter 48 | 49 | 50 | 51 | 52 | 53 | Read 54 | counter 55 | 56 | 57 | 58 | 59 | 60 | Full 61 | flag 62 | 63 | 64 | 65 | 66 | 67 | Empty 68 | flag 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | Write Data 136 | Read Data 137 | Write 138 | Signal 139 | Read 140 | Signal 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | gray 169 | code 170 | 171 | 172 | 173 | 2FF 174 | sync 175 | 176 | 177 | 178 | gray 179 | code 180 | 181 | 182 | 183 | 2FF 184 | sync 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/graycode_sync.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | clkA 29 | clkB 30 | flagA 31 | 32 | flagB 33 | 36 | 37 | datA 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | clkA 85 | 86 | 87 | dataI 88 | clkB 89 | 90 | dataO 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | D 101 | Q 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | D 136 | Q 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | D 168 | Q 169 | 170 | 171 | 172 | 173 | GrayEncoder 174 | 175 | GrayDecoder 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /Labs/01. Tcl/README.md: -------------------------------------------------------------------------------- 1 | # Лабораторная работа 1. Язык Tcl. 2 | 3 | ## Что такое Tcl 4 | ![../../pic/Labs/01_tcl/tcl.png](pic/tcl.png) 5 | 6 | * Tcl (от англ. Tool Command Language — «командный язык инструментов») — скриптовый язык высокого уровня 7 | 8 | * Tcl де-факто является языком автоматизации и интеграции во всех ведущих программных пакетах разработки микросхем (ПЛИС и ASIC) 9 | 10 | ## Зачем нужен tcl нам? 11 | 12 | * Tcl полезен для автоматизированного создания проекта из исходных кодов 13 | * Tcl может использоваться для создания сценариев синтеза и моделирования в САПР 14 | * Tcl позволяет работать с САПР в командной строке, без графического интерфейса пользователя 15 | * В частности, поддержка языка Tcl встроена в Vivado 16 | 17 | ## Подготовка к выполнению лабораторной работы 18 | * Создайте в Vivado проект "demoproject" (для вашего удобства создавайте его в отдельной папке, отметив галочку "Create project subdirectory") 19 | * Добавьте в этот проект RTL файлы [demo.v](./demoproject/rtl/demo.sv) и [demo_wrapper_nexys_a7.v](./demoproject/rtl/demo_wrapper_nexys_a7.sv) 20 | * Добавьте в проект файл тестбенча [tb_demo.v](./demoproject/tb/tb_demo.sv) 21 | * Добавьте в проект xdc-файл [Nexys-A7-100T-Master.xdc](./demoproject/xdc/Nexys-A7-100T-Master.xdc) 22 | 23 | > Не забудьте снять галочку «Copy sources into project» 24 | 25 | ![alt text](pic/tcl_add.png) 26 | 27 | Если вы не помните как создавать проекты, то обратитесь к 28 | [материалам АПС с прошлого семестра](https://github.com/MPSU/APS/tree/master/Vivado%20Basics). 29 | 30 | ## Экспорт скрипта для автоматизированного создания проекта в Vivado 31 | 32 | Давайте теперь мы создадим свой первый Tcl скрипт. Этот скрипт будет сгенерирован Vivado и будет предназначаться для восстановления проекта. Затем мы будем менять и дополнять этот скрипт. 33 | 34 | Используйте пункт меню «File > Project > Write Tcl» 35 | 36 | ![alt text](pic/tcl2.png) 37 | 38 | В появившемся окне нужно указать путь до tcl скрипта, который будет сгенерирован Vivado. 39 | 40 | > Убедитесь, что в этом окне все галочки не отмечены. 41 | 42 | ![alt text](pic/tcl3.png) 43 | 44 | 45 | Пусть это будет файл «build_project.tcl» в директории «demoproject» 46 | 47 | ![alt text](pic/tcl4.png) 48 | 49 | После нажатия на «OK» будет создан tcl скрипт 50 | 51 | ![alt text](pic/tcl5.png) 52 | 53 | Давайте теперь проверим созданный скрипт. Смело удаляем созданный вами проект (но файлы исходников не трогаем!). 54 | 55 | Теперь запустим Tcl скрипт. 56 | Для этого нужно выполнить в терминале вашей ОС следующие команды: 57 | 58 | Для windows: 59 | ``` 60 | call C:\Xilinx\Vivado\2019.2\settings64.bat 61 | vivado -mode=batch -nojournal -nolog -source build_project.tcl 62 | ``` 63 | 64 | Для Unix-подобного: 65 | ``` 66 | /tools/Xilinx/Vivado/2019.2/settings64.sh 67 | vivado -mode batch -nojournal -nolog -source build_project.tcl 68 | ``` 69 | 70 | Соответственно, путь до `settings64` вам необходимо указать с учетом того, где установлена Vivado. 71 | 72 | Если вы в процессе нигде не допустили ошибку, то проект восстановится с использованием Tcl файла, можно открыть его и убедиться в том, что это тот же самый проект. 73 | 74 | ## Подсматриваем за Vivado с целью писать Tcl скрипты 75 | 76 | > Хорошо, мы создали скрипт и он даже заработал. А что дальше? Как писать эти ваши Tcl? У меня есть книжка "Python для чайников", но для Tcl что-то такое не встречалось. Во всяком случае, на полке бестселлеров такое точно не найти. 77 | 78 | Приведенная вымышленная цитата вымышленного студента на самом деле рано или поздно возникает у каждого человека, который хоть немного копнёт тему с Tcl. Давайте разбираться и запоминать полезные советы. 79 | 80 | Прежде всего, необходимо понять, из чего состоит синтаксис языка Tcl в конкретной САПР, а состоит он из двух частей: 81 | * Базовый синтаксис языка 82 | * Дополнительные функции, добавленные разработчиком САПР для работы с ней 83 | 84 | То есть важно понимать, что Tcl представляет из себя простой язык, он содержит базовый инструментарий для написания программ и не включает конструкции "добавь файл исходного кода в проект" или "запусти моделирование". Такие конструкции дополнительно добавляются разработчиком каждой конкретной САПР, и, как правило, эти конструкции не совместимы между САПР разных производителей. Все велосипедят своё, самое лучшее и не имеющее аналогов. 85 | 86 | Хорошо, с этим разобрались, есть база и есть дополнения САПР. Где можно почитать про это всё? 87 | * Трудно найти лучшее место с информацией про базовые конструкции Tcl, чем [oфициальный мануал с примерами](https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html). 88 | * За информацией про функции САПР можно обратиться [непосредственно к документации на саму САПР](https://docs.xilinx.com/v/u/2019.2-English/ug835-vivado-tcl-commands). 89 | 90 | Давайте не будем обманывать ни себя, ни преподавателя. В процессе выполнения лабораторной работы вряд-ли кто-то станет вдумчиво читать многотомную документацию на английском техническом языке. Запомните, что тут есть ссылки на документацию, которая вам может очень сильно помочь уже в инженерной практике, и будем идти дальше. 91 | 92 | На практике достаточно удобно бывает "подсматривать" за САПР и таким образом находить Tcl команды для интересующих нас действий. 93 | 94 | Рассмотрим этот процесс на примере Vivado: 95 | 96 | ![alt text](pic/tcl6.png) 97 | 98 | * В нижней части окна Vivado есть вкладка "Tcl Console" 99 | * Эта вкладка интересна нам по нескольким причинам: 100 | * Прежде всего, это консоль, куда мы можем вбивать свои команды 101 | * Также, в этой консоли появляются вызванные команды (синий шрифт) и логи (черный шрифт) 102 | * Любопытный читатель наверняка уже замечал, что в этом окне волшебным образом появляются команды, которые он сам не печатал. Разгадка проста: **"под капотом" Vivado работает так, что почти любое действие в графическом интерфейсе вызывает выполнение какой-то Tcl команды в консоли**. 103 | * Этим мы можем и непременно будем пользоваться сегодня. 104 | 105 | Например, если нажать кнопку "Run Synthesis", в Tcl консоли появится следующий набор команд: 106 | 107 | ```tcl 108 | update_compile_order -fileset sources_1 109 | reset_run synth_1 110 | launch_runs synth_1 -jobs 4 111 | ``` 112 | 113 | Ещё одной полезной командой (которая пригодится вам для выполнения задания лабораторной работы) является `start_gui`. Фактически, эта команда открывает окно графического интерфейса Vivado. 114 | 115 | Попробуйте теперь дописать в конец скрипта создания проекта следующий фрагмент кода: 116 | 117 | ```tcl 118 | start_gui 119 | update_compile_order -fileset sources_1 120 | reset_run synth_1 121 | launch_runs synth_1 -jobs 4 122 | ``` 123 | 124 | Закройте Vivado, удалите проект и запустите скрипт заново. В случае успеха вы увидите, как у вас открылось окно Vivado и начался синтез проекта. 125 | 126 | Для выполнения некоторых вариантов вам может понадобиться команда `wait_on_run`. В Vivado команда `launch_runs` не является блокирующей, то есть интерпретатор Tcl начинает выполнять команды далее, не дожидаясь окончания, например, синтеза. В общем случае, в этом нету ничего плохого, но бывают ситуации, когда нам необходимы результаты выполнения `launch_runs` – в таком случае скрипт завершится с ошибкой. Пример использования `wait_on_run` показан ниже: 127 | 128 | ```tcl 129 | launch_runs synth_1 -jobs 4 130 | wait_on_run synth_1 131 | ``` 132 | 133 | > В Vivado, начиная с версии 2021.2, команда `wait_on_run` была переименована в `wait_on_runs`. В то же время, `wait_on_run` на данный момент ещё работает в режиме обратной совместимости. Если вы работаете в свежей версии Vivado, то лучше используйте `wait_on_runs`. 134 | 135 | Теперь вы знаете всё, что нужно для выполнения задания. 136 | 137 | # Задание лабораторной работы 138 | * Откройте созданный скрипт в редакторе, прочитайте его, выделите основные секции и попробуйте объяснить для себя смысл максимально большого количества строк в нём 139 | * Найдите в скрипте места, где добавляются все файлы проекта (rtl, tb и xdc) 140 | * Найдите в скрипте место, где выбирается part number микросхемы FPGA 141 | 142 | Индивидуальные задания: 143 | 144 | 0. Модифицировать скрипт так, чтобы после создания проекта запускалось моделирование на 100 мкс (с графическим интерфейсом) 145 | 1. Модифицировать скрипт так, чтобы после создания проекта открывалось окно RTL Analysis > Schematic со схемой проекта (с графическим интерфейсом, используйте команду `show_schematic`) 146 | 2. Модифицировать скрипт так, чтобы после создания проекта запускался синтез, а затем открывалось окно Synthesis > Schematic со схемой проекта (с графическим интерфейсом, используйте команду `show_schematic`) 147 | 3. Модифицировать скрипт так, чтобы после создания проекта запускался синтез, имплементация, а затем открывалось окно Implementation > Report Utilisation (с графическим интерфейсом) 148 | 4. Модифицировать скрипт так, чтобы после создания проекта началась генерация bitstream, а затем автоматически прошилась заранее подключенная к компьютеру отладочная плата (не запуская графический интерфейс) 149 | 150 | 151 | Номер индивидуального варианта вычисляется как остаток от деления вашего номера в группе на 5. 152 | -------------------------------------------------------------------------------- /Labs/07. PLL and CDC/pic/flag_sync_loop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | clkA 24 | clkB 25 | flagA 26 | 27 | flagB 28 | 31 | busy 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | D 69 | Q 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | clkA 79 | clkB 80 | flagA 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | D 97 | Q 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | D 109 | Q 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | D 121 | Q 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | flagB 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | D 150 | Q 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | D 162 | Q 163 | 164 | 165 | 166 | busy 167 | 168 | 169 | 170 | 171 | clkA 172 | 173 | 174 | 175 | 176 | --------------------------------------------------------------------------------