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
仿真图: