here is the code to the three modules
module au_top (
input clk, // 100MHz clock
input rst_n, // reset button (active low)
output led [8], // 8 user controllable LEDs
input usb_rx, // USB->Serial input
output usb_tx, // USB->Serial output
inout sda, // i2c data
output scl // i2c clock
)
{
sig rst; // reset signal
.clk(clk) {
reset_conditioner reset_cond;
.rst(rst) {
eeprom_24AA32A eeprom(.sda(sda));
test_eeprom test(.sda(sda));
// uart_rx uart_rx(#BAUD(9600), #CLK_FREQ(100000000)); //console
uart_tx uart_tx(#BAUD(9600), #CLK_FREQ(100000000)); //console
}
}
always {
reset_cond.in = ~rst_n; // input raw inverted reset signal
rst = reset_cond.out; // conditioned reset
//usb_tx = usb_rx; // echo the serial data
led = 8b11110011;
scl = test.scl;
//test.read_data = 0;
usb_tx = uart_tx.tx; // connect the output console
// uart_rx.rx = usb_rx; // connect the input console
// usb_tx = usb_rx; // echo the serial data
// USB TX Connections
uart_tx.block = 0; // don't block
test.usb_tx_busy = uart_tx.busy;
uart_tx.new_data = test.usb_new_tx;
uart_tx.data = test.usb_tx_data;
eeprom.cntl_byte_write = 0;
eeprom.cntl_byte_read = 0;
eeprom.high_addr_byte = 0;
eeprom.low_addr_byte = 0;
eeprom.write = 0;
eeprom.read = 0;
eeprom.data_byte = 0;
// USB RX Connections
//test.usb_new_rx = uart_rx.new_data;
//test.usb_rx_data = uart_rx.data;
test.read_value = 0;
}
module eeprom_24AA32A
(
input clk, // clock
input rst, // reset
input write, // write enabled
input read, // read enabled
output busy, // busy indicator 1 = busy
inout sda, // i2c data
output scl , // i2c clock
input cntl_byte_write[8],
input high_addr_byte[8],
input low_addr_byte[8],
input data_byte[8],
input cntl_byte_read[8],
output read_value[8]
)
{
.clk(clk) {
.rst(rst) {
fsm state = {IDLE, START, ARSTART, RSTART, ADDRESS, MEM_ADDR1, MEM_ADDR2, RADDRESS, RRADDRESS, RMEM_ADDR1, RMEM_ADDR2,DATA, READ,RSTOP,WSTOP,SPIN}; // mcp4725 states write
i2c_controller qwiic(.sda(sda)); // i2c controller
// test_eeprom test_access;
dff newvalue[8];
// value to be written to DAC
dff ack_write;
}
}
// name eeprom_24AA32A
always {
busy = state.q != state.IDLE;
// i2c signals and connections
qwiic.start = 0;
qwiic.stop = 0;
qwiic.write = 0;
ack_write.d = qwiic.ack_write;
scl = qwiic.scl;
qwiic.read = 0;
qwiic.data_in = 8hxx;
qwiic.ack_read = 0;
newvalue.d = newvalue.q + 0;
// value to be written to DAC
ack_write.d = ack_write.q + 0;
read_value = 8b00110111;
qwiic.write = write;
case(state.q) {
state.IDLE:
qwiic.start = 0;
qwiic.stop = 0;
qwiic.write = 0;
ack_write.d = qwiic.ack_write;
scl = qwiic.scl;
qwiic.read = 0;
qwiic.data_in = 8hxx;
qwiic.ack_read = 0;
newvalue.d = newvalue.q + 0;
// value to be written to DAC
ack_write.d = ack_write.q + 0;
read_value = 8b00110110;
qwiic.write = write;
// send new dac data
if(write) {
// transmit new DAC data over i2c
state.d = state.START;
newvalue.d = data_byte; // capture new DAC data
}
if (read) {
state.d = state.ARSTART;
}
state.START:
// start i2c controller
if(!qwiic.busy) {
state.d = state.ADDRESS;
qwiic.start = 1;
}
state.ADDRESS:
// if not busy write 1st byte, i2c address, write = 0
if(!qwiic.busy) {
state.d = state.MEM_ADDR1;
qwiic.write = 1;
// qwiic.data_in = 8b10100000; // address 0xA0 (<< 1)
qwiic.data_in = cntl_byte_write; // address 0xA0 (<< 1)
}
state.MEM_ADDR1:
// if not busy write 2nd byte, low end of byte xxxx0000
if(!qwiic.busy) {
state.d = state.MEM_ADDR2;
qwiic.write = 1;
// qwiic.data_in = c{8b00000000};
qwiic.data_in = high_addr_byte;
}
state.MEM_ADDR2:
// if not busy write 3rd byte, 8 address bits
if(!qwiic.busy) {
state.d = state.DATA;
qwiic.write = 1;
// qwiic.data_in = 8b00000000;
qwiic.data_in = low_addr_byte;
}
state.DATA: // write data
//if not busy write the data byte which is FF
if(!qwiic.busy) {
state.d = state.WSTOP;
qwiic.write = 1;
// qwiic.data_in = 8b10101010;
qwiic.data_in = data_byte;
}
state.WSTOP:
// stop i2c controller
if(!qwiic.busy) {
state.d = state.SPIN;
qwiic.stop = 1;
}
state.ARSTART:
// start i2c controller
if(!qwiic.busy) {
state.d = state.RADDRESS;
qwiic.start = 1;
}
state.RADDRESS:
// if not busy write 1st byte, i2c address, write = 0
if(!qwiic.busy) {
state.d = state.RMEM_ADDR1;
qwiic.write = 1;
qwiic.data_in = cntl_byte_write; // address 0xA0 (<< 1)
}
state.RMEM_ADDR1:
// if not busy write 2nd byte, low end of byte xxxx0000
if(!qwiic.busy) {
state.d = state.RMEM_ADDR2;
qwiic.write = 1;
qwiic.data_in = high_addr_byte;
}
state.RMEM_ADDR2:
// if not busy write 3rd byte, 8 address bits
if(!qwiic.busy) {
state.d = state.RSTART;
qwiic.write = 1;
qwiic.data_in = low_addr_byte;
}
state.RSTART:
// start i2c controller
if(!qwiic.busy) {
state.d = state.RRADDRESS;
qwiic.start = 1;
}
state.RRADDRESS:
// if not busy write 1st byte, i2c address, write = 0
if(!qwiic.busy) {
state.d = state.READ;
qwiic.write = 1;
qwiic.data_in = cntl_byte_read; // address 0xA0 (<< 1) // read bit (8) set to 1
}
state.READ: // READ DATA BACK
// if not busy write the data byte which is FF
if(!qwiic.busy) {
state.d = state.RSTOP;
qwiic.write = 0;
qwiic.read = 1;
//read_value = 8b00110011; //qwiic.data_out;
read_value = qwiic.data_out;
}
state.RSTOP:
// stop i2c controller
if(!qwiic.busy) {
state.d = state.IDLE;
qwiic.stop = 1;
}
state.SPIN: // just used for testing
// stop i2c controller
state.d = state.SPIN;
}
}
}
module test_eeprom (
input clk, // clock
input rst, // reset
inout sda, // i2c data
output scl, // i2c clock
output usb_tx, // USB->Serial output
input usb_tx_busy,
output usb_new_tx,
output usb_tx_data[8],
input read_value[8]
) {
.clk(clk) {
.rst(rst) {
fsm state = {IDLE, START, SPIN};
eeprom_24AA32A test(.sda(sda)); // i2c controller
}
dff delay_timer_enter[32];
dff max_counter[32];
}
always {
delay_timer_enter.d = 1;
max_counter.d = 1;
//test.usb_tx_busy = 0;
//test.read_value = 0;
test.write = 0;
test.read = 0;
usb_tx = 0;
test.cntl_byte_write = 8b10100000; // 1010 + 000 + 0 control + address + write mode
test.high_addr_byte = 8h0; // xxxx0000 high address
test.low_addr_byte = 8h0; // 00000000 low address
test.data_byte = 8b00110001; // data to be written which will be a 1
test.cntl_byte_read = 8b10100001; // control byte for read
scl = test.scl;
usb_new_tx = 0;
usb_tx_data = 8hxx;
scl = test.scl;
case (state.q) { // our FSM
// IDLE: Reset everything and wait for a new byte.
state.IDLE:
test.cntl_byte_write = 8b10100000; // 1010 + 000 + 0 control + address + write mode
test.high_addr_byte = 8h0; // xxxx0000 high address
test.low_addr_byte = 8h0; // 00000000 low address
test.data_byte = 8b00110001; // data to be written which will be a 1
test.cntl_byte_read = 8b10100001; // control byte for read
state.d = state.START;
state.START:
delay_timer_enter.d = delay_timer_enter.q + 1;
max_counter.d = max_counter.q + 1;
if (delay_timer_enter.q == 1000000000) // 1,000,000,000
{
//usb_tx_data = 8hxx;
test.write = 0;
test.cntl_byte_write = 8b10100000; // 1010 + 000 + 0 control + address + write mode
test.high_addr_byte = 8h0; // xxxx0000 high address
test.low_addr_byte = 8h0; // 00000000 low address
test.data_byte = 8b00110001; // data to be written which will be a 1
test.cntl_byte_read = 8b10100001; // control byte for read
test.read = 1;
if (!usb_tx_busy)
{
usb_new_tx = 1;
usb_tx_data = test.read_value; // this is the value read from the eeprom first byt
}
delay_timer_enter.d = 0;
}
if (max_counter.q == 3000000000)
{
state.d = state.IDLE;
max_counter.d = 1;
test.read = 0;
test.write = 0;
}
state.SPIN: // just used for testing
state.d = state.SPIN;
}