Initial commit
This commit is contained in:
106
i2c_receiver.sv
Normal file
106
i2c_receiver.sv
Normal file
@@ -0,0 +1,106 @@
|
||||
`timescale 1ps/1ps
|
||||
`default_nettype none
|
||||
|
||||
module i2c_receiver
|
||||
(input wire clock,
|
||||
input wire reset,
|
||||
|
||||
input wire i_scl,
|
||||
input wire i_sdi,
|
||||
output wire o_sdo,
|
||||
|
||||
output wire [7:0] o_data,
|
||||
output wire o_strobe,
|
||||
output wire o_start,
|
||||
output wire o_stop,
|
||||
input wire i_ack); // Active ONE
|
||||
|
||||
logic sdi_prev;
|
||||
logic scl_prev;
|
||||
logic start_condition;
|
||||
logic stop_condition;
|
||||
logic scl_rise;
|
||||
logic scl_fall;
|
||||
|
||||
always_ff @(posedge clock)
|
||||
if (reset) begin
|
||||
sdi_prev <= 1'b1;
|
||||
scl_prev <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
sdi_prev <= i_sdi;
|
||||
scl_prev <= i_scl;
|
||||
end
|
||||
|
||||
assign start_condition = (sdi_prev == 1'b1) && (i_sdi == 1'b0) && (scl_prev == 1'b1) && (i_scl == 1'b1);
|
||||
assign stop_condition = (sdi_prev == 1'b0) && (i_sdi == 1'b1) && (scl_prev == 1'b1) && (i_scl == 1'b1);
|
||||
assign scl_rise = (scl_prev == 1'b0) && (i_scl == 1'b1);
|
||||
assign scl_fall = (scl_prev == 1'b1) && (i_scl == 1'b0);
|
||||
|
||||
enum int unsigned {
|
||||
ST_WAIT_FOR_START = 0,
|
||||
ST_RECEIVE_BITS,
|
||||
ST_WAIT_FOR_SCL_LOW,
|
||||
ST_SEND_ACK
|
||||
} state;
|
||||
|
||||
logic [2:0] bit_cntr;
|
||||
logic [7:0] data_sr;
|
||||
logic byte_strobe;
|
||||
logic sdo;
|
||||
|
||||
always_ff @(posedge clock)
|
||||
if (reset) begin
|
||||
state <= ST_WAIT_FOR_START;
|
||||
bit_cntr <= '0;
|
||||
byte_strobe <= 1'b0;
|
||||
sdo <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
byte_strobe <= 1'b0;
|
||||
|
||||
if (stop_condition)
|
||||
state <= ST_WAIT_FOR_START;
|
||||
else
|
||||
case (state)
|
||||
ST_WAIT_FOR_START: begin
|
||||
sdo <= 1'b1;
|
||||
|
||||
if (start_condition) begin
|
||||
bit_cntr <= '0;
|
||||
state <= ST_RECEIVE_BITS;
|
||||
end
|
||||
end
|
||||
|
||||
ST_RECEIVE_BITS:
|
||||
if (scl_rise) begin
|
||||
data_sr <= {data_sr[6:0], i_sdi};
|
||||
bit_cntr <= bit_cntr + 1'b1;
|
||||
|
||||
if (bit_cntr == 3'd7) begin
|
||||
state <= ST_WAIT_FOR_SCL_LOW;
|
||||
byte_strobe <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
ST_WAIT_FOR_SCL_LOW:
|
||||
if (scl_fall) begin
|
||||
sdo <= i_ack ? 1'b0 : 1'b1;
|
||||
state <= ST_SEND_ACK;
|
||||
end
|
||||
|
||||
ST_SEND_ACK:
|
||||
if (scl_fall) begin
|
||||
sdo <= 1'b1;
|
||||
state <= ST_RECEIVE_BITS;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
assign o_data = data_sr;
|
||||
assign o_strobe = byte_strobe;
|
||||
assign o_start = start_condition;
|
||||
assign o_stop = stop_condition;
|
||||
assign o_sdo = sdo;
|
||||
|
||||
endmodule // i2c_receiver
|
||||
Reference in New Issue
Block a user