forked from M-Labs/nix-servo
111 lines
2.6 KiB
Verilog
111 lines
2.6 KiB
Verilog
`timescale 1ns / 1ps
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// Company: WUT
|
|
// Engineer: Jakub Matyas
|
|
//
|
|
// Create Date: 03/02/2023 01:39:08 PM
|
|
// Design Name:
|
|
// Module Name: spi2threewire
|
|
// Project Name:
|
|
// Target Devices:
|
|
// Tool Versions:
|
|
// Description:
|
|
//
|
|
// Dependencies:
|
|
//
|
|
// Revision:
|
|
// Revision 0.01 - File Created
|
|
// Additional Comments:
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
module spi2threewire (
|
|
output ps_sclk_i,
|
|
input ps_sclk_o,
|
|
input ps_sclk_t,
|
|
|
|
output ps_mosi_i,
|
|
input ps_mosi_o,
|
|
input ps_mosi_t,
|
|
|
|
output ps_miso_i,
|
|
input ps_miso_o,
|
|
input ps_miso_t,
|
|
|
|
output ps_ss_i,
|
|
input [2:0] ps_ss,
|
|
input ps_ss_t,
|
|
|
|
output o_ss,
|
|
output o_sclk,
|
|
inout sdio
|
|
|
|
);
|
|
|
|
assign ps_sclk_i = 1'b0;
|
|
assign ps_mosi_i = 1'b0;
|
|
assign ps_ss_i = 1'b1;
|
|
|
|
|
|
reg [3:0] bit_count = 'd0;
|
|
|
|
// rd_wr_n - whether it will be READ transaction or WRITE
|
|
// first bit of the command
|
|
reg rd_wr_n = 'd0;
|
|
reg sdio_buffer_direction = 'd0;
|
|
|
|
wire s_sclk;
|
|
wire s_csn;
|
|
wire s_sdio_buffer_direction;
|
|
|
|
assign s_sclk = ps_sclk_o;
|
|
assign s_csn = ps_ss[0];
|
|
assign o_ss = s_csn;
|
|
|
|
// 1 if there is a SPI tranmsission going on (CS_N is LOW)
|
|
// AND transmission is of READ type
|
|
// 0 otherwise
|
|
assign s_sdio_buffer_direction = sdio_buffer_direction & ~s_csn;
|
|
|
|
always @(posedge s_sclk or posedge s_csn) begin
|
|
if (s_csn == 1'b1) begin
|
|
// after the transmission, fill bit counter with ZEROS
|
|
// and zero transmission type (rd_wr_n)
|
|
bit_count <= 4'd0;
|
|
rd_wr_n <= 1'b0;
|
|
end else begin
|
|
// on every rising edge increment bit counter
|
|
// sample first bit to get the knowledge of the transmission type
|
|
bit_count <= (bit_count < 4'd15) ? bit_count + 1'b1 : bit_count;
|
|
if (bit_count == 4'b0)
|
|
rd_wr_n <= ps_mosi_o;
|
|
end
|
|
end
|
|
|
|
always @(negedge s_sclk or posedge s_csn) begin
|
|
if (s_csn == 1'b1)
|
|
sdio_buffer_direction <= 1'b0;
|
|
else begin
|
|
if (bit_count == 4'd8)
|
|
// after the 8th bit, on falling edge,
|
|
// set the SDIO buffer direction
|
|
// accordingly to the transmission type
|
|
sdio_buffer_direction <= rd_wr_n;
|
|
end
|
|
end
|
|
|
|
|
|
IOBUF IOBUF_inst (
|
|
.O(ps_miso_i),
|
|
.IO(sdio),
|
|
.I(ps_mosi_o),
|
|
.T(s_sdio_buffer_direction) // 3-state enable input, high=input (from ext), low=output
|
|
);
|
|
|
|
OBUFT sclk_buf (
|
|
.O(o_sclk),
|
|
.I(ps_sclk_o),
|
|
.T('b0)
|
|
);
|
|
|
|
endmodule |