From 00b07d114fbe38ca9e46fdee197f6c7b72abfc56 Mon Sep 17 00:00:00 2001 From: Nikolay Puzanov Date: Tue, 2 Feb 2021 19:09:52 +0300 Subject: [PATCH] Initial commit --- README.md | 5 + cmod-a7-vivado/.dir-locals.el | 5 + cmod-a7-vivado/cmod-a7.xdc | 31 + cmod-a7-vivado/cmod_a7.sv | 54 + cmod-a7-vivado/ip/README.md | 1 + cmod-a7-vivado/ip/ila.xci | 3250 ++++++++++++++++++++++++++++++++ cmod-a7-vivado/ip/main_pll.xci | 718 +++++++ source/dual_mcp3201_pmod.sv | 51 + source/mcp3201.sv | 77 + source/pll_lock_reset.sv | 17 + source/spi_sclk_gen.sv | 34 + testbench/.gitignore | 2 + testbench/Makefile | 30 + testbench/tb_mcp3201.sv | 70 + 14 files changed, 4345 insertions(+) create mode 100644 README.md create mode 100644 cmod-a7-vivado/.dir-locals.el create mode 100644 cmod-a7-vivado/cmod-a7.xdc create mode 100644 cmod-a7-vivado/cmod_a7.sv create mode 100644 cmod-a7-vivado/ip/README.md create mode 100644 cmod-a7-vivado/ip/ila.xci create mode 100644 cmod-a7-vivado/ip/main_pll.xci create mode 100644 source/dual_mcp3201_pmod.sv create mode 100644 source/mcp3201.sv create mode 100644 source/pll_lock_reset.sv create mode 100644 source/spi_sclk_gen.sv create mode 100644 testbench/.gitignore create mode 100644 testbench/Makefile create mode 100644 testbench/tb_mcp3201.sv diff --git a/README.md b/README.md new file mode 100644 index 0000000..98de074 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +Прошивка для платы CMOD A7 (на базе ПЛИС Artix-A7 T35) для теста платы с двумя АЦП +MCP3201. + +Создайте проект в Vivado для ПЛИС xc7a35tcpg236-1 и добавьте в него исходники RTL и +IP ядер (файлы `*.xci`). diff --git a/cmod-a7-vivado/.dir-locals.el b/cmod-a7-vivado/.dir-locals.el new file mode 100644 index 0000000..61e855c --- /dev/null +++ b/cmod-a7-vivado/.dir-locals.el @@ -0,0 +1,5 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((verilog-mode . ((flycheck-verilator-include-path . ("." "../source")) + (verilog-library-directories . ("." "../source"))))) diff --git a/cmod-a7-vivado/cmod-a7.xdc b/cmod-a7-vivado/cmod-a7.xdc new file mode 100644 index 0000000..596fae0 --- /dev/null +++ b/cmod-a7-vivado/cmod-a7.xdc @@ -0,0 +1,31 @@ +## CMOD A7 board. Chip: xc7a35tcpg236-1 + +set_property PACKAGE_PIN L17 [get_ports GCLK_i] + +set_property PACKAGE_PIN G17 [get_ports PMOD0[0]] ;# JA1 +set_property PACKAGE_PIN G19 [get_ports PMOD0[1]] ;# JA2 +set_property PACKAGE_PIN N18 [get_ports PMOD0[2]] ;# JA3 +set_property PACKAGE_PIN L18 [get_ports PMOD0[3]] ;# JA4 + +set_property PACKAGE_PIN H17 [get_ports PMOD1[0]] ;# JA7 +set_property PACKAGE_PIN H19 [get_ports PMOD1[1]] ;# JA8 +set_property PACKAGE_PIN J19 [get_ports PMOD1[2]] ;# JA9 +set_property PACKAGE_PIN K18 [get_ports PMOD1[3]] ;# JA10 + +set_property PACKAGE_PIN B18 [get_ports {BTN_i[1]}] +set_property PACKAGE_PIN A18 [get_ports {BTN_i[0]}] + +set_property IOSTANDARD LVCMOS33 [get_ports GCLK_i] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD0[0]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD0[1]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD0[2]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD0[3]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1[0]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1[1]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1[2]] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1[3]] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN_i[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN_i[0]}] + +# Overriden by PLL constraints +# create_clock -period 83.330 -name clk12 [get_ports GCLK_i] diff --git a/cmod-a7-vivado/cmod_a7.sv b/cmod-a7-vivado/cmod_a7.sv new file mode 100644 index 0000000..878e93a --- /dev/null +++ b/cmod-a7-vivado/cmod_a7.sv @@ -0,0 +1,54 @@ +`timescale 1ns/100ps +`default_nettype none + +/* verilator lint_off TIMESCALEMOD */ + +module cmod_a7 + (input wire GCLK_i, + input wire [1:0] BTN_i, + + inout wire [3:0] PMOD0, + inout wire [3:0] PMOD1); + + /* Clock and reset */ + logic clock; + logic reset; + logic pll_lock; + + main_pll main_pll_inst + (.clk_12(GCLK_i), + .reset(BTN_i[1]), + .locked(pll_lock), + .clk_50(clock)); + + pll_lock_reset #(.RESET_LEN(16)) reset_gen_impl + (.pll_clock(clock), + .pll_lock(pll_lock & (~BTN_i[1])), + .reset(reset)); + + /* ADCs connection */ + logic [11:0] ldata, rdata; + logic lstrb, rstrb; + + dual_mcp3201_pmod #(.CLOCK_FREQ(50000000), + .SAMPLE_RATE(50000)) brd + (.clock, .reset, + + .ladc_ssn(PMOD0[0]), + .ladc_clk(PMOD0[3]), + .ladc_dat(PMOD0[2]), + + .radc_ssn(PMOD1[0]), + .radc_clk(PMOD1[3]), + .radc_dat(PMOD1[2]), + + .rdata, .rstrb, + .ldata, .lstrb); + + /* Logic analyzer */ + ila ila_impl + (.clk(clock), + .probe0({ lstrb, ldata }), + .probe1({ rstrb, rdata })); + +endmodule // cmod_a7 diff --git a/cmod-a7-vivado/ip/README.md b/cmod-a7-vivado/ip/README.md new file mode 100644 index 0000000..b7ec046 --- /dev/null +++ b/cmod-a7-vivado/ip/README.md @@ -0,0 +1 @@ +Check "Copy sources into project" checkbox when add these files to the project. diff --git a/cmod-a7-vivado/ip/ila.xci b/cmod-a7-vivado/ip/ila.xci new file mode 100644 index 0000000..5d5921e --- /dev/null +++ b/cmod-a7-vivado/ip/ila.xci @@ -0,0 +1,3250 @@ + + + xilinx.com + xci + unknown + 1.0 + + + ila + + + + + 100000000 + 0 + 0.000 + 13 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 1 + 0 + 0 + undef + 0.000 + 1 + 0 + 0 + 0 + 0 + 10 + 10 + 200 + 5.0 + 6 + 65536 + 0 + 3 + 0 + 0 + 1 + 0 + 2000000 + 0 + 2019 + 2 + 1 + 2 + AXI4 + 1 + 0 + 0 + artix7 + DEFAULT + DEFAULT + DEFAULT + DEFAULT + DEFAULT + TRUE + 2 + FALSE + 10 + 10 + 200 + 5 + 65536 + FALSE + 3 + FALSE + FALSE + 1 + 0 + 2000000 + 0 + Native + 1 + 2 + 2 + 0 + 13 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 2 + 0 + 13 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 32 + 1 + 1 + 1 + 32 + 1 + 1 + 1 + 32 + 1 + AXI4 + 1 + 1 + 32 + false + false + DEFAULT + ila + TRUE + artix7 + + + xc7a35t + cpg236 + VERILOG + + MIXED + -1 + + + TRUE + TRUE + IP_Flow + 10 + TRUE + . + + . + 2019.2 + OUT_OF_CONTEXT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmod-a7-vivado/ip/main_pll.xci b/cmod-a7-vivado/ip/main_pll.xci new file mode 100644 index 0000000..f83c05b --- /dev/null +++ b/cmod-a7-vivado/ip/main_pll.xci @@ -0,0 +1,718 @@ + + + xilinx.com + xci + unknown + 1.0 + + + main_pll + + + false + 100000000 + false + 100000000 + false + 100000000 + false + 100000000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + 1 + LEVEL_HIGH + + + + 100000000 + 0 + 0.000 + 0 + 0 + + 100000000 + 0 + 0.000 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 0 + MMCM + cddcdone + cddcreq + 0000 + 0000 + clkfb_in_n + clkfb_in + clkfb_in_p + SINGLE + clkfb_out_n + clkfb_out + clkfb_out_p + clkfb_stopped + 833.33 + 100.0 + 0000 + 0000 + 50.00000 + 0000 + 0000 + 100.000 + BUFG + 50.0 + false + 50.00000 + 0.000 + 50.000 + 50 + 0.000 + 1 + 0000 + 0000 + 100.000 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + 0000 + 0000 + 100.000 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + 0000 + 0000 + 100.000 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + 0000 + 0000 + 100.000 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + 0000 + 0000 + 100.000 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + BUFG + 50.000 + false + 100.000 + 0.000 + 50.000 + 100.000 + 0.000 + 1 + 0 + VCO + clk_in_sel + clk_50 + clk_out2 + clk_out3 + clk_out4 + clk_out5 + clk_out6 + clk_out7 + CLK_VALID + NA + daddr + dclk + den + din + 0000 + 1 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + dout + drdy + dwe + 80.000 + 1.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + FDBK_AUTO + 0000 + 0000 + 0 + Input Clock Freq (MHz) Input Jitter (UI) + __primary______________12____________0.010 + no_secondary_input_clock + input_clk_stopped + 0 + Units_MHz + No_Jitter + locked + 0000 + 0000 + 0000 + false + false + false + false + false + false + false + false + OPTIMIZED + 62.500 + 0.000 + FALSE + 83.333 + 10.0 + 15.000 + 0.500 + 0.000 + FALSE + 1 + 0.500 + 0.000 + FALSE + 1 + 0.500 + 0.000 + FALSE + 1 + 0.500 + 0.000 + FALSE + FALSE + 1 + 0.500 + 0.000 + FALSE + 1 + 0.500 + 0.000 + FALSE + 1 + 0.500 + 0.000 + FALSE + FALSE + ZHOLD + 1 + None + 0.010 + 0.010 + FALSE + 64.000 + 2.000 + 1 + Output Output Phase Duty Cycle Pk-to-Pk Phase + Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) + __clk_50__50.00000______0.000______50.0______522.315____668.310 + no_CLK_OUT2_output + no_CLK_OUT3_output + no_CLK_OUT4_output + no_CLK_OUT5_output + no_CLK_OUT6_output + no_CLK_OUT7_output + 0 + 0 + 128.000 + 1.000 + WAVEFORM + UNKNOWN + false + false + false + false + false + OPTIMIZED + 1 + 0.000 + 1.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + CLKFBOUT + SYSTEM_SYNCHRONOUS + 1 + No notes + 0.010 + power_down + 0000 + 1 + clk_12 + MMCM + AUTO + 12 + 0.010 + 10.000 + Single_ended_clock_capable_pin + psclk + psdone + psen + psincdec + 100.0 + 0 + reset + 100.000 + 0.010 + 10.000 + clk_in2 + Single_ended_clock_capable_pin + CENTER_HIGH + 4000 + 0.004 + STATUS + 11 + 32 + 100.0 + 100.0 + 100.0 + 100.0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 1200.000 + 600.000 + main_pll + MMCM + false + empty + cddcdone + cddcreq + clkfb_in_n + clkfb_in + clkfb_in_p + SINGLE + clkfb_out_n + clkfb_out + clkfb_out_p + clkfb_stopped + 833.33 + 0.010 + 100.0 + 0.010 + BUFG + 522.315 + false + 668.310 + 50.000 + 50 + 0.000 + 1 + true + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + BUFG + 0.0 + false + 0.0 + 50.000 + 100.000 + 0.000 + 1 + false + 600.000 + Custom + Custom + clk_in_sel + clk_50 + false + clk_out2 + false + clk_out3 + false + clk_out4 + false + clk_out5 + false + clk_out6 + false + clk_out7 + false + CLK_VALID + auto + main_pll + daddr + dclk + den + Custom + Custom + din + dout + drdy + dwe + false + false + false + false + false + false + false + false + false + FDBK_AUTO + input_clk_stopped + frequency + Enable_AXI + Units_MHz + Units_UI + UI + No_Jitter + locked + OPTIMIZED + 62.500 + 0.000 + false + 83.333 + 10.0 + 15.000 + 0.500 + 0.000 + false + 1 + 0.500 + 0.000 + false + 1 + 0.500 + 0.000 + false + 1 + 0.500 + 0.000 + false + false + 1 + 0.500 + 0.000 + false + 1 + 0.500 + 0.000 + false + 1 + 0.500 + 0.000 + false + false + ZHOLD + 1 + None + 0.010 + 0.010 + false + 1 + false + false + WAVEFORM + false + UNKNOWN + OPTIMIZED + 4 + 0.000 + 10.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + 1 + 0.500 + 0.000 + CLKFBOUT + SYSTEM_SYNCHRONOUS + 1 + None + 0.010 + power_down + 1 + clk_12 + MMCM + mmcm_adv + 12 + 0.010 + 10.000 + Single_ended_clock_capable_pin + psclk + psdone + psen + psincdec + 100.0 + REL_PRIMARY + Custom + reset + ACTIVE_HIGH + 100.000 + 0.010 + 10.000 + clk_in2 + Single_ended_clock_capable_pin + CENTER_HIGH + 250 + 0.004 + STATUS + empty + 100.0 + 100.0 + 100.0 + 100.0 + false + false + false + false + false + false + false + true + false + false + true + false + false + false + true + false + true + false + false + false + artix7 + + + xc7a35t + cpg236 + VERILOG + + MIXED + -1 + + + TRUE + TRUE + IP_Flow + 4 + TRUE + . + + . + 2019.2 + OUT_OF_CONTEXT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/dual_mcp3201_pmod.sv b/source/dual_mcp3201_pmod.sv new file mode 100644 index 0000000..a56af65 --- /dev/null +++ b/source/dual_mcp3201_pmod.sv @@ -0,0 +1,51 @@ +`timescale 1ns/100ps +`default_nettype none + +module dual_mcp3201_pmod #(parameter CLOCK_FREQ = 25000000, + parameter SAMPLE_RATE = 50000) + (input wire clock, + input wire reset, + + output wire radc_ssn, + output wire radc_clk, + input wire radc_dat, + + output wire ladc_ssn, + output wire ladc_clk, + input wire ladc_dat, + + output wire [11:0] rdata, + output wire rstrb, + output wire [11:0] ldata, + output wire lstrb); + + localparam MCP3201_CLOCK_PER_SAMPLE = 17; + localparam SCLK_FREQ = SAMPLE_RATE * MCP3201_CLOCK_PER_SAMPLE; + + logic spi_clk; + + spi_sclk_gen #(.CLOCK_FREQ(CLOCK_FREQ), + .SCLK_FREQ(SCLK_FREQ)) spi_sclk_gen_impl + (.clock, .reset, + .sclk_o(spi_clk)); + + mcp3201 adc_left + (.clock, .reset, + .spi_clk_i(spi_clk), + .spi_ssn_o(ladc_ssn), + .spi_miso_i(ladc_dat), + .data_o(ldata), + .strb_o(lstrb)); + + mcp3201 adc_right + (.clock, .reset, + .spi_clk_i(spi_clk), + .spi_ssn_o(radc_ssn), + .spi_miso_i(radc_dat), + .data_o(rdata), + .strb_o(rstrb)); + + assign ladc_clk = spi_clk; + assign radc_clk = spi_clk; + +endmodule // dual_mcp3201_pmod diff --git a/source/mcp3201.sv b/source/mcp3201.sv new file mode 100644 index 0000000..8997f0b --- /dev/null +++ b/source/mcp3201.sv @@ -0,0 +1,77 @@ +`timescale 1ns/100ps +`default_nettype none + +/* + * MCP3201 controller + * Make one sample per 17 clock periods. + */ + +module mcp3201 + (input wire clock, + input wire reset, + + input wire spi_clk_i, + output reg spi_ssn_o, + input wire spi_miso_i, + + output reg [11:0] data_o, + output reg strb_o); + + logic sclk_posedge; + logic sclk_prev; + + always_ff @(posedge clock) + if (reset) sclk_prev <= 1'b0; + else sclk_prev <= spi_clk_i; + + assign sclk_posedge = { sclk_prev, spi_clk_i } == 2'b01 ? 1'b1 : 1'b0; + + /* Receive data FSM */ + enum int unsigned { + ST_RELAX = 0, + ST_SHIFT, + ST_STROBE + } state; + + logic [3:0] bit_cnt; + logic [11:0] data_sr; + + always_ff @(posedge clock) + if (reset) begin + state <= ST_RELAX; + bit_cnt <= '0; + spi_ssn_o <= 1'b1; + data_o <= '0; + strb_o <= 1'b0; + end + else begin + strb_o <= 1'b0; + + case (state) + ST_RELAX: + if (sclk_posedge) begin + bit_cnt <= '0; + spi_ssn_o <= 1'b0; + state <= ST_SHIFT; + end + + ST_SHIFT: + if (sclk_posedge) begin + data_sr <= { data_sr[10:0], spi_miso_i }; + bit_cnt <= bit_cnt + 1'b1; + + if (bit_cnt == 4'd14) begin + spi_ssn_o <= 1'b1; + state <= ST_STROBE; + end + end + + ST_STROBE: begin + data_o <= data_sr; + strb_o <= 1'b1; + state <= ST_RELAX; + end + endcase + end + +endmodule // mcp3201 diff --git a/source/pll_lock_reset.sv b/source/pll_lock_reset.sv new file mode 100644 index 0000000..957a22e --- /dev/null +++ b/source/pll_lock_reset.sv @@ -0,0 +1,17 @@ +`timescale 1ns/100ps +`default_nettype none + +module pll_lock_reset #(parameter RESET_LEN = 8) + (input wire pll_clock, + input wire pll_lock, + output wire reset); + + logic [RESET_LEN:0] rst_sr; + + always_ff @(posedge pll_clock, negedge pll_lock) + if (~pll_lock) rst_sr <= '0; + else rst_sr <= { 1'b1, rst_sr[RESET_LEN:1] }; + + assign reset = ~rst_sr[0]; + +endmodule // pll_lock_reset diff --git a/source/spi_sclk_gen.sv b/source/spi_sclk_gen.sv new file mode 100644 index 0000000..7d1cf81 --- /dev/null +++ b/source/spi_sclk_gen.sv @@ -0,0 +1,34 @@ +`timescale 1ns/100ps +`default_nettype none + +module spi_sclk_gen #(parameter CLOCK_FREQ = 12000000, + parameter SCLK_FREQ = 50000) + (input wire clock, + input wire reset, + output reg sclk_o); + + localparam SCLK_PERIOD = integer'($floor(real'(CLOCK_FREQ)/real'(SCLK_FREQ) + 0.5)); + localparam SCLK_HPER = SCLK_PERIOD/2; + localparam SCLK_CW = $clog2(SCLK_PERIOD); + + logic [SCLK_CW-1:0] sclk_cnt; + + always_ff @(posedge clock) + if (reset) begin + sclk_cnt <= '0; + sclk_o <= 1'b0; + end + else begin + if (sclk_cnt == '0) + sclk_o <= 1'b0; + else + if (sclk_cnt == SCLK_CW'(SCLK_HPER)) + sclk_o <= 1'b1; + + if (sclk_cnt == SCLK_CW'(SCLK_PERIOD-1)) + sclk_cnt <= '0; + else + sclk_cnt <= sclk_cnt + 1'b1; + end + +endmodule // spi_sclk_gen diff --git a/testbench/.gitignore b/testbench/.gitignore new file mode 100644 index 0000000..cd6b35a --- /dev/null +++ b/testbench/.gitignore @@ -0,0 +1,2 @@ +*.bin +*.vcd diff --git a/testbench/Makefile b/testbench/Makefile new file mode 100644 index 0000000..6087a94 --- /dev/null +++ b/testbench/Makefile @@ -0,0 +1,30 @@ +VC = iverilog +VI = vvp + +SOURCES = ../rtl/mcp3201.sv ../rtl/spi_sclk_gen.sv + +VFLAGS = -g2012 + +TBS = $(wildcard tb_*.sv) +DEFINES = -D TESTBENCH +VCDDEPS = $(TBS:.sv=.vcd) +BINDEPS = $(TBS:.sv=.bin) + +all: $(VCDDEPS) + +.SECONDARY: +#.SILENT: $(VCDDEPS) $(BINDEPS) clean + +%.vcd: %.bin + @echo "Simulate :" $(<:.bin=.sv) + $(VI) $< #> $(<:.bin=.out) + +%.bin: %.sv $(SOURCES) + @echo "Compile :" $(@:.bin=.sv) + $(VC) $(VFLAGS) $(DEFINES) -D DUMPFILE=\"$(@:.bin=.vcd)\" -o $@ $< $(SOURCES) + +clean: + @echo "Remove *.bin, *.vcd, *.out" + rm -rf *.bin + rm -rf *.out + rm -rf *.vcd diff --git a/testbench/tb_mcp3201.sv b/testbench/tb_mcp3201.sv new file mode 100644 index 0000000..6ae718a --- /dev/null +++ b/testbench/tb_mcp3201.sv @@ -0,0 +1,70 @@ +`timescale 1ps/1ps + +module tb_mcp3201; + logic clock = 1'b0; + logic reset = 1'b1; + + /* Master clock 10MHz (100ns period) */ + always #(100ns/2) clock <= ~clock; + + logic spi_clk; + logic spi_ssn; + logic spi_miso; + + logic [11:0] data; + logic strb; + + spi_sclk_gen #(.CLOCK_FREQ(10000000), .SCLK_FREQ(50000 * 17)) spi_clk_g + (.clock, .reset, + .sclk_o(spi_clk)); + + mcp3201 DUT + (.clock, .reset, + .spi_clk_i(spi_clk), + .spi_ssn_o(spi_ssn), + .spi_miso_i(spi_miso), + .data_o(data), + .strb_o(strb)); + + always_ff @ (posedge clock) + if (strb) + $display("%15b", data); + + logic [14:0] ds; + + initial begin + reset = 1'b1; + repeat(10) @(posedge clock); + reset = 1'b0; + + /* Send word 0 */ + wait(spi_ssn == 1'b0); + + ds = 15'bzz0_1010_1010_1010; + for (int i = 0; i < 15; i ++) begin + @(negedge spi_clk) spi_miso = ds[14]; + ds = ds << 1; + end + + /* Send word 1 */ + wait(spi_ssn == 1'b1); + wait(spi_ssn == 1'b0); + + ds = 15'bzz0_0101_0101_0101; + for (int i = 0; i < 15; i ++) begin + @(negedge spi_clk) spi_miso = ds[14]; + ds = ds << 1; + end + + wait(spi_ssn == 1'b1); + + repeat(10) @(posedge clock); + $finish; + end + + initial begin + $dumpfile("tb_mcp3201.vcd"); + $dumpvars; + end + +endmodule // tb_mcp3201