SPI通信---verilog(全双工)
做一个全双工的通信方式,可以一边发送一边接收,速度会快,但是感觉实用性不大。根据具体的情况再做修改吧。
读取结果没有引出,输入地址也没有引出,在程序中固化了。
程序:
/********************************Copyright**************************************
**----------------------------File information--------------------------
** File name :spi_main_2.v
** CreateDate :2015.04
** Funtions : SPI作为主机的全双工模式,一边发送地址数据一边接收数据
** Operate on :M5C06N3L114C7
** Copyright :All rights reserved.
** Version :V1.0
**---------------------------Modify the file information----------------
** Modified by :
** Modified data :
** Modify Content:
*******************************************************************************/
module spi_main_2 (
clk,
rst_n,
txd_rd_en,
spi_cs,
spi_sck,
spi_miso,
spi_mosi
);
input clk;
input rst_n;
input txd_rd_en;
output reg spi_cs;
output reg spi_sck;
output reg spi_mosi;
input spi_miso;
`define addr_1 8'h01
`define addr_2 8'h02
`define addr_3 8'h03
//---------------------------
reg [3:0] state;
reg txd_en;
reg [7:0] rxd_data_1;
reg [7:0] rxd_data_2;
reg [7:0] rxd_data_3;
reg txd_over;
reg [7:0] txd_data_reg;
reg [7:0] rxd_data_shift;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= 0;
txd_en<= 0;
rxd_data_1 <= 0;
rxd_data_2 <= 0;
rxd_data_3 <= 0;
spi_cs <= 1;
txd_data_reg <= 8'd0;
end
else
begin
case(state)
'd0:
begin
txd_en<= 0;
spi_cs <= 1;
txd_data_reg <= 8'd0;
if(txd_rd_en)
state <= 'd1;
end
'd1:
begin
spi_cs <= 0;
state <= 'd2;
end
'd2:
begin
if(txd_over)
begin
txd_data_reg <= 8'h00;
txd_en<= 0;
state <= 'd3;
end
else
begin
txd_data_reg <= `addr_1;
txd_en<= 1;
end
end
'd3:
begin
if(txd_over)
begin
txd_data_reg <= 8'h00;
txd_en<= 0;
state <= 'd4;
rxd_data_1 <= rxd_data_shift;
end
else
begin
txd_data_reg <= `addr_2;
txd_en<= 1;
end
end
'd4:
begin
if(txd_over)
begin
txd_data_reg <= 8'h00;
txd_en<= 0;
state <= 'd5;
rxd_data_2 <= rxd_data_shift;
end
else
begin
txd_data_reg <= `addr_3;
txd_en<= 1;
end
end
'd5:
begin
if(txd_over)
begin
txd_data_reg <= 8'h00;
txd_en<= 0;
state <= 'd6;
rxd_data_3 <= rxd_data_shift;
end
else
begin
txd_data_reg <= 8'h00;
txd_en<= 1;
end
end
'd6:
begin
spi_cs <= 1;
state <= 'd0;
end
default : state <= 'd0;
endcase
end
end
//----------------------------
reg [3:0] state_bit;
reg [3:0] cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
spi_sck <= 0;
spi_mosi <= 0;
state_bit <= 0;
cnt <= 0;
rxd_data_shift <= 0;
txd_over <= 0;
end
else if(txd_en)
begin
case(state_bit)
'd0:
begin
spi_sck <= 0;
spi_mosi <= 0;
state_bit <= 'd1;
cnt <= 0;
rxd_data_shift <= 0;
end
'd1:
begin
spi_mosi <= txd_data_reg[7-cnt[2:0]]; /* 先发送最高位 */
state_bit <= 'd2;
end
'd2:
begin
spi_sck <= 1;
state_bit <= 'd3;
end
'd3:
begin
cnt <= cnt + 1;
state_bit <= 'd4;
end
'd4:
begin
spi_sck <= 0;
state_bit <= 'd5;
end
'd5:
begin
rxd_data_shift[0] <= spi_miso;
if(cnt == 8)
begin
cnt <= 0;
state_bit <= 'd7;
end
else
state_bit <= 'd6;
end
'd6:
begin
state_bit <= 'd1;
rxd_data_shift <= rxd_data_shift << 1;
end
'd7:
begin
txd_over <= 1;
state_bit <= 'd8;
end
'd8:
begin
txd_over <= 0;
state_bit <= 'd8;
end
default:state_bit <= 'd0;
endcase
end
else
begin
spi_sck <= 0;
spi_mosi <= 0;
state_bit <= 0;
cnt <= 0;
rxd_data_shift <= 0;
txd_over <= 0;
end
end
endmodule
测试程序:
/********************************Copyright************************************** **----------------------------File information-------------------------- ** File name :api_main_tb.v ** CreateDate :2015.04 ** Funtions : 测试文件 ** Operate on :M5C06N3L114C7 ** Copyright :All rights reserved. ** Version :V1.0 **---------------------------Modify the file information---------------- ** Modified by : ** Modified data : ** Modify Content: *******************************************************************************/ module api_main_tb; reg clk; reg rst_n; reg txd_rd_en; wire spi_cs; wire spi_sck; wire spi_mosi; reg spi_miso; spi_main_2 spi_main_2_1( .clk, .rst_n, .txd_rd_en, .spi_cs, .spi_sck, .spi_miso, .spi_mosi ); parameter tck = 24; parameter t = 1000/tck; always #(t/2) clk = ~clk; always #(t*2) spi_miso = ~spi_miso; initial begin clk= 0; rst_n = 0; spi_miso = 0; txd_rd_en = 0; #(5*t) rst_n = 1; #(2*t) txd_rd_en = 1; #(2*t) txd_rd_en = 0; end endmodule
仿真图:


浙公网安备 33010602011771号