added uart to display spd report
This commit is contained in:
parent
253d9495ca
commit
7acaf34b44
|
|
@ -24,10 +24,14 @@ set_property IOSTANDARD LVCMOS25 [get_ports i_rst_n]
|
|||
|
||||
##############LED define##################
|
||||
set_property PACKAGE_PIN A22 [get_ports {led[0]}]
|
||||
set_property IOSTANDARD LVCMOS15 [get_ports {led[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
|
||||
set_property PACKAGE_PIN C19 [get_ports {led[1]}]
|
||||
set_property IOSTANDARD LVCMOS15 [get_ports {led[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
|
||||
set_property PACKAGE_PIN B19 [get_ports {led[2]}]
|
||||
set_property IOSTANDARD LVCMOS15 [get_ports {led[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
|
||||
set_property PACKAGE_PIN E18 [get_ports {led[3]}]
|
||||
set_property IOSTANDARD LVCMOS15 [get_ports {led[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
|
||||
|
||||
##############uart define###########################
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports uart_tx]
|
||||
set_property PACKAGE_PIN AK26 [get_ports uart_tx]
|
||||
|
|
@ -10,10 +10,9 @@ module spd_reader (
|
|||
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
|
||||
(* mark_debug = "true" *) output reg read_spd_done,
|
||||
// uart interface
|
||||
// input uart_rx,
|
||||
// output uart_tx
|
||||
output wire uart_tx
|
||||
);
|
||||
|
||||
// byte 2: DRAM Device Type (DDR3 SDRAM = 0x0B)
|
||||
|
|
@ -29,7 +28,13 @@ module spd_reader (
|
|||
localparam IDLE = 0,
|
||||
READ_ADDRESS = 1,
|
||||
READ_BYTE = 1,
|
||||
WAIT_ACK = 2;
|
||||
SEND_BYTE = 1,
|
||||
WAIT_ACK = 2,
|
||||
WAIT_SEND = 2,
|
||||
DONE_FIND_ADDRESS = 3,
|
||||
UART_SEND = 3,
|
||||
WAIT_UART_DONE = 4;
|
||||
|
||||
(* mark_debug = "true" *) reg[1:0] state_find_i2c_address;
|
||||
(* mark_debug = "true" *) reg[6:0] i2c_address;
|
||||
|
||||
|
|
@ -45,7 +50,18 @@ module spd_reader (
|
|||
(* 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];
|
||||
|
||||
// uart interface
|
||||
wire uart_tx_busy;
|
||||
reg uart_tx_en;
|
||||
reg[7:0] uart_tx_data;
|
||||
reg[30*8-1:0] uart_text; // max of 30 chars
|
||||
reg[2:0] state_uart_send;
|
||||
reg uart_start_send;
|
||||
reg[9:0] uart_text_length,uart_text_length_index;
|
||||
reg uart_send_done;
|
||||
reg skip_byte;
|
||||
reg[7:0] mtb_dividend, mtb;
|
||||
reg[3:0] tras_high;
|
||||
|
||||
// initialize in case fpga starts with no reset
|
||||
initial begin
|
||||
|
|
@ -59,9 +75,21 @@ module spd_reader (
|
|||
nack_unexpected_err = 1'b0;
|
||||
state_read_spd = IDLE;
|
||||
byte_address = 6'h00;
|
||||
state_uart_send = IDLE;
|
||||
uart_text_length_index = 0;
|
||||
uart_tx_en = 0;
|
||||
uart_send_done = 0;
|
||||
uart_tx_data = 0;
|
||||
uart_start_send = 0;
|
||||
uart_text_length = 0;
|
||||
uart_text = {(30*8){1'b0}};
|
||||
skip_byte = 0;
|
||||
mtb_dividend = 0;
|
||||
mtb = 0;
|
||||
tras_high = 0;
|
||||
end
|
||||
|
||||
// main FSM
|
||||
// FSM for I2C
|
||||
always @(posedge i_clk, negedge i_rst_n) begin
|
||||
if(!i_rst_n) begin
|
||||
state_find_i2c_address <= IDLE;
|
||||
|
|
@ -74,6 +102,13 @@ module spd_reader (
|
|||
nack_unexpected_err <= 1'b0;
|
||||
state_read_spd <= IDLE;
|
||||
byte_address <= 6'h00;
|
||||
uart_start_send <= 0;
|
||||
uart_text_length = 0;
|
||||
uart_text = {(30*8){1'b0}};
|
||||
skip_byte <= 1'b0;
|
||||
mtb_dividend <= 0;
|
||||
mtb <= 0;
|
||||
tras_high <= 0;
|
||||
end
|
||||
else begin
|
||||
// Find I2C Address of SPD
|
||||
|
|
@ -95,13 +130,25 @@ module spd_reader (
|
|||
state_find_i2c_address <= READ_ADDRESS;
|
||||
end
|
||||
else begin // I2C acks so i2c_address is correct!
|
||||
state_find_i2c_address <= IDLE;
|
||||
find_i2c_address_done <= 1'b1;
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 18;
|
||||
uart_text[30*8-1:8*3] <= "I2C Address: 0x";
|
||||
uart_text[8*3-1:8*2] <= hex_to_ascii(i2c_address[6:4]);
|
||||
uart_text[8*2-1:8*1] <= hex_to_ascii(i2c_address[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
state_find_i2c_address <= DONE_FIND_ADDRESS;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
enable <= 1'b0;
|
||||
end
|
||||
DONE_FIND_ADDRESS: if(uart_send_done) begin
|
||||
state_find_i2c_address <= IDLE;
|
||||
find_i2c_address_done <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
uart_start_send <= 1'b0;
|
||||
end
|
||||
default: state_find_i2c_address <= IDLE;
|
||||
endcase
|
||||
|
||||
|
|
@ -110,6 +157,8 @@ module spd_reader (
|
|||
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
|
||||
uart_start_send <= 1'b0;
|
||||
skip_byte <= 1'b0;
|
||||
end
|
||||
READ_BYTE: if(!busy) begin // if not busy, send i2c read transaction
|
||||
enable <= 1'b1;
|
||||
|
|
@ -123,23 +172,249 @@ module spd_reader (
|
|||
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
|
||||
else begin // I2C acks so send via UART the received data
|
||||
state_read_spd <= UART_SEND;
|
||||
// byte_data[byte_address] <= miso_data;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
enable <= 1'b0;
|
||||
end
|
||||
UART_SEND: begin
|
||||
case(byte_address)
|
||||
0: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 15;
|
||||
uart_text[30*8-1:8] <= "START SPD READ";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
1: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 18;
|
||||
uart_text[30*8-1:8*4] <= "SPD Revision: ";
|
||||
uart_text[8*4-1:8*3] <= hex_to_ascii(miso_data[7:4]);
|
||||
uart_text[8*3-1:8*2] <= ".";
|
||||
uart_text[8*2-1:8*1] <= hex_to_ascii(miso_data[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
2: begin
|
||||
if(miso_data == 8'h0b) begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 22;
|
||||
uart_text[30*8-1:8] <= "DRAM Type: DDR3 SDRAM";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
else begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 21;
|
||||
uart_text[30*8-1:8] <= "DRAM Type: NOT DDR3!";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
end
|
||||
3: begin
|
||||
case(miso_data)
|
||||
8'h00: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 24;
|
||||
uart_text[30*8-1:8] <= "Module Type: Undefined!";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
8'h01: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 19;
|
||||
uart_text[30*8-1:8] <= "Module Type: RDIMM";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
8'h02: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 19;
|
||||
uart_text[30*8-1:8] <= "Module Type: UDIMM";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
8'h03: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 21;
|
||||
uart_text[30*8-1:8] <= "Module Type: SO-DIMM";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
4: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 29;
|
||||
uart_text[30*8-1:8*20] <= "BA_BITS: ";
|
||||
uart_text[8*20-1:8*19] <= hex_to_ascii(miso_data[6:4]+3);
|
||||
uart_text[8*19-1:8*18] <= 8'h0a;
|
||||
uart_text[8*18-1:8*2] <= "SDRAM_CAPACITY: ";
|
||||
uart_text[8*2-1:8*1] <= hex_to_ascii(miso_data[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
5: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 26;
|
||||
uart_text[30*8-1:8*16] <= "ROW_BITS: ";
|
||||
case(miso_data[5:3])
|
||||
0: uart_text[8*16-1:8*14] <= "12";
|
||||
1: uart_text[8*16-1:8*14] <= "13";
|
||||
2: uart_text[8*16-1:8*14] <= "14";
|
||||
3: uart_text[8*16-1:8*14] <= "15";
|
||||
4: uart_text[8*16-1:8*14] <= "16";
|
||||
endcase
|
||||
uart_text[8*14-1:8*13] <= 8'h0a;
|
||||
uart_text[8*13-1:8*3] <= "COL_BITS: ";
|
||||
case(miso_data[2:0])
|
||||
0: uart_text[8*3-1:8*1] <= "9 ";
|
||||
1: uart_text[8*3-1:8*1] <= "10";
|
||||
2: uart_text[8*3-1:8*1] <= "11";
|
||||
3: uart_text[8*3-1:8*1] <= "12";
|
||||
endcase
|
||||
uart_text[8*1-1:8*0] <= 8'h0a;
|
||||
end
|
||||
7: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 18;
|
||||
if(miso_data[5:3] == 0) begin
|
||||
uart_text[30*8-1:8] <= "DUAL_RANK_DIMM: 1";
|
||||
end
|
||||
else begin
|
||||
uart_text[30*8-1:8] <= "DUAL_RANK_DIMM: 0";
|
||||
end
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
8: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 14;
|
||||
case(miso_data[2:0])
|
||||
0: uart_text[30*8-1:8] <= "BYTE_LANES: 1";
|
||||
1: uart_text[30*8-1:8] <= "BYTE_LANES: 2";
|
||||
2: uart_text[30*8-1:8] <= "BYTE_LANES: 4";
|
||||
3: uart_text[30*8-1:8] <= "BYTE_LANES: 8";
|
||||
endcase
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
10: begin
|
||||
mtb_dividend = miso_data;
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 30;
|
||||
uart_text[30*8-1:8*1] <= "----- timing parameters -----";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
11: begin
|
||||
mtb = mtb_dividend*1000/miso_data;
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 15;
|
||||
uart_text[30*8-1:8*8] <= "mtb: 0x";
|
||||
uart_text[8*8-1:8*7] <= hex_to_ascii(mtb[7:4]);
|
||||
uart_text[7*8-1:8*6] <= hex_to_ascii(mtb[3:0]);
|
||||
uart_text[6*8-1:8*1] <= " (ps)";
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
18: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 17;
|
||||
uart_text[30*8-1:8*3] <= "TRCD: mtb * 0x";
|
||||
uart_text[3*8-1:8*2] <= hex_to_ascii(miso_data[7:4]);
|
||||
uart_text[2*8-1:8*1] <= hex_to_ascii(miso_data[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
20: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 16;
|
||||
uart_text[30*8-1:8*3] <= "TRP: mtb * 0x";
|
||||
uart_text[3*8-1:8*2] <= hex_to_ascii(miso_data[7:4]);
|
||||
uart_text[2*8-1:8*1] <= hex_to_ascii(miso_data[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
21: begin
|
||||
tras_high = miso_data[3:0];
|
||||
end
|
||||
22: begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text_length <= 18;
|
||||
uart_text[30*8-1:8*4] <= "TRAS: mtb * 0x";
|
||||
uart_text[4*8-1:8*3] <= hex_to_ascii(tras_high[3:0]);
|
||||
uart_text[3*8-1:8*2] <= hex_to_ascii(miso_data[7:4]);
|
||||
uart_text[2*8-1:8*1] <= hex_to_ascii(miso_data[3:0]);
|
||||
uart_text[7:0] <= 8'h0a;
|
||||
end
|
||||
default: begin
|
||||
skip_byte <= 1;
|
||||
end
|
||||
endcase
|
||||
state_read_spd <= WAIT_UART_DONE;
|
||||
end
|
||||
WAIT_UART_DONE: if(uart_send_done || skip_byte) begin
|
||||
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
|
||||
skip_byte <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
uart_start_send <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// FSM for uart
|
||||
// uart_text = "Hello" , uart_text_length = 5
|
||||
// [5<<3-1 (39):4<<3 (32)] = "H" , [4<<3-1 (31):3<<3(24)] = "e" , [3<<3-1(23):2<<3(16)] = "l" , [2<<3-1(15):1<<3(8)] = "l" , [1<<3-1(7):0<<3(0)] = "o"
|
||||
always @(posedge i_clk, negedge i_rst_n) begin
|
||||
if(!i_rst_n) begin
|
||||
state_uart_send <= IDLE;
|
||||
uart_text_length_index <= 0;
|
||||
uart_tx_en <= 0;
|
||||
uart_send_done <= 0;
|
||||
uart_tx_data <= 0;
|
||||
end
|
||||
else begin
|
||||
case(state_uart_send)
|
||||
IDLE: if (uart_start_send) begin // if receive request to send via uart
|
||||
state_uart_send <= SEND_BYTE;
|
||||
uart_text_length_index <= uart_text_length-1;
|
||||
end
|
||||
else begin
|
||||
uart_tx_en <= 1'b0;
|
||||
uart_send_done <= 1'b0;
|
||||
end
|
||||
SEND_BYTE: if(!uart_tx_busy) begin // if uart tx is not busy, send character
|
||||
uart_tx_en <= 1'b1;
|
||||
uart_tx_data <= uart_text[((uart_text_length_index)<<3) +: 8];
|
||||
end
|
||||
else begin // once busy, go to wait state
|
||||
state_uart_send <= WAIT_SEND;
|
||||
uart_tx_en <= 1'b0;
|
||||
end
|
||||
WAIT_SEND: if(!uart_tx_busy) begin // if not busy again, then uart is done sending
|
||||
if(uart_text_length_index != 0) begin // if not yet at 0, go to next character
|
||||
uart_text_length_index <= uart_text_length_index - 1;
|
||||
state_uart_send <= SEND_BYTE;
|
||||
end
|
||||
else begin // if already at 1, go back to idle
|
||||
state_uart_send <= IDLE;
|
||||
uart_send_done <= 1'b1;
|
||||
end
|
||||
end
|
||||
default: state_uart_send <= IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Function to convert hex to ASCII
|
||||
function [7:0] hex_to_ascii;
|
||||
input [3:0] hex;
|
||||
begin
|
||||
if (hex < 4'd10)
|
||||
hex_to_ascii = hex + 8'd48; // ASCII for '0'-'9'
|
||||
else
|
||||
hex_to_ascii = hex + 8'd55; // ASCII for 'A'-'F'
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
// module instantiations
|
||||
i2c_master #(.DATA_WIDTH(8),.REGISTER_WIDTH(8),.ADDRESS_WIDTH(7))
|
||||
i2c_master_inst(
|
||||
|
|
@ -159,6 +434,20 @@ module spd_reader (
|
|||
.external_serial_clock (i2c_scl),
|
||||
.slave_nack (slave_nack)
|
||||
);
|
||||
|
||||
uart_tx #(
|
||||
.BIT_RATE(115200),
|
||||
.CLK_HZ(100_000_000),
|
||||
.PAYLOAD_BITS(8),
|
||||
.STOP_BITS(1)
|
||||
) uart_tx_inst (
|
||||
.clk(i_clk), // Top level system clock input
|
||||
.resetn(i_rst_n), // Asynchronous active low reset.
|
||||
.uart_txd(uart_tx) , // UART transmit pin.
|
||||
.uart_tx_busy(uart_tx_busy), // Module busy sending previous item.
|
||||
.uart_tx_en(uart_tx_en), // Send the data on uart_tx_data
|
||||
.uart_tx_data(uart_tx_data) // The data to be sent
|
||||
);
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ module spd_reader_top (
|
|||
// i2c interface
|
||||
inout wire i2c_scl,
|
||||
inout wire i2c_sda,
|
||||
// uart tx interface
|
||||
output wire uart_tx,
|
||||
// fan
|
||||
output wire fan_pwm,
|
||||
//Debug LEDs
|
||||
|
|
@ -58,6 +60,7 @@ module spd_reader_top (
|
|||
.i_rst_n(i_rst_n && clk_locked),
|
||||
.i2c_scl(i2c_scl),
|
||||
.i2c_sda(i2c_sda),
|
||||
.uart_tx(uart_tx),
|
||||
.find_i2c_address_done(find_i2c_address_done),
|
||||
.read_spd_done(read_spd_done)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
|
||||
|
||||
//
|
||||
// Module: uart_tx
|
||||
//
|
||||
// Notes:
|
||||
// - UART transmitter module.
|
||||
//
|
||||
|
||||
module uart_tx(
|
||||
input wire clk , // Top level system clock input.
|
||||
input wire resetn , // Asynchronous active low reset.
|
||||
output wire uart_txd , // UART transmit pin.
|
||||
output wire uart_tx_busy, // Module busy sending previous item.
|
||||
input wire uart_tx_en , // Send the data on uart_tx_data
|
||||
input wire [PAYLOAD_BITS-1:0] uart_tx_data // The data to be sent
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// External parameters.
|
||||
//
|
||||
|
||||
//
|
||||
// Input bit rate of the UART line.
|
||||
parameter BIT_RATE = 9600; // bits / sec
|
||||
localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds
|
||||
|
||||
//
|
||||
// Clock frequency in hertz.
|
||||
parameter CLK_HZ = 50_000_000;
|
||||
localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds
|
||||
|
||||
//
|
||||
// Number of data bits recieved per UART packet.
|
||||
parameter PAYLOAD_BITS = 8;
|
||||
|
||||
//
|
||||
// Number of stop bits indicating the end of a packet.
|
||||
parameter STOP_BITS = 1;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Internal parameters.
|
||||
//
|
||||
|
||||
//
|
||||
// Number of clock cycles per uart bit.
|
||||
localparam CYCLES_PER_BIT = BIT_P / CLK_P;
|
||||
|
||||
//
|
||||
// Size of the registers which store sample counts and bit durations.
|
||||
localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Internal registers.
|
||||
//
|
||||
|
||||
//
|
||||
// Internally latched value of the uart_txd line. Helps break long timing
|
||||
// paths from the logic to the output pins.
|
||||
reg txd_reg;
|
||||
|
||||
//
|
||||
// Storage for the serial data to be sent.
|
||||
reg [PAYLOAD_BITS-1:0] data_to_send;
|
||||
|
||||
//
|
||||
// Counter for the number of cycles over a packet bit.
|
||||
reg [COUNT_REG_LEN-1:0] cycle_counter;
|
||||
|
||||
//
|
||||
// Counter for the number of sent bits of the packet.
|
||||
reg [3:0] bit_counter;
|
||||
|
||||
//
|
||||
// Current and next states of the internal FSM.
|
||||
reg [2:0] fsm_state;
|
||||
reg [2:0] n_fsm_state;
|
||||
|
||||
localparam FSM_IDLE = 0;
|
||||
localparam FSM_START= 1;
|
||||
localparam FSM_SEND = 2;
|
||||
localparam FSM_STOP = 3;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// FSM next state selection.
|
||||
//
|
||||
|
||||
assign uart_tx_busy = fsm_state != FSM_IDLE;
|
||||
assign uart_txd = txd_reg;
|
||||
|
||||
wire next_bit = cycle_counter == CYCLES_PER_BIT;
|
||||
wire payload_done = bit_counter == PAYLOAD_BITS ;
|
||||
wire stop_done = bit_counter == STOP_BITS && fsm_state == FSM_STOP;
|
||||
|
||||
//
|
||||
// Handle picking the next state.
|
||||
always @(*) begin : p_n_fsm_state
|
||||
case(fsm_state)
|
||||
FSM_IDLE : n_fsm_state = uart_tx_en ? FSM_START: FSM_IDLE ;
|
||||
FSM_START: n_fsm_state = next_bit ? FSM_SEND : FSM_START;
|
||||
FSM_SEND : n_fsm_state = payload_done ? FSM_STOP : FSM_SEND ;
|
||||
FSM_STOP : n_fsm_state = stop_done ? FSM_IDLE : FSM_STOP ;
|
||||
default : n_fsm_state = FSM_IDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Internal register setting and re-setting.
|
||||
//
|
||||
|
||||
//
|
||||
// Handle updates to the sent data register.
|
||||
integer i = 0;
|
||||
always @(posedge clk) begin : p_data_to_send
|
||||
if(!resetn) begin
|
||||
data_to_send <= {PAYLOAD_BITS{1'b0}};
|
||||
end else if(fsm_state == FSM_IDLE && uart_tx_en) begin
|
||||
data_to_send <= uart_tx_data;
|
||||
end else if(fsm_state == FSM_SEND && next_bit ) begin
|
||||
for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin
|
||||
data_to_send[i] <= data_to_send[i+1];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// Increments the bit counter each time a new bit frame is sent.
|
||||
always @(posedge clk) begin : p_bit_counter
|
||||
if(!resetn) begin
|
||||
bit_counter <= 4'b0;
|
||||
end else if(fsm_state != FSM_SEND && fsm_state != FSM_STOP) begin
|
||||
bit_counter <= {COUNT_REG_LEN{1'b0}};
|
||||
end else if(fsm_state == FSM_SEND && n_fsm_state == FSM_STOP) begin
|
||||
bit_counter <= {COUNT_REG_LEN{1'b0}};
|
||||
end else if(fsm_state == FSM_STOP&& next_bit) begin
|
||||
bit_counter <= bit_counter + 1'b1;
|
||||
end else if(fsm_state == FSM_SEND && next_bit) begin
|
||||
bit_counter <= bit_counter + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// Increments the cycle counter when sending.
|
||||
always @(posedge clk) begin : p_cycle_counter
|
||||
if(!resetn) begin
|
||||
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||
end else if(next_bit) begin
|
||||
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||
end else if(fsm_state == FSM_START ||
|
||||
fsm_state == FSM_SEND ||
|
||||
fsm_state == FSM_STOP ) begin
|
||||
cycle_counter <= cycle_counter + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// Progresses the next FSM state.
|
||||
always @(posedge clk) begin : p_fsm_state
|
||||
if(!resetn) begin
|
||||
fsm_state <= FSM_IDLE;
|
||||
end else begin
|
||||
fsm_state <= n_fsm_state;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// Responsible for updating the internal value of the txd_reg.
|
||||
always @(posedge clk) begin : p_txd_reg
|
||||
if(!resetn) begin
|
||||
txd_reg <= 1'b1;
|
||||
end else if(fsm_state == FSM_IDLE) begin
|
||||
txd_reg <= 1'b1;
|
||||
end else if(fsm_state == FSM_START) begin
|
||||
txd_reg <= 1'b0;
|
||||
end else if(fsm_state == FSM_SEND) begin
|
||||
txd_reg <= data_to_send[0];
|
||||
end else if(fsm_state == FSM_STOP) begin
|
||||
txd_reg <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -86,13 +86,29 @@ module i2c_slave (scl, sda);
|
|||
wire debug = 1'b1;
|
||||
genvar i;
|
||||
|
||||
reg [7:0] mem [99:0]; // initiate memory
|
||||
reg [7:0] mem [22:0]; // initiate memory
|
||||
|
||||
integer index;
|
||||
initial begin
|
||||
for (index = 0; index <= 100; index = index + 1) begin
|
||||
mem[index] = index; // Assign each element with its index value
|
||||
end
|
||||
// for (index = 0; index <= 100; index = index + 1) begin
|
||||
// mem[index] = index; // Assign each element with its index value
|
||||
// end
|
||||
mem[0] = 8'h00;
|
||||
mem[1] = 8'h11;
|
||||
mem[2] = 8'h0b;
|
||||
mem[3] = 8'h03;
|
||||
mem[4] = 8'h05; // BA_BITS = 3 , SDRAM_CAPACITY = 5
|
||||
mem[5][5:3] = 3'h3; // ROW_BITS = 15, COL_BITS = 10
|
||||
mem[5][2:0] = 3'h1;
|
||||
mem[7][5:3] = 3'h1; // DUAL_RANK_DIMM = 0
|
||||
mem[7][2:0] = 3'h1; //
|
||||
mem[8] = 8'h03; // BYTE_LANES = 8
|
||||
mem[10] = 8'h01;
|
||||
mem[11] = 8'h08; // mtb = mtb (1/8)
|
||||
mem[18] = 8'h6e; // TRCD = 13_750
|
||||
mem[20] = 8'h6c; //TRP = 13_500
|
||||
mem[21] = 8'h01; // TRAS = 35_000
|
||||
mem[22] = 8'h18;
|
||||
end
|
||||
|
||||
reg [7:0] mem_adr; // memory address
|
||||
|
|
|
|||
Loading…
Reference in New Issue