목표: FIFO 메모리에 저장되어 있는 데이터를 SPI 통신을 통해 PC단으로 넘겨준다


SCLK(직렬 클럭): 마스터에서 출력하여 슬레이브로 입력해줌. 동기화 신호임 → FPGA에서 클럭 생성해서 주면 될 듯? 마스터(fpga)가 생성하는 클럭 기준으로 데이터 전송
MOSI: 마스터 출력, 슬레이브 입력-fpga에서 PC로 데이터 줄거니까 fpga가 마스터, PC가 슬레이브
MISO: 보통 MOSI를 통해 슬레이브에 명령 DATA가 들어오면 MISO를 통해 슬레이브에서 마스터로 응답 데이터 출력
CS(Chip Select): 슬레이브 선택할 때 사용
https://www.youtube.com/watch?v=TR0Pw89EuGk&list=PLsskX2sA20kfSg64biDONnC-unVdoa-sX
https://github.com/nandland/spi-master/blob/master/Verilog/sim/SPI_Master_TB.sv
project manager-settings-simulation 들어가서

예제 코드 보면서 아래 파형 분석한 사진 보면서 이해하면 될 듯

예제 코드랑 거의 같은데
실제로 안쓸부분 주석처리랑
비바도에서 합성 가능하게 수정한 부분이 처리된 코드
///////////////////////////////////////////////////////////////////////////////
// Description: SPI (Serial Peripheral Interface) Master
// Creates master based on input configuration.
// Sends a byte one bit at a time on MOSI
// Will also receive byte data one bit at a time on MISO.
// Any data on input byte will be shipped out on MOSI.
//
// To kick-off transaction, user must pulse i_TX_DV.
// This module supports multi-byte transmissions by pulsing
// i_TX_DV and loading up i_TX_Byte when o_TX_Ready is high.
//
// This module is only responsible for controlling Clk, MOSI,
// and MISO. If the SPI peripheral requires a chip-select,
// this must be done at a higher level.
//
// Note: i_Clk must be at least 2x faster than i_SPI_Clk
//
// Parameters: SPI_MODE, can be 0, 1, 2, or 3. See above.
// Can be configured in one of 4 modes:
// Mode | Clock Polarity (CPOL/CKP) | Clock Phase (CPHA)
// 0 | 0 | 0
// 1 | 0 | 1
// 2 | 1 | 0
// 3 | 1 | 1
// More: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Mode_numbers
// CLKS_PER_HALF_BIT - Sets frequency of o_SPI_Clk. o_SPI_Clk is
// derived from i_Clk. Set to integer number of clocks for each
// half-bit of SPI data. E.g. 100 MHz i_Clk, CLKS_PER_HALF_BIT = 2
// would create o_SPI_CLK of 25 MHz. Must be >= 2
//
///////////////////////////////////////////////////////////////////////////////
module SPI_Master
#(parameter SPI_MODE = 0,
parameter CLKS_PER_HALF_BIT = 2) //SPI Clock 주기의 반에 i_clk이 얼마나 들어가냐
(
// Control/Data Signals,
input i_Rst_L, // FPGA Reset //reset 신호
input i_Clk, // FPGA Clock -fpga reference clock 말하는듯
// TX (MOSI) Signals
input [7:0] i_TX_Byte, // Byte to transmit on MOSI -MOSI핀으로 전송할 8비트 데이터
input i_TX_DV, // Data Valid Pulse with i_TX_Byte -데이터 다 보냈다고 보내는 펄스인듯
output reg o_TX_Ready, // Transmit Ready for next byte -다음 바이트를 보낼 준비가 되었다(바이트를 비트로 바꾸기 위해서 필요?)
//MISO 안쓰니까 필요 없을듯
// RX (MISO) Signals
output reg o_RX_DV, // Data Valid pulse (1 clock cycle)
output reg [7:0] o_RX_Byte, // Byte received on MISO
// SPI Interface
output reg o_SPI_Clk, //SCK 만들어주기 위한거인듯
input i_SPI_MISO,
output reg o_SPI_MOSI //이게 내가 필요한 핀일듯-slave로 전달하기 위한 핀
);
// SPI Interface (All Runs at SPI Clock Domain)
wire w_CPOL; // Clock polarity
wire w_CPHA; // Clock phase
reg [$clog2(CLKS_PER_HALF_BIT*2)-1:0] r_SPI_Clk_Count;
reg r_SPI_Clk;
reg [4:0] r_SPI_Clk_Edges;
reg r_Leading_Edge;
reg r_Trailing_Edge;
reg r_TX_DV;
reg [7:0] r_TX_Byte;
reg [2:0] r_RX_Bit_Count;
reg [2:0] r_TX_Bit_Count;
// CPOL: Clock Polarity
// CPOL=0 means clock idles at 0, leading edge is rising edge.
// CPOL=1 means clock idles at 1, leading edge is falling edge.
assign w_CPOL = (SPI_MODE == 2) | (SPI_MODE == 3);
// CPHA: Clock Phase
// CPHA=0 means the "out" side changes the data on trailing edge of clock
// the "in" side captures data on leading edge of clock
// CPHA=1 means the "out" side changes the data on leading edge of clock
// the "in" side captures data on the trailing edge of clock
assign w_CPHA = (SPI_MODE == 1) | (SPI_MODE == 3);
// Purpose: Generate SPI Clock correct number of times when DV pulse comes
//내가 원하는 SPI_clk(SCK) 만들어주는 부분
always @(posedge i_Clk or negedge i_Rst_L)
begin
if (~i_Rst_L) //active-low로 동작하는 reset
begin //초기
o_TX_Ready <= 1'b0;
r_SPI_Clk_Edges <= 0;
r_Leading_Edge <= 1'b0;
r_Trailing_Edge <= 1'b0;
r_SPI_Clk <= w_CPOL; // assign default state to idle state, w_CPOL 0이면 clk값 0부터 시작, 1이면 clk값 1부터 시작
r_SPI_Clk_Count <= 0;
end
else
begin
// Default assignments
r_Leading_Edge <= 1'b0;
r_Trailing_Edge <= 1'b0;
if (i_TX_DV)
begin
o_TX_Ready <= 1'b0;
r_SPI_Clk_Edges <= 16; // Total # edges in one byte ALWAYS 16
end
//
else if (r_SPI_Clk_Edges > 0)
begin
o_TX_Ready <= 1'b0;
if (r_SPI_Clk_Count == CLKS_PER_HALF_BIT*2-1) //r_SPI_Clk_count==7(시뮬레이션에서 4로해놔서)
begin
r_SPI_Clk_Edges <= r_SPI_Clk_Edges - 1'b1;
r_Trailing_Edge <= 1'b1; //trailing: 하강
r_SPI_Clk_Count <= 0;
r_SPI_Clk <= ~r_SPI_Clk;
end
else if (r_SPI_Clk_Count == CLKS_PER_HALF_BIT-1) //3
begin
r_SPI_Clk_Edges <= r_SPI_Clk_Edges - 1'b1;
r_Leading_Edge <= 1'b1; //leading: 상승
r_SPI_Clk_Count <= r_SPI_Clk_Count + 1'b1;
r_SPI_Clk <= ~r_SPI_Clk;
end
else
begin
r_SPI_Clk_Count <= r_SPI_Clk_Count + 1'b1;
end
end
//
else
begin
o_TX_Ready <= 1'b1;
end
end // else: !if(~i_Rst_L)
end // always @ (posedge i_Clk or negedge i_Rst_L)
//여기까지 내가 원하는 SCK 생성 파트
// Purpose: Register i_TX_Byte when Data Valid is pulsed.
// Keeps local storage of byte in case higher level module changes the data
always @(posedge i_Clk or negedge i_Rst_L)
begin
if (~i_Rst_L)
begin
r_TX_Byte <= 8'h00;
r_TX_DV <= 1'b0;
end
else
begin
r_TX_DV <= i_TX_DV; // 1 clock cycle delay
if (i_TX_DV)
begin
r_TX_Byte <= i_TX_Byte;
end
end // else: !if(~i_Rst_L)
end // always @ (posedge i_Clk or negedge i_Rst_L)
// Purpose: Generate MOSI data
// Works with both CPHA=0 and CPHA=1
always @(posedge i_Clk or negedge i_Rst_L)
begin
if (~i_Rst_L)
begin
o_SPI_MOSI <= 1'b0;
r_TX_Bit_Count <= 3'b111; // send MSb first
end
else
begin
// If ready is high, reset bit counts to default
if (o_TX_Ready)
begin
r_TX_Bit_Count <= 3'b111; //8비트니까
end
// Catch the case where we start transaction and CPHA = 0
else if (r_TX_DV & ~w_CPHA)
begin
o_SPI_MOSI <= r_TX_Byte[3'b111]; //MSB 전송
r_TX_Bit_Count <= 3'b110;
end
else if ((r_Leading_Edge & w_CPHA) | (r_Trailing_Edge & ~w_CPHA)) //시뮬레이션에서 모드 3으로 해서 CPHA 계속 1임
//CPHA 1일때는 상승에지일 때, CPHA 0일 때는 하강에지일 때 (CPOL 1일때로 가정하는건가?)
//1비트씩 수신
begin
r_TX_Bit_Count <= r_TX_Bit_Count - 1'b1;
o_SPI_MOSI <= r_TX_Byte[r_TX_Bit_Count]; //나머지 7비트 전송
end
end
end
// Purpose: Read in MISO data.
always @(posedge i_Clk or negedge i_Rst_L)
begin
if (~i_Rst_L)
begin
o_RX_Byte <= 8'h00;
o_RX_DV <= 1'b0;
r_RX_Bit_Count <= 3'b111;
end
else
begin
// Default Assignments
o_RX_DV <= 1'b0;
if (o_TX_Ready) // Check if ready is high, if so reset bit count to default
begin
r_RX_Bit_Count <= 3'b111;
end
else if ((r_Leading_Edge & ~w_CPHA) | (r_Trailing_Edge & w_CPHA))
begin
o_RX_Byte[r_RX_Bit_Count] <= i_SPI_MISO; // Sample data
r_RX_Bit_Count <= r_RX_Bit_Count - 1'b1;
if (r_RX_Bit_Count == 3'b000)
begin
o_RX_DV <= 1'b1; // Byte done, pulse Data Valid
end
end
end
end
// Purpose: Add clock delay to signals for alignment.
always @(posedge i_Clk or negedge i_Rst_L)
begin
if (~i_Rst_L)
begin
o_SPI_Clk <= w_CPOL;
end
else
begin
o_SPI_Clk <= r_SPI_Clk;
end // else: !if(~i_Rst_L)
end // always @ (posedge i_Clk or negedge i_Rst_L)
endmodule // SPI_Master
소스 코드에서 입력 받는 데이터가 i_TX_Byte인데 어차피 FIFO 메모리에서 데이터 보내줘야 하니까 내부 데이터로 실험해보고자 i_TX_Byte 자리에 임의의 데이터 8'b10010010를 넣어서 오실로스코프로 관측
//constraint
## This file is a general .xdc for the Zybo Z7 Rev. B
## It is compatible with the Zybo Z7-20 and Zybo Z7-10
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
##Clock signal
set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports {i_Clk}]; #IO_L12P_T1_MRCC_35 Sch=sysclk
create_clock -add -name sys_clk_pin -period 80 -waveform {0 40} [get_ports { i_Clk }];
##Switches
set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { i_Rst_L }]; #IO_L19N_T3_VREF_35 Sch=sw[0]
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L24P_T3_34 Sch=sw[1]
#set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L4N_T0_34 Sch=sw[2]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L9P_T1_DQS_34 Sch=sw[3]
##Buttons
set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { i_TX_DV }]; #IO_L12N_T1_MRCC_35 Sch=btn[0]
#set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L24N_T3_34 Sch=btn[1]
#set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L10P_T1_AD11P_35 Sch=btn[2]
#set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L7P_T1_34 Sch=btn[3]
##LEDs
#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { test_LED }]; #IO_L23P_T3_35 Sch=led[0]
#set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L23N_T3_35 Sch=led[1]
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_0_35 Sch=led[2]
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { test_LED }]; #IO_L3N_T0_DQS_AD1N_35 Sch=led[3]
##RGB LED 5 (Zybo Z7-20 only)
#set_property -dict { PACKAGE_PIN Y11 IOSTANDARD LVCMOS33 } [get_ports { led5_r }]; #IO_L18N_T2_13 Sch=led5_r
#set_property -dict { PACKAGE_PIN T5 IOSTANDARD LVCMOS33 } [get_ports { led5_g }]; #IO_L19P_T3_13 Sch=led5_g
#set_property -dict { PACKAGE_PIN Y12 IOSTANDARD LVCMOS33 } [get_ports { led5_b }]; #IO_L20P_T3_13 Sch=led5_b
##RGB LED 6
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led6_r }]; #IO_L18P_T2_34 Sch=led6_r
#set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { led6_g }]; #IO_L6N_T0_VREF_35 Sch=led6_g
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { led6_b }]; #IO_L8P_T1_AD10P_35 Sch=led6_b
##Audio Codec
#set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { ac_bclk }]; #IO_0_34 Sch=ac_bclk
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ac_mclk }]; #IO_L19N_T3_VREF_34 Sch=ac_mclk
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ac_muten }]; #IO_L23N_T3_34 Sch=ac_muten
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { ac_pbdat }]; #IO_L20N_T3_34 Sch=ac_pbdat
#set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } [get_ports { ac_pblrc }]; #IO_25_34 Sch=ac_pblrc
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ac_recdat }]; #IO_L19P_T3_34 Sch=ac_recdat
#set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { ac_reclrc }]; #IO_L17P_T2_34 Sch=ac_reclrc
#set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports { ac_scl }]; #IO_L13P_T2_MRCC_34 Sch=ac_scl
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ac_sda }]; #IO_L23P_T3_34 Sch=ac_sda
##Additional Ethernet signals
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { eth_int_pu_b }]; #IO_L6P_T0_35 Sch=eth_int_pu_b
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rst_b }]; #IO_L3P_T0_DQS_AD1P_35 Sch=eth_rst_b
##USB-OTG over-current detect pin
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { otg_oc }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=otg_oc
##Fan (Zybo Z7-20 only)
#set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { fan_fb_pu }]; #IO_L20N_T3_13 Sch=fan_fb_pu
##HDMI RX
#set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_hpd }]; #IO_L22N_T3_34 Sch=hdmi_rx_hpd
#set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_scl }]; #IO_L22P_T3_34 Sch=hdmi_rx_scl
#set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_sda }]; #IO_L17N_T2_34 Sch=hdmi_rx_sda
#set_property -dict { PACKAGE_PIN U19 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_clk_n }]; #IO_L12N_T1_MRCC_34 Sch=hdmi_rx_clk_n
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_clk_p }]; #IO_L12P_T1_MRCC_34 Sch=hdmi_rx_clk_p
#set_property -dict { PACKAGE_PIN W20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[0] }]; #IO_L16N_T2_34 Sch=hdmi_rx_n[0]
#set_property -dict { PACKAGE_PIN V20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[0] }]; #IO_L16P_T2_34 Sch=hdmi_rx_p[0]
#set_property -dict { PACKAGE_PIN U20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[1] }]; #IO_L15N_T2_DQS_34 Sch=hdmi_rx_n[1]
#set_property -dict { PACKAGE_PIN T20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[1] }]; #IO_L15P_T2_DQS_34 Sch=hdmi_rx_p[1]
#set_property -dict { PACKAGE_PIN P20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[2] }]; #IO_L14N_T2_SRCC_34 Sch=hdmi_rx_n[2]
#set_property -dict { PACKAGE_PIN N20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[2] }]; #IO_L14P_T2_SRCC_34 Sch=hdmi_rx_p[2]
##HDMI RX CEC (Zybo Z7-20 only)
#set_property -dict { PACKAGE_PIN Y8 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L14N_T2_SRCC_13 Sch=hdmi_rx_cec
##HDMI TX
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_hpd }]; #IO_L5P_T0_AD9P_35 Sch=hdmi_tx_hpd
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_scl }]; #IO_L16P_T2_35 Sch=hdmi_tx_scl
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_sda }]; #IO_L16N_T2_35 Sch=hdmi_tx_sda
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_clk_n }]; #IO_L13N_T2_MRCC_35 Sch=hdmi_tx_clk_n
#set_property -dict { PACKAGE_PIN H16 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_clk_p }]; #IO_L13P_T2_MRCC_35 Sch=hdmi_tx_clk_p
#set_property -dict { PACKAGE_PIN D20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[0] }]; #IO_L4N_T0_35 Sch=hdmi_tx_n[0]
#set_property -dict { PACKAGE_PIN D19 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[0] }]; #IO_L4P_T0_35 Sch=hdmi_tx_p[0]
#set_property -dict { PACKAGE_PIN B20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[1] }]; #IO_L1N_T0_AD0N_35 Sch=hdmi_tx_n[1]
#set_property -dict { PACKAGE_PIN C20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[1] }]; #IO_L1P_T0_AD0P_35 Sch=hdmi_tx_p[1]
#set_property -dict { PACKAGE_PIN A20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[2] }]; #IO_L2N_T0_AD8N_35 Sch=hdmi_tx_n[2]
#set_property -dict { PACKAGE_PIN B19 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[2] }]; #IO_L2P_T0_AD8P_35 Sch=hdmi_tx_p[2]
##HDMI TX CEC
#set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_cec }]; #IO_L5N_T0_AD9N_35 Sch=hdmi_tx_cec
##Pmod Header JA (XADC)
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L21P_T3_DQS_AD14P_35 Sch=JA1_R_p
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L22P_T3_AD7P_35 Sch=JA2_R_P
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L24P_T3_AD15P_35 Sch=JA3_R_P
#set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L20P_T3_AD6P_35 Sch=JA4_R_P
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L21N_T3_DQS_AD14N_35 Sch=JA1_R_N
#set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L22N_T3_AD7N_35 Sch=JA2_R_N
#set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L24N_T3_AD15N_35 Sch=JA3_R_N
#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L20N_T3_AD6N_35 Sch=JA4_R_N
##Pmod Header JB (Zybo Z7-20 only)
#set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L15P_T2_DQS_13 Sch=jb_p[1]
#set_property -dict { PACKAGE_PIN W8 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L15N_T2_DQS_13 Sch=jb_n[1]
#set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L11P_T1_SRCC_13 Sch=jb_p[2]
#set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L11N_T1_SRCC_13 Sch=jb_n[2]
#set_property -dict { PACKAGE_PIN Y7 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L13P_T2_MRCC_13 Sch=jb_p[3]
#set_property -dict { PACKAGE_PIN Y6 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L13N_T2_MRCC_13 Sch=jb_n[3]
#set_property -dict { PACKAGE_PIN V6 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L22P_T3_13 Sch=jb_p[4]
#set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L22N_T3_13 Sch=jb_n[4]
##Pmod Header JC
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L10P_T1_34 Sch=jc_p[1]
#set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L10N_T1_34 Sch=jc_n[1]
#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L1P_T0_34 Sch=jc_p[2]
#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L1N_T0_34 Sch=jc_n[2]
#set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jc[4] }]; #IO_L8P_T1_34 Sch=jc_p[3]
#set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L8N_T1_34 Sch=jc_n[3]
#set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L2P_T0_34 Sch=jc_p[4]
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L2N_T0_34 Sch=jc_n[4]
##Pmod Header JD
#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { o_SPI_MOSI }]; #IO_L5P_T0_34 Sch=jd_p[1]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { i_SPI_MISO }]; #IO_L5N_T0_34 Sch=jd_n[1]
#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { o_SPI_Clk }]; #IO_L6P_T0_34 Sch=jd_p[2]
#set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { o_RX_DV}]; #IO_L6N_T0_VREF_34 Sch=jd_n[2]
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { o_TX_Ready }]; #IO_L11P_T1_SRCC_34 Sch=jd_p[3]
#set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { i_Clk }]; #IO_L11N_T1_SRCC_34 Sch=jd_n[3]
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L21P_T3_DQS_34 Sch=jd_p[4]
#set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L21N_T3_DQS_34 Sch=jd_n[4]
##Pmod Header JE
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { o_SPI_MOSI }]; #IO_L4P_T0_34 Sch=je[1]
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { i_SPI_MISO }]; #IO_L18N_T2_34 Sch=je[2]
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { o_SPI_Clk }]; #IO_25_35 Sch=je[3]
set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { o_RX_DV }]; #IO_L19P_T3_35 Sch=je[4]
set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { o_TX_Ready}]; #IO_L3N_T0_DQS_34 Sch=je[7]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports {need_clk }]; #IO_L9N_T1_DQS_34 Sch=je[8]
#set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { je[6] }]; #IO_L20P_T3_34 Sch=je[9]
#set_property -dict { PACKAGE_PIN Y17 IOSTANDARD LVCMOS33 } [get_ports { je[7] }]; #IO_L7N_T1_34 Sch=je[10]
##Pcam MIPI CSI-2 Connector
## This configuration expects the sensor to use 672Mbps/lane = 336 MHz HS_Clk
#create_clock -period 2.976 -name dphy_hs_clock_clk_p -waveform {0.000 1.488} [get_ports dphy_hs_clock_clk_p]
#set_property INTERNAL_VREF 0.6 [get_iobanks 35]
#set_property -dict { PACKAGE_PIN J19 IOSTANDARD HSUL_12 } [get_ports { dphy_clk_lp_n }]; #IO_L10N_T1_AD11N_35 Sch=lp_clk_n
#set_property -dict { PACKAGE_PIN H20 IOSTANDARD HSUL_12 } [get_ports { dphy_clk_lp_p }]; #IO_L17N_T2_AD5N_35 Sch=lp_clk_p
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_n[0] }]; #IO_L8N_T1_AD10N_35 Sch=lp_lane_n[0]
#set_property -dict { PACKAGE_PIN L19 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_p[0] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=lp_lane_p[0]
#set_property -dict { PACKAGE_PIN L20 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_n[1] }]; #IO_L9N_T1_DQS_AD3N_35 Sch=lp_lane_n[1]
#set_property -dict { PACKAGE_PIN J20 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_p[1] }]; #IO_L17P_T2_AD5P_35 Sch=lp_lane_p[1]
#set_property -dict { PACKAGE_PIN H18 IOSTANDARD LVDS_25 } [get_ports { dphy_hs_clock_clk_n }]; #IO_L14N_T2_AD4N_SRCC_35 Sch=mipi_clk_n
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVDS_25 } [get_ports { dphy_hs_clock_clk_p }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=mipi_clk_p
#set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_n[0] }]; #IO_L7N_T1_AD2N_35 Sch=mipi_lane_n[0]
#set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_p[0] }]; #IO_L7P_T1_AD2P_35 Sch=mipi_lane_p[0]
#set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_n[1] }]; #IO_L11N_T1_SRCC_35 Sch=mipi_lane_n[1]
#set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_p[1] }]; #IO_L11P_T1_SRCC_35 Sch=mipi_lane_p[1]
#set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports { cam_clk }]; #IO_L18P_T2_AD13P_35 Sch=cam_clk
#set_property -dict { PACKAGE_PIN G20 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { cam_gpio }]; #IO_L18N_T2_AD13N_35 Sch=cam_gpio
#set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { cam_scl }]; #IO_L15N_T2_DQS_AD12N_35 Sch=cam_scl
#set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { cam_sda }]; #IO_L15P_T2_DQS_AD12P_35 Sch=cam_sda
##Unloaded Crypto Chip SWI (for future use)
#set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }]; #IO_L13N_T2_MRCC_34 Sch=crypto_sda
##Unconnected Pins (Zybo Z7-20 only)
#set_property PACKAGE_PIN T9 [get_ports {netic19_t9}]; #IO_L12P_T1_MRCC_13
#set_property PACKAGE_PIN U10 [get_ports {netic19_u10}]; #IO_L12N_T1_MRCC_13
#set_property PACKAGE_PIN U5 [get_ports {netic19_u5}]; #IO_L19N_T3_VREF_13
#set_property PACKAGE_PIN U8 [get_ports {netic19_u8}]; #IO_L17N_T2_13
#set_property PACKAGE_PIN U9 [get_ports {netic19_u9}]; #IO_L17P_T2_13
#set_property PACKAGE_PIN V10 [get_ports {netic19_v10}]; #IO_L21N_T3_DQS_13
#set_property PACKAGE_PIN V11 [get_ports {netic19_v11}]; #IO_L21P_T3_DQS_13
#set_property PACKAGE_PIN V5 [get_ports {netic19_v5}]; #IO_L6N_T0_VREF_13
#set_property PACKAGE_PIN W10 [get_ports {netic19_w10}]; #IO_L16P_T2_13
#set_property PACKAGE_PIN W11 [get_ports {netic19_w11}]; #IO_L18P_T2_13
#set_property PACKAGE_PIN W9 [get_ports {netic19_w9}]; #IO_L16N_T2_13
#set_property PACKAGE_PIN Y9 [get_ports {netic19_y9}]; #IO_L14P_T2_SRCC_13
FPGA 상에서 i_TX_DV를 푸시 버튼으로 구현
푸시 버튼 눌렀다 떼면 임의의 데이터 수신되는 것 확인 가능
(i_TX_DV의 목적: 내가 이해한 바로는 SPI 통신 모드가 4가지인데 그 중 일부 모드에서 데이터 밀리거나 잘리는거 방지 위함인듯)

영상으로 보고 싶으면 구글 드라이브 참고
여기까지가 단순 SPI 구현