SergeyVas 0 9 мая, 2015 Опубликовано 9 мая, 2015 · Жалоба Хочу попробовать запустить spi slave на циклоне. Поискал в сети готовые исходники, примеров много для этого интерфейса не знаю с какого начать, подскажите пожалуйста ссылку на проверенный пример, который вам понравился )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 9 мая, 2015 Опубликовано 9 мая, 2015 · Жалоба Хочу попробовать запустить spi slave на циклоне. Поискал в сети готовые исходники, примеров много для этого интерфейса не знаю с какого начать, подскажите пожалуйста ссылку на проверенный пример, который вам понравился )) `timescale 1ns/1ns `define CLOCK_PHASE 0 `define CLOCK_POLARITY 0 module spi_slave #( parameter SHIFT_DIRECTION = 0, parameter DATA_LENGTH = 8 // changed from 32 to 8 ) ( //Back end device interfacet CSn, DATA_IN, //8 bit width - changed from 32 bits WR_RD, DATA_OUT, //8 bit width - changed from 32 bits TX_RDY, RX_RDY, TX_ERR, RX_ERR, CLK_I, RST_I, //spi interface MISO_SLAVE, MOSI_SLAVE, CSn_SLAVE, SCLK_SLAVE ); //back end device interface input CSn; input [7:0] DATA_IN; //8 bit width - changed from 32 bits input WR_RD; output [7:0] DATA_OUT; //8 bit width - changed from 32 bits output TX_RDY; output RX_RDY; output TX_ERR; output RX_ERR; input CLK_I; input RST_I; //spi interface output MISO_SLAVE; input MOSI_SLAVE; input CSn_SLAVE; input SCLK_SLAVE; parameter UDLY = 1; //register access reg MISO_SLAVE; reg [7:0] latch_s_data; //8 bit width - changed from 32 bits reg [DATA_LENGTH-1:0] reg_rxdata; reg [DATA_LENGTH-1:0] reg_txdata; reg [DATA_LENGTH-1:0] rx_shift_data; reg reg_toe; reg reg_roe; reg reg_trdy; reg reg_rrdy; reg tx_done; reg rx_done; reg rx_done_flip1; reg rx_done_flip2; reg rx_done_flip3; reg tx_done_flip1; reg tx_done_flip2; reg tx_done_flip3; reg [5:0] rx_data_cnt; reg [5:0] tx_data_cnt; assign TX_RDY=reg_trdy; assign RX_RDY=reg_rrdy; assign TX_ERR=reg_toe; assign RX_ERR=reg_roe; assign DATA_OUT=reg_rxdata; always @(posedge CLK_I or posedge RST_I) if(RST_I) latch_s_data <= #UDLY 32'h0; else if (!WR_RD && !CSn && reg_trdy) latch_s_data <= #UDLY DATA_IN; //Receive Data Register always @(posedge CLK_I or posedge RST_I) if(RST_I) reg_rxdata <= #UDLY 'h0; else if (rx_done_flip1 && !rx_done_flip2) reg_rxdata <= #UDLY rx_shift_data; //Transmit Data Register always @(posedge CLK_I or posedge RST_I) if(RST_I) reg_txdata <= #UDLY 'h0; else //if (!WR_RD && !CSn && reg_trdy) reg_txdata <= #UDLY latch_s_data; //-----------------------------For Rx data, //-----------------sample at posedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 0 `ifdef CLOCK_POLARITY `ifdef CLOCK_PHASE always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_shift_data <= #UDLY 'h0; else if (!CSn_SLAVE) if (SHIFT_DIRECTION) rx_shift_data <= #UDLY {MOSI_SLAVE,rx_shift_data[DATA_LENGTH-1:1]}; else rx_shift_data <= #UDLY {rx_shift_data,MOSI_SLAVE}; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_data_cnt <= #UDLY 'h0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) rx_data_cnt <= #UDLY rx_data_cnt + 1; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_done <= #UDLY 1'b0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_done <= #UDLY 1'b1; else rx_done <= #UDLY 1'b0; //-----------------sample at negedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 1 `else //For Rx data, sample at negedge when CLOCK_PHASE is 1 always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_shift_data <= #UDLY 'h0; else if (!CSn_SLAVE) if (SHIFT_DIRECTION) rx_shift_data <= #UDLY {MOSI_SLAVE,rx_shift_data[DATA_LENGTH-1:1]}; else rx_shift_data <= #UDLY {rx_shift_data,MOSI_SLAVE}; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_data_cnt <= #UDLY 'h0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) rx_data_cnt <= #UDLY rx_data_cnt + 1; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_done <= #UDLY 1'b0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_done <= #UDLY 1'b1; else rx_done <= #UDLY 1'b0; //end `endif //-----------------sample at negedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 0 `else `ifdef CLOCK_PHASE always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_shift_data <= #UDLY 'h0; else if (!CSn_SLAVE) if (SHIFT_DIRECTION) rx_shift_data <= #UDLY {MOSI_SLAVE,rx_shift_data[DATA_LENGTH-1:1]}; else rx_shift_data <= #UDLY {rx_shift_data,MOSI_SLAVE}; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_data_cnt <= #UDLY 'h0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) rx_data_cnt <= #UDLY rx_data_cnt + 1; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_done <= #UDLY 1'b0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_done <= #UDLY 1'b1; else rx_done <= #UDLY 1'b0; //-----------------sample at posedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 1 `else //For Rx data, sample at negedge when CLOCK_PHASE is 1 always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_shift_data <= #UDLY 'h0; else if (!CSn_SLAVE) if (SHIFT_DIRECTION) rx_shift_data <= #UDLY {MOSI_SLAVE,rx_shift_data[DATA_LENGTH-1:1]}; else rx_shift_data <= #UDLY {rx_shift_data,MOSI_SLAVE}; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_data_cnt <= #UDLY 'h0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) rx_data_cnt <= #UDLY rx_data_cnt + 1; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) rx_done <= #UDLY 1'b0; else if (rx_data_cnt == DATA_LENGTH - 1) rx_done <= #UDLY 1'b1; else rx_done <= #UDLY 1'b0; //end `endif `endif always @(posedge CLK_I or posedge RST_I) if (RST_I) begin rx_done_flip1 <= #UDLY 1'b0; rx_done_flip2 <= #UDLY 1'b0; rx_done_flip3 <= #UDLY 1'b0; end else begin rx_done_flip1 <= #UDLY rx_done; rx_done_flip2 <= #UDLY rx_done_flip1; rx_done_flip3 <= #UDLY rx_done_flip2; end always @(posedge CLK_I or posedge RST_I) if (RST_I) reg_rrdy <= #UDLY 1'b0; else if (rx_done_flip2 && !rx_done_flip3) reg_rrdy <= #UDLY 1'b1; else if (WR_RD && !CSn) reg_rrdy <= #UDLY 1'b0; always @(posedge CLK_I or posedge RST_I) if (RST_I) reg_roe <= #UDLY 1'b0; else if (rx_done_flip2 && !rx_done_flip3 && reg_rrdy) reg_roe <= #UDLY 1'b1; else if (WR_RD && !CSn) reg_roe <= #UDLY 1'b0; //--------------------For Tx data, //-----------------------------------update at negedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 0 `ifdef CLOCK_POLARITY `ifdef CLOCK_PHASE //always @(*) always @(reg_txdata or tx_data_cnt or CSn_SLAVE ) if (!CSn_SLAVE) MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : reg_txdata[DATA_LENGTH-tx_data_cnt-1]; else MISO_SLAVE<=1'bz; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_data_cnt <= #UDLY 'h0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) tx_data_cnt <= #UDLY tx_data_cnt + 1; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_done <= #UDLY 1'b0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_done <= #UDLY 1'b1; else tx_done <= #UDLY 1'b0; //-----------------------------------update at posedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 1 `else //always @(posedge SCLK_SLAVE or posedge RST_I) // if (RST_I) // MISO_SLAVE <= #UDLY 1'b0; // else // MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : // reg_txdata[DATA_LENGTH-tx_data_cnt-1]; always @(posedge SCLK_SLAVE) if (!CSn_SLAVE) MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : reg_txdata[DATA_LENGTH-tx_data_cnt-1]; else MISO_SLAVE<=1'bz; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_data_cnt <= #UDLY 'h0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) tx_data_cnt <= #UDLY tx_data_cnt + 1; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_done <= #UDLY 1'b0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_done <= #UDLY 1'b1; else tx_done <= #UDLY 1'b0; `endif //-----------------------------------update at posedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 0 `else `ifdef CLOCK_PHASE //always @(*) always @(reg_txdata or tx_data_cnt or CSn_SLAVE ) if (!CSn_SLAVE) MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : reg_txdata[DATA_LENGTH-tx_data_cnt-1]; else MISO_SLAVE<=1'bz; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_data_cnt <= #UDLY 'h0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) tx_data_cnt <= #UDLY tx_data_cnt + 1; always @(posedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_done <= #UDLY 1'b0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_done <= #UDLY 1'b1; else tx_done <= #UDLY 1'b0; //-----------------------------------update at negedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 1 `else // always @(negedge SCLK_SLAVE or posedge RST_I) // if (RST_I) // MISO_SLAVE <= #UDLY 1'b0; // else // MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : // reg_txdata[DATA_LENGTH-tx_data_cnt-1]; always @(negedge SCLK_SLAVE) if (!CSn_SLAVE) MISO_SLAVE <= #UDLY SHIFT_DIRECTION ? reg_txdata[tx_data_cnt] : reg_txdata[DATA_LENGTH-tx_data_cnt-1]; else MISO_SLAVE<=1'bz; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_data_cnt <= #UDLY 'h0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_data_cnt <= #UDLY 'h0; else if (!CSn_SLAVE) tx_data_cnt <= #UDLY tx_data_cnt + 1; always @(negedge SCLK_SLAVE or posedge RST_I) if (RST_I) tx_done <= #UDLY 1'b0; else if (tx_data_cnt == DATA_LENGTH - 1) tx_done <= #UDLY 1'b1; else tx_done <= #UDLY 1'b0; `endif `endif always @(posedge CLK_I or posedge RST_I) if (RST_I) begin tx_done_flip1 <= #UDLY 1'b0; tx_done_flip2 <= #UDLY 1'b0; tx_done_flip3 <= #UDLY 1'b0; end else begin tx_done_flip1 <= #UDLY tx_done; tx_done_flip2 <= #UDLY tx_done_flip1; tx_done_flip3 <= #UDLY tx_done_flip2; end always @(posedge CLK_I or posedge RST_I) if (RST_I) reg_trdy <= #UDLY 1'b1; else if (!WR_RD && !CSn) reg_trdy <= #UDLY 1'b0; else if (tx_done_flip2 && !tx_done_flip3) reg_trdy <= #UDLY 1'b1; always @(posedge CLK_I or posedge RST_I) if(RST_I) reg_toe <= #UDLY 1'b0; else if(!reg_trdy && !WR_RD && !CSn) reg_toe <= #UDLY 1'b1; else if(!WR_RD && !CSn) reg_toe <= #UDLY 1'b0; endmodule тестбенч: `timescale 1ns/1ps module spi_speripheral_tb; wire clk,rst; wire mosi,csn_spi,sclk; wire csn,wr_rd; wire [7:0] data_out; wire miso; wire tx_rdy,rx_rdy,tx_err,rx_err; wire [7:0] data_in; spi_master spi_master( .sclk_master(sclk), .csn_master(csn_spi), .mosi_master(mosi), .miso_master(miso) ); spi_slave spi_slave ( //slave port .CSn(csn), .DATA_IN(data_in), //8 bit width - changed from 32 bits .WR_RD(wr_rd), .DATA_OUT(data_out), //8 bit width - changed from 32 bits .TX_RDY(tx_rdy), .RX_RDY(rx_rdy), .TX_ERR(tx_err), .RX_ERR(rx_err), //spi interface .MISO_SLAVE(miso), .MOSI_SLAVE(mosi), .CSn_SLAVE(csn_spi), .SCLK_SLAVE(sclk), //system clock and reset .CLK_I(clk), .RST_I(rst) ); back_end_device back_end_device( .CSn(csn), .DATA_IN(data_out), .WR_RD(wr_rd), .DATA_OUT(data_in), .TX_RDY(tx_rdy), .RX_RDY(rx_rdy), .TX_ERR(tx_err), .RX_ERR(rx_err), .CLK(clk), .RST(rst) ); endmodule `timescale 1ns/1ps module spi_master( sclk_master, csn_master, mosi_master, miso_master ); parameter CLOCK_PHASE = 0; parameter CLOCK_POLARITY = 0; parameter sclk_cycle= 40; parameter SHIFT_DIRECTION = 0; parameter DATA_LENGTH = 8; // changed from 32 to 8 output sclk_master; output csn_master; output mosi_master; input miso_master; reg sclk_master; reg csn_master; reg mosi_master; reg [7:0] master_data_in; reg [7:0] master_data_out; reg [2:0] cnt; initial begin if(CLOCK_POLARITY) sclk_master<=#1 1'b1; else sclk_master<=#1 1'b0; csn_master<=1'b1; master_data_in<=8'h00; master_data_out<=8'h00; cnt<=3'h0; mosi_master<=1'b0; #306; spi_master_operation(8'h73); #100; spi_master_operation(8'h43); #104; spi_master_operation(8'h19); #100 spi_master_operation(8'h55); #100 spi_master_operation(8'haa); #100 $stop; end task spi_master_operation; input [7:0] data_out; integer i; begin $display($time,"ns: SPI master sends data %h",data_out); master_data_out=data_out; csn_master<=1'b0; if(!CLOCK_POLARITY) begin if(!CLOCK_PHASE) begin cnt<=3'h0; for (i = 7; i >= 0; i = i - 1) begin mosi_master<=SHIFT_DIRECTION ? master_data_out[cnt]:master_data_out[DATA_LENGTH-cnt-1]; #sclk_cycle; sclk_master<=#1 1'b1; master_data_in<={master_data_in[6:0],miso_master}; #sclk_cycle; sclk_master<=#1 1'b0; // at the falling edge of SCLK. cnt=cnt+1; end #2; csn_master<=1'b1; end else begin cnt<=3'h0; for (i = 7; i >= 0; i = i - 1) begin #sclk_cycle; sclk_master<=1'b1; // at the raising edge of SCLK. mosi_master<=SHIFT_DIRECTION ? master_data_out[cnt]:master_data_out[DATA_LENGTH-cnt-1]; cnt<=cnt+1; #sclk_cycle; sclk_master<=1'b0; master_data_in<={master_data_in[6:0],miso_master}; end #2; csn_master<=1'b1; end end else begin if(!CLOCK_PHASE) begin cnt<=3'h0; for (i = 7; i >= 0; i = i - 1) begin mosi_master<=SHIFT_DIRECTION ? master_data_out[cnt]:master_data_out[DATA_LENGTH-cnt-1]; #sclk_cycle; sclk_master<=1'b0; master_data_in<={master_data_in[6:0],miso_master}; #sclk_cycle; sclk_master<=1'b1; // at the raising edge of SCLK. cnt=cnt+1; end #2; csn_master<=1'b1; end else begin cnt<=3'h0; for (i = 7; i >= 0; i = i - 1) begin #sclk_cycle; sclk_master<=1'b0; // at the falling edge of SCLK. mosi_master<=SHIFT_DIRECTION ? master_data_out[cnt]:master_data_out[DATA_LENGTH-cnt-1]; cnt<=cnt+1; #sclk_cycle; sclk_master<=1'b1; master_data_in<={master_data_in[6:0],miso_master}; end #2; csn_master<=1'b1; end end $display($time,"ns: SPI master receive data %h",master_data_in); end endtask endmodule `timescale 1ns/1ps module back_end_device( CSn, DATA_IN, WR_RD, DATA_OUT, TX_RDY, RX_RDY, TX_ERR, RX_ERR, CLK, RST ); output CLK; output RST; output CSn; input [7:0] DATA_IN; output WR_RD; output [7:0] DATA_OUT; input TX_RDY; input RX_RDY; input TX_ERR; input RX_ERR; parameter clk_cycle= 10; reg CLK; reg RST; reg CSn; reg WR_RD; reg [7:0] DATA_OUT; integer i; always #(clk_cycle/2) CLK = ~CLK; initial begin RST<=1'b0; CLK<= 1'b0; CSn<=1'b1; WR_RD<=1'b1; DATA_OUT<=8'h00; i=0; #2; RST<=1'b1; #200; RST<=1'b0; while(i<3) begin @(posedge CLK) if(RX_RDY || TX_RDY) begin if(TX_RDY) begin CSn<=#1 1'b0; WR_RD<=#1 1'b0; DATA_OUT=#1 $random % 60; i=i+1; $display($time,"ns: Back end device send data %h",DATA_OUT); @(posedge CLK) CSn<=#1 1'b1; WR_RD<=#1 1'b1; end else if(RX_RDY) begin CSn<=#1 1'b0; WR_RD<=#1 1'b1; $display($time,"ns: Back end device receive data %h",DATA_IN); @(posedge CLK) CSn<=#1 1'b1; WR_RD<=#1 1'b1; end end end @(posedge CLK) CSn<=#1 1'b0; WR_RD<=#1 1'b0; DATA_OUT=#1 $random % 60; $display($time,"ns: Back end device send data %h",DATA_OUT); @(posedge CLK) CSn<=#1 1'b1; WR_RD<=#1 1'b1; end endmodule //--------------------------------EOF----------------------------------------- module BI_DIR (O,I0,IO,OE); input I0,OE; inout IO; output O; supply0 GND; supply1 VCC; reg IO0, O0; wire IO1; parameter PULL = "Off"; parameter OUTOPEN = "Off"; //assign O=O0; buf INSXQ1 (O,O0); //assign IO = IO0; //buf INSXQ2 (IO,IO0); //assign IO1 = IO; buf INSXQ3 (IO1,IO); bufif1 INSXQ2 (IO,IO0,OE); always @(IO1) begin if (PULL == "Off") case(IO1) 1'b0: O0 = 1'b0; 1'b1: O0 = 1'b1; 1'bz: O0 = 1'bx; 1'bx: O0 = 1'bx; endcase else if (PULL == "Up") case(IO1) 1'b0: O0 = 1'b0; 1'b1: O0 = 1'b1; 1'bz: O0 = 1'b1; endcase else if (PULL == "Down") case(IO1) 1'b0: O0 = 1'b0; 1'b1: O0 = 1'b1; 1'bz: O0 = 1'b0; endcase else if (PULL == "Hold") case(IO1) 1'b0: O0 = 1'b0; 1'b1: O0 = 1'b1; 1'bz: O0 = O0; endcase end always @(OE or I0) begin if (OE == 1'b0) IO0 = 1'bz; else if (OE == 1'b1) if (OUTOPEN == "Off") case(I0) 1'b0: IO0 = 1'b0; 1'b1: IO0 = 1'b1; 1'bz: IO0 = 1'bx; 1'bx: IO0 = 1'bx; endcase else if (OUTOPEN == "Drain" || OUTOPEN == "Collect") begin if (I0 == 1'b0) IO0 = 1'b0; else if (I0 == 1'b1) begin if (PULL == "Off") IO0 = 1'bz; else if (PULL == "Up") IO0 = 1'b1; else if (PULL == "Down") IO0 = 1'b0; else if (PULL == "Hold") IO0 = IO0; else IO0 = 1'bz; end else IO0 = 1'bx; end end specify (I0 => IO) = 0:0:0, 0:0:0; (OE => IO) = 0:0:0, 0:0:0; (IO => O) = 0:0:0, 0:0:0; endspecify endmodule PS могу поделиться описанием на VHDL... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Благодарю за код, давайте если не жалко )). Есть какие отличия ? На верилоге вроде компактнее получается код, конечно у меня опыта не много поэтому утверждать не буду. Сейчас попробую протестировать на stm32f407 ep3c5e результат напишу. Значок решетка что означает? Немного не по теме, случайно не знаете в квартусе 13,1 есть автоформатирование кода ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Благодарю за код, давайте если не жалко )). Есть какие отличия ? описание на VHDL - функциональных отличий нет по сравнению с описанием на verilog. library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity spi_slave is generic (DATA_LENGTH : integer:=8; SHIFT_DIRECTION: std_logic := '0'; CLOCK_POLARITY:std_logic:='0'; CLOCK_PHASE:std_logic:='0'); port ( CSn : in std_logic; DATA_IN : in std_logic_vector(7 downto 0); WR_RD : in std_logic; DATA_OUT : out std_logic_vector(7 downto 0); TX_RDY : out std_logic; RX_RDY : out std_logic; TX_ERR : out std_logic; RX_ERR : out std_logic; CLK_I : in std_logic; RST_I : in std_logic; MISO_SLAVE : out std_logic; MOSI_SLAVE : in std_logic; CSn_SLAVE : in std_logic; SCLK_SLAVE : in std_logic ); end; architecture arch of spi_slave is constant UDLY:time:=1 ns; signal latch_s_data:std_logic_vector(7 downto 0); signal reg_rxdata:std_logic_vector(DATA_LENGTH-1 downto 0); signal reg_txdata:std_logic_vector(DATA_LENGTH-1 downto 0); signal rx_shift_data:std_logic_vector(DATA_LENGTH-1 downto 0); signal reg_toe:std_logic; signal reg_roe:std_logic; signal reg_trdy:std_logic; signal reg_rrdy:std_logic; signal tx_done:std_logic; signal rx_done:std_logic; signal rx_done_flip1:std_logic; signal rx_done_flip2:std_logic; signal rx_done_flip3:std_logic; signal tx_done_flip1:std_logic; signal tx_done_flip2:std_logic; signal tx_done_flip3:std_logic; signal rx_data_cnt:std_logic_vector(5 downto 0); signal tx_data_cnt:std_logic_vector(5 downto 0); begin TX_RDY<=reg_trdy; RX_RDY<=reg_rrdy; TX_ERR<=reg_toe; RX_ERR<=reg_roe; DATA_OUT<=reg_rxdata; process(CLK_I,RST_I) begin if(RST_I='1') then latch_s_data <= (others => '0'); elsif rising_edge(CLK_I) then if (WR_RD='0' and CSn='0' and reg_trdy='1') then latch_s_data <=DATA_IN; end if; end if; end process; --Receive Data Register process(CLK_I,RST_I) begin if(RST_I='1') then reg_rxdata <=(others => '0'); elsif rising_edge(CLK_I) then if (rx_done_flip1='1' and rx_done_flip2='0') then reg_rxdata <= rx_shift_data; end if; end if; end process; --Transmit Data Register process(CLK_I,RST_I) begin if(RST_I='1') then reg_txdata <= (others => '0'); elsif rising_edge(CLK_I) then reg_txdata <= latch_s_data; end if; end process; -------------------------------For Rx data, -------------------sample at posedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 0 u1: if CLOCK_POLARITY='0' and CLOCK_PHASE='0' generate process(SCLK_SLAVE,RST_I) begin if (RST_I='1') then rx_shift_data <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (CSn_SLAVE='0') then if (SHIFT_DIRECTION='1') then rx_shift_data <= MOSI_SLAVE & rx_shift_data(DATA_LENGTH-1 downto 1); else rx_shift_data <= rx_shift_data(DATA_LENGTH-2 downto 0) & MOSI_SLAVE; end if; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_data_cnt <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_data_cnt <=(others => '0'); elsif (CSn_SLAVE='0') then rx_data_cnt <=rx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_done <= '0'; elsif rising_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_done <= '1'; else rx_done <= '0'; end if; end if; end process; end generate; -------------------sample at negedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 1 u2: if CLOCK_POLARITY='0' and CLOCK_PHASE='1' generate --For Rx data, sample at negedge when CLOCK_PHASE is 1 process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_shift_data <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (CSn_SLAVE='0') then if (SHIFT_DIRECTION='1') then rx_shift_data <= MOSI_SLAVE & rx_shift_data(DATA_LENGTH-1 downto 1); else rx_shift_data <= rx_shift_data(DATA_LENGTH-2 downto 0) & MOSI_SLAVE; end if; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_data_cnt <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_data_cnt <=(others => '0'); elsif (CSn_SLAVE='0') then rx_data_cnt <=rx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_done <= '0'; elsif falling_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_done <= '1'; else rx_done <= '0'; end if; end if; end process; end generate; -------------------sample at negedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 0 u3:if CLOCK_POLARITY='1' and CLOCK_PHASE='0' generate process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_shift_data <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (CSn_SLAVE='0') then if (SHIFT_DIRECTION='1') then rx_shift_data <= MOSI_SLAVE & rx_shift_data(DATA_LENGTH-1 downto 1); else rx_shift_data <= rx_shift_data(DATA_LENGTH-2 downto 0) & MOSI_SLAVE; end if; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_data_cnt <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_data_cnt <=(others => '0'); elsif (CSn_SLAVE='0') then rx_data_cnt <=rx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_done <= '0'; elsif falling_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_done <= '1'; else rx_done <= '0'; end if; end if; end process; end generate; -------------------sample at posedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 1 u4: if CLOCK_POLARITY='1' and CLOCK_PHASE='1' generate --For Rx data, sample at negedge when CLOCK_PHASE is 1 process(SCLK_SLAVE,RST_I) begin if (RST_I='1') then rx_shift_data <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (CSn_SLAVE='0') then if (SHIFT_DIRECTION='1') then rx_shift_data <= MOSI_SLAVE & rx_shift_data(DATA_LENGTH-1 downto 1); else rx_shift_data <= rx_shift_data(DATA_LENGTH-2 downto 0) & MOSI_SLAVE; end if; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_data_cnt <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_data_cnt <=(others => '0'); elsif (CSn_SLAVE='0') then rx_data_cnt <=rx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then rx_done <= '0'; elsif rising_edge(SCLK_SLAVE) then if (rx_data_cnt = DATA_LENGTH - 1) then rx_done <= '1'; else rx_done <= '0'; end if; end if; end process; end generate; process(CLK_I,RST_I) begin if (RST_I='1') then rx_done_flip1 <= '0'; rx_done_flip2 <= '0'; rx_done_flip3 <= '0'; elsif rising_edge(CLK_I) then rx_done_flip1 <= rx_done; rx_done_flip2 <= rx_done_flip1; rx_done_flip3 <= rx_done_flip2; end if; end process; process(CLK_I,RST_I) begin if (RST_I='1') then reg_rrdy <= '0'; elsif rising_edge(CLK_I) then if (rx_done_flip2='1' and rx_done_flip3='0') then reg_rrdy <= '1'; elsif (WR_RD='1' and CSn='0') then reg_rrdy <= '0'; end if; end if; end process; process(CLK_I,RST_I) begin if (RST_I='1') then reg_roe <= '0'; elsif rising_edge(CLK_I) then if (rx_done_flip2='1' and rx_done_flip3='0' and reg_rrdy='1') then reg_roe <= '1'; elsif (WR_RD='1' and CSn='0') then reg_roe <= '0'; end if; end if; end process; ----------------------For Tx data, -------------------------------------update at negedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 0 u11: if CLOCK_POLARITY='0' and CLOCK_PHASE='0' generate process(reg_txdata,tx_data_cnt,CSn_SLAVE ) begin if (CSn_SLAVE='0') then if(SHIFT_DIRECTION='1') then MISO_SLAVE <= reg_txdata(conv_integer(tx_data_cnt)); else MISO_SLAVE <= reg_txdata(conv_integer(DATA_LENGTH-tx_data_cnt-1)); end if; else MISO_SLAVE<='Z'; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_data_cnt <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_data_cnt <= (others => '0'); elsif (CSn_SLAVE='0') then tx_data_cnt <= tx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_done <='0'; elsif falling_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_done <= '1'; else tx_done <= '0'; end if; end if; end process; end generate; -------------------------------------update at posedge when CLOCK_POLARITY=0 and CLOCK_PHASE is 1 u22: if CLOCK_POLARITY='0' and CLOCK_PHASE='1' generate process (SCLK_SLAVE) begin if rising_edge(CLK_I) then if (CSn_SLAVE='0') then if(SHIFT_DIRECTION='1') then MISO_SLAVE <= reg_txdata(conv_integer(tx_data_cnt)); else MISO_SLAVE <= reg_txdata(conv_integer(DATA_LENGTH-tx_data_cnt-1)); end if; else MISO_SLAVE<='Z'; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_data_cnt <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_data_cnt <= (others => '0'); elsif (CSn_SLAVE='0') then tx_data_cnt <= tx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_done <= '0'; elsif rising_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_done <= '1'; else tx_done <= '0'; end if; end if; end process; end generate; -------------------------------------update at posedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 0 u33: if CLOCK_POLARITY='1' and CLOCK_PHASE='0' generate process(reg_txdata,tx_data_cnt,CSn_SLAVE ) begin if (CSn_SLAVE='0') then if(SHIFT_DIRECTION='1') then MISO_SLAVE <= reg_txdata(conv_integer(tx_data_cnt)); else MISO_SLAVE <= reg_txdata(conv_integer(DATA_LENGTH-tx_data_cnt-1)); end if; else MISO_SLAVE<='Z'; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_data_cnt <= (others => '0'); elsif rising_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_data_cnt <= (others => '0'); elsif (CSn_SLAVE='0') then tx_data_cnt <= tx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_done <= '0'; elsif rising_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_done <= '1'; else tx_done <= '0'; end if; end if; end process; end generate; -------------------------------------update at negedge when CLOCK_POLARITY=1 and CLOCK_PHASE is 1 u44: if CLOCK_POLARITY='1' and CLOCK_PHASE='1' generate process (SCLK_SLAVE) begin if falling_edge(CLK_I) then if (CSn_SLAVE='0') then if(SHIFT_DIRECTION='1') then MISO_SLAVE <= reg_txdata(conv_integer(tx_data_cnt)); else MISO_SLAVE <= reg_txdata(conv_integer(DATA_LENGTH-tx_data_cnt-1)); end if; else MISO_SLAVE<='Z'; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_data_cnt <= (others => '0'); elsif falling_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_data_cnt <= (others => '0'); elsif (CSn_SLAVE='0') then tx_data_cnt <= tx_data_cnt + 1; end if; end if; end process; process(SCLK_SLAVE ,RST_I) begin if (RST_I='1') then tx_done <='0'; elsif falling_edge(SCLK_SLAVE) then if (tx_data_cnt = DATA_LENGTH - 1) then tx_done <= '1'; else tx_done <= '0'; end if; end if; end process; end generate; process(CLK_I,RST_I) begin if (RST_I='1') then tx_done_flip1 <= '0'; tx_done_flip2 <= '0'; tx_done_flip3 <= '0'; elsif rising_edge(CLK_I) then tx_done_flip1 <= tx_done; tx_done_flip2 <= tx_done_flip1; tx_done_flip3 <= tx_done_flip2; end if; end process; process(CLK_I,RST_I) begin if (RST_I='1') then reg_roe <= '0'; elsif rising_edge(CLK_I) then if (rx_done_flip2='1' and rx_done_flip3='0' and reg_rrdy='1') then reg_roe <= '1'; elsif (WR_RD='1' and CSn='0') then reg_roe <= '0'; end if; end if; end process; process(CLK_I,RST_I) begin if (RST_I='1') then reg_trdy <= '1'; elsif rising_edge(CLK_I) then if (WR_RD='0' and CSn='0') then reg_trdy <= '0'; elsif (tx_done_flip2='1' and tx_done_flip3='0') then reg_trdy <= '1'; end if; end if; end process; process(CLK_I,RST_I) begin if (RST_I='1') then reg_toe <= '0'; elsif rising_edge(CLK_I) then if(reg_trdy='0' and WR_RD='0' and CSn='0') then reg_toe <= '1'; elsif(WR_RD='0' and CSn='0') then reg_toe <= '0'; end if; end if; end process; end arch; тестбенч: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity spi_master is port( sclk_master: out std_logic; csn_master: out std_logic; mosi_master: out std_logic; miso_master: in std_logic ); end; architecture arch_spi_master of spi_master is constant CLOCK_PHASE:std_logic:='0'; constant CLOCK_POLARITY:std_logic:='0'; constant SHIFT_DIRECTION:std_logic:='0'; constant DATA_LENGTH:integer:= 8; --signal master_data_in:std_logic_vector(7 downto 0); --signal master_data_out:std_logic_vector(7 downto 0); -- --signal cnt:std_logic_vector(2 downto 0); signal sclk_master_tmp: std_logic; signal csn_master_tmp: std_logic; signal mosi_master_tmp: std_logic; function slv4_xcha (inp: STD_LOGIC_VECTOR(3 downto 0)) return CHARACTER is variable result: character; begin case inp is when "0000" => result := '0'; when "0001" => result := '1'; when "0010" => result := '2'; when "0011" => result := '3'; when "0100" => result := '4'; when "0101" => result := '5'; when "0110" => result := '6'; when "0111" => result := '7'; when "1000" => result := '8'; when "1001" => result := '9'; when "1010" => result := 'a'; when "1011" => result := 'b'; when "1100" => result := 'c'; when "1101" => result := 'd'; when "1110" => result := 'e'; when "1111" => result := 'f'; when others => result := 'x'; end case; return result; end; function slv8_xstr (inp: STD_LOGIC_VECTOR(7 downto 0)) return STRING is variable result : string (1 to 2); begin result := slv4_xcha(inp(7 downto 4)) & slv4_xcha(inp(3 downto 0)); return result; end; procedure spi_master_operation (signal sclk_master_tmp : out std_logic; signal csn_master_tmp: out std_logic; signal mosi_master_tmp: out std_logic; signal miso_master: in std_logic; constant data_out:in STD_LOGIC_VECTOR(7 downto 0); constant CLOCK_PHASE : in std_logic; constant CLOCK_POLARITY : in std_logic; constant SHIFT_DIRECTION : in std_logic; constant DATA_LENGTH : in integer ) is variable master_data_in:std_logic_vector(7 downto 0):=(others => '0'); variable master_data_out:std_logic_vector(7 downto 0):=(others => '0'); variable cnt:integer; variable i:integer; variable sclk_cycle:time:=40 ns; begin csn_master_tmp<='1'; mosi_master_tmp<='0'; report "SPI master sends data " & slv8_xstr(data_out); master_data_out:=data_out; csn_master_tmp<='0'; if(CLOCK_POLARITY='0') then if(CLOCK_PHASE='0') then cnt:=0; for i in 7 downto 0 loop if(SHIFT_DIRECTION='1') then mosi_master_tmp<=master_data_out(cnt); else mosi_master_tmp<=master_data_out(DATA_LENGTH-cnt-1); end if; wait for sclk_cycle; sclk_master_tmp<='1'; master_data_in:=(master_data_in(6 downto 0) & miso_master); wait for sclk_cycle; sclk_master_tmp<='0'; cnt:=cnt+1; end loop; wait for 2 ns; csn_master_tmp<='1'; else cnt:=0; for i in 7 downto 0 loop wait for sclk_cycle; sclk_master_tmp<='1'; if(SHIFT_DIRECTION='1') then mosi_master_tmp<=master_data_out(cnt); else mosi_master_tmp<=master_data_out(DATA_LENGTH-cnt-1); end if; cnt:=cnt+1; wait for sclk_cycle; sclk_master_tmp<='0'; master_data_in:=(master_data_in(6 downto 0) & miso_master); end loop; wait for 2 ns; csn_master_tmp<='1'; end if; else if(CLOCK_PHASE='0') then cnt:=0; for i in 7 downto 0 loop if(SHIFT_DIRECTION='1') then mosi_master_tmp<=master_data_out(cnt); else mosi_master_tmp<=master_data_out(DATA_LENGTH-cnt-1); end if; wait for sclk_cycle; sclk_master_tmp<='0'; master_data_in:=(master_data_in(6 downto 0) & miso_master); wait for sclk_cycle; sclk_master_tmp<='1'; cnt:=cnt+1; end loop; wait for 2 ns; csn_master_tmp<='1'; else cnt:=0; for i in 7 downto 0 loop wait for sclk_cycle; sclk_master_tmp<='0'; if(SHIFT_DIRECTION='1') then mosi_master_tmp<=master_data_out(cnt); else mosi_master_tmp<=master_data_out(DATA_LENGTH-cnt-1); end if; cnt:=cnt+1; wait for sclk_cycle; sclk_master_tmp<='1'; master_data_in:=(master_data_in(6 downto 0) & miso_master); end loop; wait for 2 ns; csn_master_tmp<='1'; end if; end if; report "SPI master receive data " & slv8_xstr(master_data_in); end; begin sclk_master<=sclk_master_tmp; csn_master<=csn_master_tmp; mosi_master<=mosi_master_tmp; initial: process begin --wait for 1 ns; if(CLOCK_POLARITY='1') then sclk_master_tmp<='1' after 1 ns; else sclk_master_tmp<='0'; end if; wait for 306 ns; spi_master_operation(sclk_master_tmp,csn_master_tmp,mosi_master_tmp,miso_master, "01110011",CLOCK_PHASE,CLOCK_POLARITY,SHIFT_DIRECTION,DATA_LENGTH); wait for 100 ns; spi_master_operation(sclk_master_tmp,csn_master_tmp,mosi_master_tmp,miso_master, "01000011",CLOCK_PHASE,CLOCK_POLARITY,SHIFT_DIRECTION,DATA_LENGTH); wait for 104 ns; spi_master_operation(sclk_master_tmp,csn_master_tmp,mosi_master_tmp,miso_master, "00011001",CLOCK_PHASE,CLOCK_POLARITY,SHIFT_DIRECTION,DATA_LENGTH); wait for 100 ns; spi_master_operation(sclk_master_tmp,csn_master_tmp,mosi_master_tmp,miso_master, "01010101",CLOCK_PHASE,CLOCK_POLARITY,SHIFT_DIRECTION,DATA_LENGTH); wait for 100 ns; spi_master_operation(sclk_master_tmp,csn_master_tmp,mosi_master_tmp,miso_master, "10101010",CLOCK_PHASE,CLOCK_POLARITY,SHIFT_DIRECTION,DATA_LENGTH); wait for 100 ns; wait; end process; end arch_spi_master; ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity back_end_device is port( CSn: out std_logic; DATA_IN:in STD_LOGIC_VECTOR(7 downto 0); WR_RD: out std_logic; DATA_OUT:out STD_LOGIC_VECTOR(7 downto 0); TX_RDY: in std_logic; RX_RDY: in std_logic; TX_ERR: in std_logic; RX_ERR: in std_logic; CLK: out std_logic; RST: out std_logic ); end; architecture arch_back_end_device of back_end_device is constant clk_cycle:time:=5 ns; signal clk_temp:std_logic; signal data_out_temp:STD_LOGIC_VECTOR(7 downto 0); signal i:integer:=0; function slv4_xcha_r (inp: STD_LOGIC_VECTOR(3 downto 0)) return CHARACTER is variable result: character; begin case inp is when "0000" => result := '0'; when "0001" => result := '1'; when "0010" => result := '2'; when "0011" => result := '3'; when "0100" => result := '4'; when "0101" => result := '5'; when "0110" => result := '6'; when "0111" => result := '7'; when "1000" => result := '8'; when "1001" => result := '9'; when "1010" => result := 'a'; when "1011" => result := 'b'; when "1100" => result := 'c'; when "1101" => result := 'd'; when "1110" => result := 'e'; when "1111" => result := 'f'; when others => result := 'x'; end case; return result; end; function slv8_xstr_r (inp: STD_LOGIC_VECTOR(7 downto 0)) return STRING is variable result : string (1 to 2); begin result := slv4_xcha_r(inp(7 downto 4)) & slv4_xcha_r(inp(3 downto 0)); return result; end; begin clk_gen:process begin clk_temp<='0'; wait for clk_cycle; loop clk_temp<=not clk_temp; wait for clk_cycle; end loop; end process; CLK<=clk_temp; DATA_OUT<=data_out_temp; initial: process begin RST<='0'; CSn<='1'; WR_RD<='1'; data_out_temp<=(others => '0'); wait for 2 ns; RST<='1'; wait for 202 ns; RST<='0'; while(i<3) loop wait until clk_temp'event and clk_temp = '1'; if(RX_RDY='1' or TX_RDY='1') then if(TX_RDY='1') then CSn<='0' after 1 ns; WR_RD<='0' after 1 ns; if(i=0) then data_out_temp<="00001000" after 1 ns; elsif(i=1) then data_out_temp<="11101101" after 1 ns; elsif(i=2) then data_out_temp<="11011001" after 1 ns; end if; i<=i+1; wait for 1 ns; report "Back end device send data " & slv8_xstr_r(data_out_temp); wait until clk_temp'event and clk_temp = '1'; CSn<='1' after 1 ns; WR_RD<='1' after 1 ns; elsif(RX_RDY='1') then CSn<='0' after 1 ns; WR_RD<='1' after 1 ns; report "Back end device receive data " & slv8_xstr_r(DATA_IN); wait until clk_temp'event and clk_temp = '1'; CSn<='1' after 1 ns; WR_RD<='1' after 1 ns; end if; end if; end loop; while(i=3) loop wait until clk_temp'event and clk_temp = '1'; CSn<='0' after 1 ns; WR_RD<='0' after 1 ns; data_out_temp<="11100011" after 1 ns; wait for 1 ns; report "Back end device send data " & slv8_xstr_r(data_out_temp); wait until clk_temp'event and clk_temp = '1'; CSn<='1' after 1 ns; WR_RD<='1' after 1 ns; i<=4; end loop; wait for 2500 ns; --wait; end process; end arch_back_end_device; ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity spi_speripheral_tb is end spi_speripheral_tb; architecture arch_spi_speripheral_tb of spi_speripheral_tb is component spi_slave is --generic (DATA_LENGTH : integer:=8; -- SHIFT_DIRECTION: std_logic := '0'; -- CLOCK_POLARITY:std_logic:='0'; -- CLOCK_PHASE:std_logic:='0'); port ( CSn : in std_logic; DATA_IN : in std_logic_vector(7 downto 0); WR_RD : in std_logic; DATA_OUT : out std_logic_vector(7 downto 0); TX_RDY : out std_logic; RX_RDY : out std_logic; TX_ERR : out std_logic; RX_ERR : out std_logic; CLK_I : in std_logic; RST_I : in std_logic; MISO_SLAVE : out std_logic; MOSI_SLAVE : in std_logic; CSn_SLAVE : in std_logic; SCLK_SLAVE : in std_logic ); end component; component spi_master is port( sclk_master: out std_logic; csn_master: out std_logic; mosi_master: out std_logic; miso_master: in std_logic ); end component; component back_end_device is port( CSn: out std_logic; DATA_IN: in std_logic_vector(7 downto 0); WR_RD: out std_logic; DATA_OUT: out std_logic_vector(7 downto 0); TX_RDY: in std_logic; RX_RDY: in std_logic; TX_ERR: in std_logic; RX_ERR: in std_logic; CLK: out std_logic; RST: out std_logic ); end component; signal clk,rst:std_logic; signal mosi,csn_spi,sclk:std_logic; signal csn,wr_rd:std_logic; signal data_out:std_logic_vector(7 downto 0); signal miso:std_logic; signal tx_rdy,rx_rdy,tx_err,rx_err:std_logic; signal data_in:std_logic_vector(7 downto 0); begin spi_master_uut: spi_master port map( sclk_master=>sclk, csn_master=>csn_spi, mosi_master=>mosi, miso_master=>miso ); spi_slave_uut: spi_slave port map ( CSn=>csn, DATA_IN=>data_in, WR_RD=>wr_rd, DATA_OUT=>data_out, TX_RDY=>tx_rdy, RX_RDY=>rx_rdy, TX_ERR=>tx_err, RX_ERR=>rx_err, MISO_SLAVE=>miso, MOSI_SLAVE=>mosi, CSn_SLAVE=>csn_spi, SCLK_SLAVE=>sclk, CLK_I=>clk, RST_I=>rst ); back_end_device_uut: back_end_device port map( CSn=>csn, DATA_IN=>data_out, WR_RD=>wr_rd, DATA_OUT=>data_in, TX_RDY=>tx_rdy, RX_RDY=>rx_rdy, TX_ERR=>tx_err, RX_ERR=>rx_err, CLK=>clk, RST=>rst ); end arch_spi_speripheral_tb; Значок решетка что означает? #100; (verilog) = wait for 100 ns; (vhdl) PS у меня это описание работало в "железе" PS PS Мне не жалко, в надежде, что когда мне что-то понадобиться, то тоже люди тоже откликнуться и помогут... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Благодарю вас. Эта задержка синтезируется или это только для симулятора? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Благодарю вас. Эта задержка синтезируется или это только для симулятора? только для симулятора Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Понятно. Попробовал сразу все заработало)). Частоту подал на clck_in 200Мгц , правильно ? spi_slave spi_uc(csn,datain,wr_rd,dataout,tx_rdy,rx_rdy,tx_err,rx_err,CLOCK,RESET,SDOUT_UC,SD I_UC,CS_UC,SCLCK_UC); //--------------------------------------------------------------------------// //--------------------------------------------------------------------------// always@(posedge CLOCK ) begin if(RESET == 1) begin rxtxrdwr <= 8'd0; adressreg <= 8'd0; getadres <= 1'b0; csn <= 1'b1; wr_rd <= 1'b1; for(initdatafor = 0; initdatafor < 8'd255;initdatafor = initdatafor + 8'd1) begin dataINuc[initdatafor] <= 8'd0; dataOUTuc[initdatafor] <= 8'd0; end end else begin if(CS_UC == 1) begin getadres <= 1'b0; end if(tx_rdy || rx_rdy) begin if(tx_rdy) begin csn<= 1'b0; wr_rd<= 1'b0; rxtxrdwr <= 8'd1; if(getadres == 1) begin datain <= 20;//dataOUTuc[adressreg]; end else begin datain <= 8'd0; end end else if(rx_rdy) begin csn<= 1'b0; wr_rd<= 1'b1; rxtxrdwr <= 8'd2; if(getadres == 0) begin getadres <= 1'b1; adressreg <= dataout; end else begin dataINuc[adressreg] <= dataout; end end end else begin if(rxtxrdwr == 1)begin csn<= 1'b1; wr_rd<= 1'b1; rxtxrdwr <= 8'd0; end else if(rxtxrdwr == 2)begin csn<= 1'b1; wr_rd<= 1'b1; rxtxrdwr <= 8'd0; end end end end //--------------------------------------------------------------------------// Единственное почему то последний байт не доходит например отправляю с плис 20 в мк приходит 10 и тд. Микроконтроллер вначале пробовал с mems датчиком что бы проверить правильность настройки spi интерфейса в микроконтроллере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Единственное почему то последний байт не доходит например отправляю с плис 20 в мк приходит 10 и тд. Микроконтроллер вначале пробовал с mems датчиком что бы проверить правильность настройки spi интерфейса в микроконтроллере. режимы работы SPI в мк и в плис должны совпадать. совпадают? Для обозначения режимов работы интерфейса SPI принято следующее соглашений: режим 1 (CPOL = 0, CPHA = 0); режим 2 (CPOL = 0, CPHA = 1); режим 3 (CPOL = 1, CPHA = 0); режим 4 (CPOL = 1, CPHA = 1). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Да совпадают RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_I2S_DeInit(SPI1); SPI_InitTypeDef spi1; SPI_StructInit(&spi1); spi1.SPI_Direction = SPI_Direction_2Lines_FullDuplex; spi1.SPI_Mode = SPI_Mode_Master; spi1.SPI_DataSize = SPI_DataSize_8b; spi1.SPI_CPOL = SPI_CPOL_Low; spi1.SPI_CPHA = SPI_CPHA_1Edge; spi1.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; spi1.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; spi1.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &spi1); SPI_Cmd(SPI1, ENABLE); SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); Сделал осциллограмму если правильно смотрю из плис уходит 00001010 = 10 а должно быть 00010100. Дико извиняюсь, я напортачил не правильно настроил, все работает отлично. нужно было объявить это `define CLOCK_POLARITY `define CLOCK_PHASE Это настройки spi в stm32f407 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_I2S_DeInit(SPI1); SPI_InitTypeDef spi1; SPI_StructInit(&spi1); spi1.SPI_Direction = SPI_Direction_2Lines_FullDuplex; spi1.SPI_Mode = SPI_Mode_Master; spi1.SPI_DataSize = SPI_DataSize_8b; spi1.SPI_CPOL = SPI_CPOL_Low; spi1.SPI_CPHA = SPI_CPHA_1Edge; spi1.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; spi1.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; spi1.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &spi1); SPI_Cmd(SPI1, ENABLE); SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); большое спасибо за помощь.)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
johan 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба только для симулятора Где-то читал (или сам сделал выводы :) ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика. Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Где-то читал (или сам сделал выводы :) ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика. Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ). а что оно дает для синтезатора? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба Можно как то синтезировать задержку? Иногда очень нужна, делаю либо сдвигом клока либо внешними цепочками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
johan 0 10 мая, 2015 Опубликовано 10 мая, 2015 · Жалоба а что оно дает для синтезатора? Разумеется, ничего :) Или смысл только в том, что бы видеть в симуляции времянки более красивые и приближенные к реальности (появления значения на выходе триггера) "позже", чем edge клока? Или есть еще какие-то тонкости? :rolleyes: Можно как то синтезировать задержку? Иногда очень нужна, делаю либо сдвигом клока либо внешними цепочками. А для каких целей вам надо синтезировать задержку? Вы синхронный дизайн планируете делать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nepoch 0 20 мая, 2015 Опубликовано 20 мая, 2015 (изменено) · Жалоба Где-то читал (или сам сделал выводы :) ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика. Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ). Зачем Вам задержка, если надо, чтобы у Вас часть проекта сработало через определенное время, используйте счетчик, это идеальный вариант Изменено 20 мая, 2015 пользователем Nepoch Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 20 мая, 2015 Опубликовано 20 мая, 2015 · Жалоба #1 сильно помогает "старой гвардии", привыкшей работать с такими конструкциями, во время симуляции видеть причинно-следственные связи, не заглядывая в код, а догадываясь по названиям сигналов. тем, кто учился писать RTL без #1 - его наличие/отсутствие не помогает никак, может только сбивает с толку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться