реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> модуль spi slave verilog
sergey sva
сообщение May 9 2015, 15:14
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Хочу попробовать запустить spi slave на циклоне. Поискал в сети готовые исходники, примеров много для этого интерфейса не знаю с какого начать, подскажите пожалуйста ссылку на проверенный пример, который вам понравился ))
Go to the top of the page
 
+Quote Post
Maverick
сообщение May 9 2015, 17:48
Сообщение #2


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(sergey sva @ May 9 2015, 18:14) *
Хочу попробовать запустить spi slave на циклоне. Поискал в сети готовые исходники, примеров много для этого интерфейса не знаю с какого начать, подскажите пожалуйста ссылку на проверенный пример, который вам понравился ))

CODE
`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


тестбенч:

CODE
`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...


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
sergey sva
сообщение May 10 2015, 09:03
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Благодарю за код, давайте если не жалко )).
Есть какие отличия ? На верилоге вроде компактнее получается код, конечно у меня опыта не много поэтому утверждать не буду.
Сейчас попробую протестировать на stm32f407 ep3c5e результат напишу.

Значок решетка что означает? Немного не по теме, случайно не знаете в квартусе 13,1 есть автоформатирование кода ?
Go to the top of the page
 
+Quote Post
Maverick
сообщение May 10 2015, 11:20
Сообщение #4


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(sergey sva @ May 10 2015, 12:03) *
Благодарю за код, давайте если не жалко )).
Есть какие отличия ?


описание на VHDL - функциональных отличий нет по сравнению с описанием на verilog.

CODE
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;


тестбенч:

CODE
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 Мне не жалко, в надежде, что когда мне что-то понадобиться, то тоже люди тоже откликнуться и помогут...


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
sergey sva
сообщение May 10 2015, 13:09
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Благодарю вас. Эта задержка синтезируется или это только для симулятора?
Go to the top of the page
 
+Quote Post
Maverick
сообщение May 10 2015, 13:10
Сообщение #6


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(sergey sva @ May 10 2015, 16:09) *
Благодарю вас. Эта задержка синтезируется или это только для симулятора?

только для симулятора


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
sergey sva
сообщение May 10 2015, 13:20
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Понятно. Попробовал сразу все заработало)). Частоту подал на 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 интерфейса в микроконтроллере.
Go to the top of the page
 
+Quote Post
Maverick
сообщение May 10 2015, 13:57
Сообщение #8


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(sergey sva @ May 10 2015, 16:20) *
Единственное почему то последний байт не доходит например отправляю с плис 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).


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
sergey sva
сообщение May 10 2015, 15:35
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Да совпадают
Код
    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);

Прикрепленное изображение

большое спасибо за помощь.))
Go to the top of the page
 
+Quote Post
johan
сообщение May 10 2015, 17:52
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 78
Регистрация: 3-09-12
Пользователь №: 73 371



Цитата(Maverick @ May 10 2015, 16:10) *
только для симулятора

Где-то читал (или сам сделал выводы sm.gif ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика.
Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ).



--------------------
Go to the top of the page
 
+Quote Post
Maverick
сообщение May 10 2015, 17:58
Сообщение #11


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(johan @ May 10 2015, 20:52) *
Где-то читал (или сам сделал выводы sm.gif ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика.
Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ).

а что оно дает для синтезатора?


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
sergey sva
сообщение May 10 2015, 18:30
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923



Можно как то синтезировать задержку? Иногда очень нужна, делаю либо сдвигом клока либо внешними цепочками.
Go to the top of the page
 
+Quote Post
johan
сообщение May 10 2015, 18:59
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 78
Регистрация: 3-09-12
Пользователь №: 73 371



Цитата(Maverick @ May 10 2015, 20:58) *
а что оно дает для синтезатора?

Разумеется, ничего sm.gif
Или смысл только в том, что бы видеть в симуляции времянки более красивые и приближенные к реальности (появления значения на выходе триггера) "позже", чем edge клока?
Или есть еще какие-то тонкости? rolleyes.gif

Цитата
Можно как то синтезировать задержку? Иногда очень нужна, делаю либо сдвигом клока либо внешними цепочками.

А для каких целей вам надо синтезировать задержку?
Вы синхронный дизайн планируете делать?


--------------------
Go to the top of the page
 
+Quote Post
Nepoch
сообщение May 20 2015, 17:58
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 78
Регистрация: 19-12-11
Из: Курск
Пользователь №: 68 971



Цитата(johan @ May 10 2015, 21:52) *
Где-то читал (или сам сделал выводы sm.gif ), что трюк с #1 в чистом RTL-коде это не самая интуитивная/хорошая практика.
Однако, ребята с opencores в низскоскоростных протоколах очень любят такое делать (например, I2C ).

Зачем Вам задержка, если надо, чтобы у Вас часть проекта сработало через определенное время, используйте счетчик, это идеальный вариант

Сообщение отредактировал Nepoch - May 20 2015, 17:59
Go to the top of the page
 
+Quote Post
krux
сообщение May 20 2015, 18:11
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 700
Регистрация: 2-07-12
Из: дефолт-сити
Пользователь №: 72 596



#1 сильно помогает "старой гвардии", привыкшей работать с такими конструкциями, во время симуляции видеть причинно-следственные связи, не заглядывая в код, а догадываясь по названиям сигналов.
тем, кто учился писать RTL без #1 - его наличие/отсутствие не помогает никак, может только сбивает с толку.


--------------------
провоцируем неудовлетворенных провокаторов с удовольствием.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01644 секунд с 7
ELECTRONIX ©2004-2016