read bytes 0 to 63 of spd then store (sim passing)
This commit is contained in:
parent
fbc4b5ff9a
commit
75857a0af0
|
|
@ -0,0 +1,20 @@
|
|||
############## clock define##################
|
||||
create_clock -period 5.000 [get_ports sys_clk_p]
|
||||
set_property IOSTANDARD DIFF_SSTL15 [get_ports sys_clk_p]
|
||||
# no need to constrain N side (only P side) or else tool will analyze interclock oaths and show failure in timing
|
||||
# https://support.xilinx.com/s/article/57109?language=en_US
|
||||
#create_clock -period 5.000 [get_ports sys_clk_n]
|
||||
set_property PACKAGE_PIN AE10 [get_ports sys_clk_p]
|
||||
set_property PACKAGE_PIN AF10 [get_ports sys_clk_n]
|
||||
set_property IOSTANDARD DIFF_SSTL15 [get_ports sys_clk_n]
|
||||
############## SODIMM SPD define##################
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports i2c_scl]
|
||||
set_property PACKAGE_PIN B20 [get_ports i2c_scl]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports i2c_sda]
|
||||
set_property PACKAGE_PIN C20 [get_ports i2c_sda]
|
||||
############## fan define##################
|
||||
set_property IOSTANDARD LVCMOS25 [get_ports fan_pwm]
|
||||
set_property PACKAGE_PIN AE26 [get_ports fan_pwm]
|
||||
############## key define##################
|
||||
set_property PACKAGE_PIN AG27 [get_ports i_rst_n]
|
||||
set_property IOSTANDARD LVCMOS25 [get_ports i_rst_n]
|
||||
|
|
@ -7,7 +7,10 @@ module spd_reader (
|
|||
input wire i_rst_n,
|
||||
// i2c interface
|
||||
inout wire i2c_scl,
|
||||
inout wire i2c_sda
|
||||
inout wire i2c_sda,
|
||||
// state of spd reader
|
||||
(* mark_debug = "true" *) output reg find_i2c_address_done,
|
||||
(* mark_debug = "true" *) output reg read_spd_done
|
||||
// uart interface
|
||||
// input uart_rx,
|
||||
// output uart_tx
|
||||
|
|
@ -25,9 +28,9 @@ module spd_reader (
|
|||
localparam I2C_ADDRESS = 7'h30;
|
||||
localparam IDLE = 0,
|
||||
READ_ADDRESS = 1,
|
||||
READ_BYTE = 1,
|
||||
WAIT_ACK = 2;
|
||||
(* mark_debug = "true" *) reg[1:0] state_find_i2c_address;
|
||||
(* mark_debug = "true" *) reg find_i2c_address_done;
|
||||
(* mark_debug = "true" *) reg[6:0] i2c_address;
|
||||
|
||||
// i2c master interface
|
||||
|
|
@ -38,7 +41,27 @@ module spd_reader (
|
|||
wire[7:0] miso_data;
|
||||
wire busy;
|
||||
wire slave_nack;
|
||||
|
||||
(* mark_debug = "true" *) reg nack_unexpected_err;
|
||||
(* mark_debug = "true" *) reg[2:0] state_read_spd;
|
||||
(* mark_debug = "true" *) reg[5:0] byte_address; // read until byte 63
|
||||
(* mark_debug = "true" *) reg[7:0] byte_data[63:0];
|
||||
|
||||
|
||||
// initialize in case fpga starts with no reset
|
||||
initial begin
|
||||
state_find_i2c_address = IDLE;
|
||||
find_i2c_address_done = 0;
|
||||
enable = 1'b0;
|
||||
read_write = 1'b0;
|
||||
register_address = 8'd0;
|
||||
i2c_address = 7'd0;
|
||||
read_spd_done = 1'b0;
|
||||
nack_unexpected_err = 1'b0;
|
||||
state_read_spd = IDLE;
|
||||
byte_address = 6'h00;
|
||||
end
|
||||
|
||||
// main FSM
|
||||
always @(posedge i_clk, negedge i_rst_n) begin
|
||||
if(!i_rst_n) begin
|
||||
state_find_i2c_address <= IDLE;
|
||||
|
|
@ -47,13 +70,17 @@ module spd_reader (
|
|||
read_write <= 1'b0;
|
||||
register_address <= 8'd0;
|
||||
i2c_address <= 7'd0;
|
||||
read_spd_done <= 1'b0;
|
||||
nack_unexpected_err <= 1'b0;
|
||||
state_read_spd <= IDLE;
|
||||
byte_address <= 6'h00;
|
||||
end
|
||||
else begin
|
||||
// Find I2C Address of SPD
|
||||
case(state_find_i2c_address)
|
||||
IDLE: if(!find_i2c_address_done) begin
|
||||
state_find_i2c_address <= READ_ADDRESS;
|
||||
i2c_address <= 7'd0;
|
||||
i2c_address <= 7'h01; // start brute force find i2c address from 1 (0 might be general call)
|
||||
end
|
||||
READ_ADDRESS: if(!busy) begin
|
||||
enable <= 1'b1;
|
||||
|
|
@ -71,10 +98,44 @@ module spd_reader (
|
|||
state_find_i2c_address <= IDLE;
|
||||
find_i2c_address_done <= 1'b1;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
enable <= 1'b0;
|
||||
end
|
||||
default: state_find_i2c_address <= IDLE;
|
||||
endcase
|
||||
|
||||
// read bytes from SPD
|
||||
case(state_read_spd)
|
||||
IDLE: if(find_i2c_address_done && !read_spd_done && !nack_unexpected_err) begin // start read SPD only once i2c address is found
|
||||
state_read_spd <= READ_BYTE;
|
||||
byte_address <= 6'h00; // start read from byte 0
|
||||
end
|
||||
else begin
|
||||
enable <= 1'b0;
|
||||
READ_BYTE: if(!busy) begin // if not busy, send i2c read transaction
|
||||
enable <= 1'b1;
|
||||
read_write <= 1'b1; // read i2c
|
||||
register_address <= {2'b00,byte_address};
|
||||
device_address <= i2c_address;
|
||||
state_read_spd <= WAIT_ACK;
|
||||
end
|
||||
WAIT_ACK: if(!busy && !enable) begin
|
||||
if(slave_nack) begin // if i2c_address NACKS, then something is wrong, raise nack_unexpected_err
|
||||
nack_unexpected_err <= 1'b1;
|
||||
state_read_spd <= IDLE;
|
||||
end
|
||||
else begin // I2C acks so store the received byte
|
||||
byte_data[byte_address] <= miso_data;
|
||||
state_read_spd <= READ_BYTE;
|
||||
byte_address <= byte_address + 1;
|
||||
if(byte_address == 63) begin
|
||||
read_spd_done <= 1'b1;
|
||||
state_read_spd <= IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
enable <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,15 +9,21 @@ module spd_reader_top (
|
|||
// i2c interface
|
||||
inout wire i2c_scl,
|
||||
inout wire i2c_sda,
|
||||
output wire i2c_lsb,
|
||||
// fan
|
||||
output wire fan_pwm
|
||||
output wire fan_pwm,
|
||||
//Debug LEDs
|
||||
output wire[3:0] led
|
||||
);
|
||||
assign fan_pwm = 1'b0; // turn on fan
|
||||
assign i2c_lsb = 1'b0;
|
||||
|
||||
wire clk_locked;
|
||||
wire main_clk_100;
|
||||
wire find_i2c_address_done, read_spd_done;
|
||||
|
||||
assign fan_pwm = 1'b0; // turn on fan from the start
|
||||
assign led[0] = find_i2c_address_done; // lights up once done
|
||||
assign led[1] = find_i2c_address_done;
|
||||
assign led[2] = read_spd_done;
|
||||
assign led[3] = read_spd_done;
|
||||
|
||||
//===========================================================================
|
||||
//Differentia system clock to single end clock
|
||||
|
|
@ -51,7 +57,9 @@ module spd_reader_top (
|
|||
.i_clk(main_clk_100),
|
||||
.i_rst_n(i_rst_n && clk_locked),
|
||||
.i2c_scl(i2c_scl),
|
||||
.i2c_sda(i2c_sda)
|
||||
.i2c_sda(i2c_sda),
|
||||
.find_i2c_address_done(find_i2c_address_done),
|
||||
.read_spd_done(read_spd_done)
|
||||
);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ module i2c_slave (scl, sda);
|
|||
//
|
||||
// parameters
|
||||
//
|
||||
parameter I2C_ADR = 7'b001_0000;
|
||||
parameter I2C_ADR = 7'b000_0100;
|
||||
|
||||
//
|
||||
// input && outpus
|
||||
|
|
@ -86,13 +86,13 @@ module i2c_slave (scl, sda);
|
|||
wire debug = 1'b1;
|
||||
genvar i;
|
||||
|
||||
reg [7:0] mem [3:0]; // initiate memory
|
||||
reg [7:0] mem [99:0]; // initiate memory
|
||||
|
||||
integer index;
|
||||
initial begin
|
||||
mem[0] = 8'd00;
|
||||
mem[1] = 8'd01;
|
||||
mem[2] = 8'd02;
|
||||
mem[3] = 8'd03;
|
||||
for (index = 0; index <= 100; index = index + 1) begin
|
||||
mem[index] = index; // Assign each element with its index value
|
||||
end
|
||||
end
|
||||
|
||||
reg [7:0] mem_adr; // memory address
|
||||
|
|
@ -350,14 +350,14 @@ module i2c_slave (scl, sda);
|
|||
fast_tsu_sto = 600,
|
||||
fast_tbuf = 1300;
|
||||
|
||||
$width(negedge scl, normal_scl_low); // scl low time
|
||||
$width(posedge scl, normal_scl_high); // scl high time
|
||||
// $width(negedge scl, normal_scl_low); // scl low time
|
||||
// $width(posedge scl, normal_scl_high); // scl high time
|
||||
|
||||
$setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
|
||||
$setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
|
||||
$setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
|
||||
// $setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
|
||||
// $setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
|
||||
// $setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
|
||||
|
||||
$setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time
|
||||
// $setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ module spd_reader_tb;
|
|||
.i_rst_n(rst_n),
|
||||
// i2c interface
|
||||
.i2c_scl(scl),
|
||||
.i2c_sda(sda),
|
||||
.i2c_lsb(),
|
||||
// fan
|
||||
.fan_pwm()
|
||||
.i2c_sda(sda)
|
||||
);
|
||||
|
||||
initial begin
|
||||
|
|
@ -28,7 +25,7 @@ module spd_reader_tb;
|
|||
rst_n = 0;
|
||||
#100;
|
||||
rst_n = 1;
|
||||
wait(DUT.spd_reader_inst.find_i2c_address_done);
|
||||
wait(DUT.spd_reader_inst.read_spd_done);
|
||||
#10_000;
|
||||
$stop;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue