summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Buesch <m@bues.ch>2017-01-29 12:17:36 +0100
committerMichael Buesch <m@bues.ch>2017-02-07 19:43:19 +0100
commit232a029ffb1355690eddad470b995138573f5485 (patch)
tree6d6baaf20ec7b038bd1ef51c33d26c68704b743e
parent42657f00c8827d6cafc35dbb95890127c77e7946 (diff)
downloadtoprammer-232a029ffb1355690eddad470b995138573f5485.tar.xz
toprammer-232a029ffb1355690eddad470b995138573f5485.zip
m24cxx: Fix I2C implementation
Signed-off-by: Michael Buesch <m@bues.ch>
-rw-r--r--libtoprammer/chips/m24cxxdip8.py149
-rw-r--r--libtoprammer/fpga/bin/m24c16dip8.bitbin24787 -> 24787 bytes
-rw-r--r--libtoprammer/fpga/common/i2c.v234
-rw-r--r--libtoprammer/fpga/src/m24c16dip8/m24c16dip8.ucf62
-rw-r--r--libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v483
-rw-r--r--libtoprammer/fpga/src/m24c16dip8/warning.filter1
6 files changed, 386 insertions, 543 deletions
diff --git a/libtoprammer/chips/m24cxxdip8.py b/libtoprammer/chips/m24cxxdip8.py
index 85a58cf..44ab3c2 100644
--- a/libtoprammer/chips/m24cxxdip8.py
+++ b/libtoprammer/chips/m24cxxdip8.py
@@ -3,7 +3,7 @@
#
# M24C16 I2C based serial EEPROM
#
-# Copyright (c) 2011 Michael Buesch <m@bues.ch>
+# Copyright (c) 2011-2017 Michael Buesch <m@bues.ch>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,13 +24,9 @@ from libtoprammer.chip import *
class Chip_m24cXXdip8_common(Chip):
- CMD_DEVSEL_READ = 0
- CMD_DEVSEL_WRITE = 1
- CMD_SETADDR = 2
- CMD_DATA_READ = 3
- CMD_DATA_READ_STOP = 4
- CMD_DATA_WRITE = 5
- CMD_DATA_WRITE_STOP = 6
+ I2C_BASE_ADDR = 0x50 << 1
+ I2C_READ = 0x01
+ I2C_WRITE = 0x00
def __init__(self, eepromSize):
Chip.__init__(self,
@@ -57,27 +53,34 @@ class Chip_m24cXXdip8_common(Chip):
self.__chipTurnOn()
image = ""
- count = 0
prevAddr = None
self.progressMeterInit("Reading EEPROM", self.eepromSize)
for addr in range(0, self.eepromSize):
self.progressMeter(addr)
if prevAddr is None or (prevAddr & 0xFF00) != (addr & 0xFF00):
- self.__setAddress(addr, writeMode=False)
- self.__runCommand(self.CMD_DEVSEL_WRITE)
- self.__runCommand(self.CMD_SETADDR)
- self.__runCommand(self.CMD_DEVSEL_READ)
- self.__runCommand(self.CMD_DATA_READ_STOP)
+ self.__setAddressExtension(addr, writeMode=False)
+ # Begin sequential random read
+ self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE,
+ read=False, do_start=True, do_stop=False)
+ self.__expectACK()
+ self.__runI2C(data=addr & 0xFF,
+ read=False, do_start=False, do_stop=False)
+ self.__expectACK()
+ self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_READ,
+ read=False, do_start=True, do_stop=False)
+ self.__expectACK()
prevAddr = addr
+ # Sequential random read
+ if addr >= self.eepromSize - 1:
+ # Last byte
+ self.__runI2C(read=True, do_start=False, do_stop=True)
+ self.__expectNACK()
else:
- self.__runCommand(self.CMD_DEVSEL_READ)
- self.__runCommand(self.CMD_DATA_READ_STOP)
+ self.__runI2C(read=True, do_start=False, do_stop=False,
+ drive_ack=True)
+ self.__expectACK()
self.__readData()
- count += 1
- if count == self.top.getBufferRegSize():
- image += self.top.cmdReadBufferReg(count)
- count = 0
- image += self.top.cmdReadBufferReg(count)
+ image += self.top.cmdReadBufferReg(1)
self.progressMeterFinish()
return image
@@ -93,18 +96,24 @@ class Chip_m24cXXdip8_common(Chip):
for addr in range(0, len(image)):
self.progressMeter(addr)
if prevAddr is None or (prevAddr & 0xFFF0) != (addr & 0xFFF0):
- self.__setAddress(addr, writeMode=True)
- self.__runCommand(self.CMD_DEVSEL_WRITE, busyWait=True)
- self.__runCommand(self.CMD_SETADDR, busyWait=True)
- self.__setData(byte2int(image[addr]))
- self.__runCommand(self.CMD_DATA_WRITE, busyWait=True)
+ self.__setAddressExtension(addr, writeMode=True)
+ self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE,
+ read=False, do_start=True, do_stop=False)
+ self.__expectACK()
+ self.__runI2C(data=addr & 0xFF,
+ read=False, do_start=False, do_stop=False)
+ self.__expectACK()
prevAddr = addr
+ if (addr & 0xF) == 0xF:
+ self.__runI2C(data=byte2int(image[addr]),
+ read=False, do_start=False, do_stop=True)
+ self.__expectACK()
+ self.top.cmdDelay(0.005) # Max write time
else:
- self.__setData(byte2int(image[addr]))
- if (addr & 0xF) == 0xF:
- self.__runCommand(self.CMD_DATA_WRITE_STOP, busyWait=True)
- else:
- self.__runCommand(self.CMD_DATA_WRITE, busyWait=True)
+ self.__runI2C(data=byte2int(image[addr]),
+ read=False, do_start=False, do_stop=False)
+ self.__expectACK()
+
self.progressMeterFinish()
def __readData(self):
@@ -113,56 +122,39 @@ class Chip_m24cXXdip8_common(Chip):
def __setData(self, dataByte):
self.top.cmdFPGAWrite(1, dataByte & 0xFF)
- def __setAddress(self, address, writeMode):
- # Address base
- self.__setData(address)
- # Address extension
+ def __setAddressExtension(self, address, writeMode):
sizeMask = self.eepromSize - 1
assert(sizeMask & ~0x7FF == 0)
- addrExt = address & 0x700 & sizeMask
- if self.currentAddrExt != addrExt or\
- self.currentWriteMode != writeMode:
- self.currentAddrExt = addrExt
- self.currentWriteMode = writeMode
- if sizeMask & 0x0100:
- E0 = addrExt & 0x0100
- E0_en = 0
- else:
- E0 = 0
- E0_en = 1
- if sizeMask & 0x0200:
- E1 = addrExt & 0x0200
- E1_en = 0
- else:
- E1 = 0
- E1_en = 1
- if sizeMask & 0x0400:
- E2 = addrExt & 0x0400
- E2_en = 0
- else:
- E2 = 0
- E2_en = 1
- if writeMode:
- WC = 0
- else:
- WC = 1
+ addrExt = ((address & 0x700 & sizeMask) >> 8) << 1
+
+ if self.currentWriteMode != writeMode:
+ E0 = E1 = E2 = 0
+ E0_en = not (sizeMask & 0x0100)
+ E1_en = not (sizeMask & 0x0200)
+ E2_en = not (sizeMask & 0x0400)
+ WC = not writeMode
self.__setControlPins(E0=E0, E0_en=E0_en,
E1=E1, E1_en=E1_en,
E2=E2, E2_en=E2_en,
WC=WC)
+ self.currentAddrExt = addrExt
+ self.currentWriteMode = writeMode
- def __runCommand(self, command, busyWait=False):
- self.top.cmdFPGAWrite(0, command & 0xFF)
- if busyWait:
- self.__busyWait()
+ def __runI2C(self, data=None, read=False, do_start=False, do_stop=False, drive_ack=False):
+ if data is not None:
+ self.__setData(data)
else:
- # We do not read busy flags, but wait long enough for
- # the operation to finish. This is safe for eeprom read.
- self.top.cmdDelay(0.00009)
+ self.__setData(0)
+ command = (0x01 if read else 0) |\
+ (0x02 if do_start else 0) |\
+ (0x04 if do_stop else 0) |\
+ (0x08 if drive_ack else 0)
+ self.top.cmdFPGAWrite(0, command)
+ self.__busyWait()
def __isBusy(self):
- (busy0, busy1) = self.__getStatusFlags()
- return busy0 != busy1
+ (busy, ack) = self.__getStatusFlags()
+ return busy
def __busyWait(self):
for i in range(0, 100):
@@ -174,9 +166,18 @@ class Chip_m24cXXdip8_common(Chip):
def __getStatusFlags(self):
self.top.cmdFPGARead(1)
stat = self.top.cmdReadBufferReg8()
- busy0 = bool(stat & 0x01)
- busy1 = bool(stat & 0x02)
- return (busy0, busy1)
+ busy = bool(stat & 0x01)
+ ack = not bool(stat & 0x02)
+ self.lastAck = ack
+ return (busy, ack)
+
+ def __expectACK(self):
+ if not self.lastAck:
+ self.throwError("Expected I2C ACK, but received NACK")
+
+ def __expectNACK(self):
+ if self.lastAck:
+ self.throwError("Expected I2C NACK, but received ACK")
def __setControlPins(self, E0, E0_en, E1, E1_en, E2, E2_en, WC):
value = 0
diff --git a/libtoprammer/fpga/bin/m24c16dip8.bit b/libtoprammer/fpga/bin/m24c16dip8.bit
index be6fb81..6786f5d 100644
--- a/libtoprammer/fpga/bin/m24c16dip8.bit
+++ b/libtoprammer/fpga/bin/m24c16dip8.bit
Binary files differ
diff --git a/libtoprammer/fpga/common/i2c.v b/libtoprammer/fpga/common/i2c.v
new file mode 100644
index 0000000..593398c
--- /dev/null
+++ b/libtoprammer/fpga/common/i2c.v
@@ -0,0 +1,234 @@
+/*
+ * TOP2049 Open Source programming suite
+ *
+ * FPGA bottomhalf I2C bus implementation
+ *
+ * Copyright (c) 2011-2017 Michael Buesch <m@bues.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+module i2c_module(clock, nreset,
+ scl_out, scl_out_en, scl_in,
+ sda_out, sda_out_en, sda_in,
+ write_byte, read_byte, read_mode,
+ ack, drive_ack,
+ do_start, do_stop,
+ finished);
+ input clock;
+ input nreset;
+ output scl_out;
+ output scl_out_en;
+ input scl_in;
+ output sda_out;
+ output sda_out_en;
+ input sda_in;
+ input [7:0] write_byte;
+ output [7:0] read_byte;
+ input read_mode;
+ output ack;
+ input drive_ack;
+ input do_start;
+ input do_stop;
+ output finished;
+
+ reg [1:0] start_state;
+ reg [1:0] data_state;
+ reg [0:0] ack_state;
+ reg [0:0] stop_state;
+ reg [3:0] bit_index;
+
+ reg sda_out_reg;
+ reg sda_out_en_reg;
+ reg [1:0] scl_out_reg;
+ reg scl_out_en_reg;
+ reg scl_running;
+ reg [7:0] read_byte_reg;
+ reg ack_reg;
+ reg finished_reg;
+
+ wire [1:0] scl_pos;
+ assign scl_pos = (scl_out_reg + 1) & 3;
+ parameter SCL_HILO = 0;
+ parameter SCL_LO = 1;
+ parameter SCL_LOHI = 2;
+ parameter SCL_HI = 3;
+
+ wire [7:0] write_byte_wire;
+ assign write_byte_wire[0] = write_byte[7];
+ assign write_byte_wire[1] = write_byte[6];
+ assign write_byte_wire[2] = write_byte[5];
+ assign write_byte_wire[3] = write_byte[4];
+ assign write_byte_wire[4] = write_byte[3];
+ assign write_byte_wire[5] = write_byte[2];
+ assign write_byte_wire[6] = write_byte[1];
+ assign write_byte_wire[7] = write_byte[0];
+ assign read_byte[0] = read_byte_reg[7];
+ assign read_byte[1] = read_byte_reg[6];
+ assign read_byte[2] = read_byte_reg[5];
+ assign read_byte[3] = read_byte_reg[4];
+ assign read_byte[4] = read_byte_reg[3];
+ assign read_byte[5] = read_byte_reg[2];
+ assign read_byte[6] = read_byte_reg[1];
+ assign read_byte[7] = read_byte_reg[0];
+ assign sda_out = sda_out_reg;
+ assign sda_out_en = sda_out_en_reg;
+ assign scl_out = scl_out_reg[1];
+ assign scl_out_en = scl_out_en_reg;
+ assign ack = ack_reg;
+ assign finished = finished_reg;
+
+ initial begin
+ start_state <= 0;
+ data_state <= 0;
+ ack_state <= 0;
+ stop_state <= 0;
+ bit_index <= 0;
+
+ sda_out_reg <= 1;
+ sda_out_en_reg <= 0;
+ scl_out_reg <= SCL_HI;
+ scl_out_en_reg <= 1;
+ scl_running <= 0;
+ read_byte_reg <= 0;
+ ack_reg <= 0;
+ finished_reg <= 0;
+ end
+
+//TODO clock stretching
+
+ always @(posedge clock or negedge nreset) begin
+ if (nreset == 0) begin
+ /* Reset */
+ start_state <= 0;
+ data_state <= 0;
+ ack_state <= 0;
+ stop_state <= 0;
+
+ bit_index <= 0;
+
+ sda_out_reg <= 1;
+ sda_out_en_reg <= 0;
+ scl_out_reg <= SCL_HI;
+ scl_out_en_reg <= 1;
+ scl_running <= 0;
+ read_byte_reg <= 0;
+ ack_reg <= 0;
+
+ finished_reg <= 0;
+ end else begin
+
+// if (scl_running) begin
+ scl_out_reg <= scl_out_reg + 1;
+// end else begin
+// scl_out_reg <= SCL_HI;
+// end
+
+ if (do_start && start_state != 2) begin
+ /* Send start condition */
+ finished_reg <= 0;
+ scl_running <= 1;
+ sda_out_en_reg <= 1;
+ case (start_state)
+ 0: begin
+ /* Begin with SDA=hi */
+ sda_out_reg <= 1;
+ if (scl_pos == SCL_LOHI) begin
+ start_state <= 1;
+ end
+ end
+ 1: begin
+ /* Start condition latch */
+ if (scl_pos == SCL_HI) begin
+ sda_out_reg <= 0;
+ start_state <= 2;
+ end
+ end
+ endcase
+ end else if (data_state != 2) begin
+ /* Data transfer */
+ finished_reg <= 0;
+ scl_running <= 1;
+ sda_out_en_reg <= !read_mode;
+ case (data_state)
+ 0: begin
+ if (scl_pos == SCL_LO) begin
+ if (read_mode) begin
+ sda_out_reg <= 0;
+ end else begin
+ sda_out_reg <= write_byte_wire[bit_index & 7];
+ end
+ data_state <= 1;
+ end
+ end
+ 1: begin
+ if (scl_pos == SCL_HI) begin
+ bit_index <= bit_index + 1;
+ if (read_mode) begin
+ read_byte_reg[bit_index & 7] <= sda_in;
+ end
+ if (bit_index >= 7) begin
+ data_state <= 2;
+ end else begin
+ data_state <= 0;
+ end
+ end
+ end
+ endcase
+ end else if (ack_state != 1) begin
+ /* Read ACK bit */
+ finished_reg <= 0;
+ scl_running <= 1;
+ case (ack_state)
+ 0: begin
+ if (scl_pos == SCL_LO) begin
+ sda_out_en_reg <= drive_ack;
+ sda_out_reg <= 0;
+ end else if (scl_pos == SCL_HI) begin
+ ack_reg <= sda_in;
+ ack_state <= 1;
+ end
+ end
+ endcase
+ end else if (do_stop && stop_state != 1) begin
+ /* Send stop condition */
+ finished_reg <= 0;
+ sda_out_en_reg <= 1;
+ case (stop_state)
+ 0: begin
+ if (scl_pos == SCL_HI) begin
+ sda_out_reg <= 1;
+ stop_state <= 1;
+ end
+ end
+ endcase
+ end else begin
+ if (scl_pos == SCL_HILO) begin
+ start_state <= 0;
+ data_state <= 0;
+ ack_state <= 0;
+ stop_state <= 0;
+
+ bit_index <= 0;
+
+ finished_reg <= 1;
+// scl_running <= 0;
+ end else begin
+ finished_reg <= 0;
+ end
+ end
+ end
+ end
+endmodule
diff --git a/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.ucf b/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.ucf
deleted file mode 100644
index a550c07..0000000
--- a/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.ucf
+++ /dev/null
@@ -1,62 +0,0 @@
-NET "data<0>" LOC = P30;
-NET "data<1>" LOC = P31;
-NET "data<2>" LOC = P32;
-NET "data<3>" LOC = P34;
-NET "data<4>" LOC = P40;
-NET "data<5>" LOC = P41;
-NET "data<6>" LOC = P43;
-NET "data<7>" LOC = P44;
-
-NET "read" LOC = P45;
-NET "write" LOC = P39;
-NET "osc_in" LOC = P46;
-NET "ale_in" LOC = P36;
-
-NET "zif<1>" LOC = P21;
-NET "zif<2>" LOC = P19;
-NET "zif<3>" LOC = P17;
-NET "zif<4>" LOC = P15;
-NET "zif<5>" LOC = P10;
-NET "zif<6>" LOC = P8;
-NET "zif<7>" LOC = P6;
-NET "zif<8>" LOC = P4;
-NET "zif<9>" LOC = P98;
-NET "zif<10>" LOC = P96;
-NET "zif<11>" LOC = P93;
-NET "zif<12>" LOC = P86;
-NET "zif<13>" LOC = P83;
-NET "zif<14>" LOC = P81;
-NET "zif<15>" LOC = P74;
-NET "zif<16>" LOC = P71;
-NET "zif<17>" LOC = P69;
-NET "zif<18>" LOC = P67;
-NET "zif<19>" LOC = P65;
-NET "zif<20>" LOC = P60;
-NET "zif<21>" LOC = P58;
-NET "zif<22>" LOC = P56;
-NET "zif<23>" LOC = P54;
-NET "zif<24>" LOC = P47;
-NET "zif<25>" LOC = P53;
-NET "zif<26>" LOC = P55;
-NET "zif<27>" LOC = P57;
-NET "zif<28>" LOC = P59;
-NET "zif<29>" LOC = P62;
-NET "zif<30>" LOC = P66;
-NET "zif<31>" LOC = P68;
-NET "zif<32>" LOC = P70;
-NET "zif<33>" LOC = P72;
-NET "zif<34>" LOC = P80;
-NET "zif<35>" LOC = P82;
-NET "zif<36>" LOC = P84;
-NET "zif<37>" LOC = P87;
-NET "zif<38>" LOC = P95;
-NET "zif<39>" LOC = P97;
-NET "zif<40>" LOC = P3;
-NET "zif<41>" LOC = P5;
-NET "zif<42>" LOC = P7;
-NET "zif<43>" LOC = P9;
-NET "zif<44>" LOC = P13;
-NET "zif<45>" LOC = P16;
-NET "zif<46>" LOC = P18;
-NET "zif<47>" LOC = P20;
-NET "zif<48>" LOC = P22;
diff --git a/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v b/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v
index 68c6f41..7b82fe0 100644
--- a/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v
+++ b/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v
@@ -4,7 +4,7 @@
* M24C16 I2C based serial EEPROM
* FPGA bottomhalf implementation
*
- * Copyright (c) 2011 Michael Buesch <m@bues.ch>
+ * Copyright (c) 2011-2017 Michael Buesch <m@bues.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,204 +21,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* The runtime ID and revision. */
-`define RUNTIME_ID 16'h000B
-`define RUNTIME_REV 16'h01
+`include "common.vh"
+`include "i2c.v"
-module i2c_module(clock, scl, sda_out, sda_out_en, sda_in,
- write_byte, read_byte, read_mode,
- do_start, expect_ack, do_stop,
- finished);
- input clock;
- output scl;
- output sda_out;
- output sda_out_en;
- input sda_in;
- input [7:0] write_byte;
- output [7:0] read_byte;
- input read_mode;
- input do_start;
- input expect_ack;
- input do_stop;
- output finished;
-
- reg [1:0] start_state;
- reg [1:0] data_state;
- reg [1:0] ack_state;
- reg [1:0] stop_state;
- reg [2:0] bit_index;
-
- reg sda_out;
- reg sda_out_en;
- reg scl;
- reg [7:0] read_byte;
- reg finished;
-
- initial begin
- start_state <= 0;
- data_state <= 0;
- ack_state <= 0;
- stop_state <= 0;
- bit_index <= 7;
-
- sda_out <= 0;
- sda_out_en <= 0;
- scl <= 0;
- read_byte <= 0;
- finished <= 0;
- end
-
- always @(posedge clock) begin
- if (do_start && start_state != 3) begin
- /* Send start condition */
- finished <= 0;
- sda_out_en <= 1;
- case (start_state)
- 0: begin
- /* Start SCL high */
- scl <= 1;
- sda_out <= 1;
- start_state <= 1;
- end
- 1: begin
- /* Start condition latch */
- sda_out <= 0;
- start_state <= 2;
- end
- 2: begin
- /* Start SCL low */
- scl <= 0;
- start_state <= 3;
- end
- endcase
- end else if (data_state != 3) begin
- /* Data transfer */
- finished <= 0;
- if (read_mode) begin /* Read */
- sda_out_en <= 0;
- sda_out <= 0;
- case (data_state)
- 0: begin
- scl <= 1;
- data_state <= 1;
- end
- 1: begin
- read_byte[bit_index] <= sda_in;
- data_state <= 2;
- end
- 2: begin
- scl <= 0;
- if (bit_index == 0) begin
- /* Done reading byte */
- bit_index <= 7;
- data_state <= 3;
- end else begin
- bit_index <= bit_index - 1;
- data_state <= 0;
- end
- end
- endcase
- end else begin /* Write */
- sda_out_en <= 1;
- case (data_state)
- 0: begin
- sda_out <= write_byte[bit_index];
- scl <= 0;
- data_state <= 1;
- end
- 1: begin
- scl <= 1;
- data_state <= 2;
- end
- 2: begin
- scl <= 0;
- if (bit_index == 0) begin
- /* Done writing byte */
- bit_index <= 7;
- data_state <= 3;
- end else begin
- bit_index <= bit_index - 1;
- data_state <= 0;
- end
- end
- endcase
- end
- end else if (expect_ack && ack_state != 2) begin
- /* Wait for ACK from chip */
- finished <= 0;
- sda_out_en <= 0;
- case (ack_state)
- 0: begin
- scl <= 1;
- ack_state <= 1;
- end
- 1: begin
- scl <= 0;
- if (sda_in == 0) begin
- /* Got it */
- ack_state <= 2;
- end else begin
- ack_state <= 0;
- end
- end
- endcase
- end else if (do_stop && stop_state != 2) begin
- /* Send stop condition */
- finished <= 0;
- sda_out_en <= 1;
- case (stop_state)
- 0: begin
- scl <= 1;
- sda_out <= 0;
- stop_state <= 1;
- end
- 1: begin
- sda_out <= 1;
- stop_state <= 2;
- end
- endcase
- end else begin
- /* Reset */
- start_state <= 0;
- data_state <= 0;
- ack_state <= 0;
- stop_state <= 0;
-
- finished <= 1;
- end
- end
-endmodule
-
-module m24c16dip8(data, ale_in, write, read, osc_in, zif);
- inout [7:0] data;
- input ale_in;
- input write;
- input read;
- input osc_in; /* 24MHz oscillator */
- inout [48:1] zif;
-
- /* Interface to the microcontroller */
- wire read_oe; /* Read output-enable */
- reg [7:0] address; /* Cached address value */
- reg [7:0] read_data; /* Cached read data */
-
- /* Programmer API and statemachine */
- reg [1:0] cmd_busy; /* bit0 != bit1 >= busy */
- reg [3:0] command;
+`BOTTOMHALF_BEGIN(m24c16dip8, 11, 1)
reg [7:0] data_buffer;
- `define IS_BUSY (cmd_busy[0] != cmd_busy[1]) /* Is running command? */
- `define SET_FINISHED cmd_busy[1] <= cmd_busy[0] /* Set command-finished */
-
- /* Programmer commands */
- parameter CMD_DEVSEL_READ = 0;
- parameter CMD_DEVSEL_WRITE = 1;
- parameter CMD_SETADDR = 2;
- parameter CMD_DATA_READ = 3;
- parameter CMD_DATA_READ_STOP = 4;
- parameter CMD_DATA_WRITE = 5;
- parameter CMD_DATA_WRITE_STOP = 6;
-
/* Chip signals */
reg chip_e0; /* E0 */
reg chip_e0_en; /* E0 enable */
@@ -227,55 +35,46 @@ module m24c16dip8(data, ale_in, write, read, osc_in, zif);
reg chip_e2; /* E2 */
reg chip_e2_en; /* E2 enable */
reg chip_wc; /* /WC */
- wire chip_scl; /* I2C SCL */
+ wire chip_scl_out; /* I2C SCL out */
+ wire chip_scl_out_en; /* I2C SCL out enable*/
wire chip_sda_out; /* I2C SDA out */
wire chip_sda_out_en; /* I2C SDA out enable */
parameter ZIF_SDA = 25;
-
- wire low, high; /* Constant lo/hi */
- assign low = 0;
- assign high = 1;
+ parameter ZIF_SCL = 26;
/* I2C interface */
reg i2c_clock;
+ reg i2c_nreset;
reg [7:0] i2c_write_byte;
wire [7:0] i2c_read_byte;
reg i2c_read; /* 1=> Read mode */
+ wire i2c_ack;
+ reg i2c_drive_ack;
reg i2c_do_start;
- reg i2c_expect_ack;
reg i2c_do_stop;
wire i2c_finished;
- reg [1:0] i2c_running;
+ reg i2c_running;
i2c_module i2c(
.clock(i2c_clock),
- .scl(chip_scl),
+ .nreset(i2c_nreset),
+ .scl_out(chip_scl_out),
+ .scl_out_en(chip_scl_out_en),
+ .scl_in(zif[ZIF_SCL]),
.sda_out(chip_sda_out),
.sda_out_en(chip_sda_out_en),
.sda_in(zif[ZIF_SDA]),
.write_byte(i2c_write_byte),
.read_byte(i2c_read_byte),
.read_mode(i2c_read),
+ .ack(i2c_ack),
+ .drive_ack(i2c_drive_ack),
.do_start(i2c_do_start),
- .expect_ack(i2c_expect_ack),
.do_stop(i2c_do_stop),
.finished(i2c_finished)
);
- /* The delay counter. Based on the 24MHz input clock. */
- reg [15:0] delay_count;
- wire osc;
- IBUF osc_ibuf(.I(osc_in), .O(osc));
-
- `define DELAY_1P5US delay_count <= 36 - 1 /* 1.5 microseconds */
-
- initial begin
- address <= 0;
- read_data <= 0;
- delay_count <= 0;
-
- cmd_busy <= 0;
- command <= 0;
+ `INITIAL_BEGIN
data_buffer <= 0;
chip_e0 <= 0;
@@ -287,212 +86,82 @@ module m24c16dip8(data, ale_in, write, read, osc_in, zif);
chip_wc <= 0;
i2c_clock <= 0;
+ i2c_nreset <= 0;
i2c_write_byte <= 0;
i2c_read <= 0;
+ i2c_drive_ack <= 0;
i2c_do_start <= 0;
- i2c_expect_ack <= 0;
i2c_do_stop <= 0;
i2c_running <= 0;
- end
+ `INITIAL_END
- always @(posedge osc) begin
- if (delay_count == 0 && `IS_BUSY) begin
+ `ASYNCPROC_BEGIN
+ if (`CMD_IS_RUNNING) begin
if (i2c_running) begin
- if (i2c_finished && i2c_running == 2) begin
+ if (i2c_finished && i2c_clock) begin
i2c_running <= 0;
- `SET_FINISHED;
+ `CMD_FINISH
end else begin
- i2c_running <= 2;
i2c_clock <= ~i2c_clock;
- `DELAY_1P5US;
+ `UDELAY(250)
end
end else begin
- case (command)
- CMD_DEVSEL_READ: begin
- i2c_write_byte[7] <= 1;
- i2c_write_byte[6] <= 0;
- i2c_write_byte[5] <= 1;
- i2c_write_byte[4] <= 0;
- i2c_write_byte[3] <= chip_e2;
- i2c_write_byte[2] <= chip_e1;
- i2c_write_byte[1] <= chip_e0;
- i2c_write_byte[0] <= 1; /* Read */
- i2c_clock <= 0;
- i2c_read <= 0;
- i2c_do_start <= 1;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 0;
- i2c_running <= 1;
- end
- CMD_DEVSEL_WRITE: begin
- i2c_write_byte[7] <= 1;
- i2c_write_byte[6] <= 0;
- i2c_write_byte[5] <= 1;
- i2c_write_byte[4] <= 0;
- i2c_write_byte[3] <= chip_e2;
- i2c_write_byte[2] <= chip_e1;
- i2c_write_byte[1] <= chip_e0;
- i2c_write_byte[0] <= 0; /* Write */
- i2c_clock <= 0;
- i2c_read <= 0;
- i2c_do_start <= 1;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 0;
- i2c_running <= 1;
- end
- CMD_SETADDR: begin
- i2c_write_byte <= data_buffer;
- i2c_clock <= 0;
- i2c_read <= 0;
- i2c_do_start <= 0;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 0;
- i2c_running <= 1;
- end
- CMD_DATA_READ: begin
- i2c_clock <= 0;
- i2c_read <= 1;
- i2c_do_start <= 0;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 0;
- i2c_running <= 1;
- end
- CMD_DATA_READ_STOP: begin
- i2c_clock <= 0;
- i2c_read <= 1;
- i2c_do_start <= 0;
- i2c_expect_ack <= 0;
- i2c_do_stop <= 1;
- i2c_running <= 1;
- end
- CMD_DATA_WRITE: begin
- i2c_write_byte <= data_buffer;
- i2c_clock <= 0;
- i2c_read <= 0;
- i2c_do_start <= 0;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 0;
- i2c_running <= 1;
- end
- CMD_DATA_WRITE_STOP: begin
- i2c_write_byte <= data_buffer;
- i2c_clock <= 0;
- i2c_read <= 0;
- i2c_do_start <= 0;
- i2c_expect_ack <= 1;
- i2c_do_stop <= 1;
- i2c_running <= 1;
- end
- endcase
- end
- end else begin
- if (delay_count != 0) begin
- delay_count <= delay_count - 1;
+ i2c_write_byte <= data_buffer;
+ i2c_read <= `CMD_NR[0];
+ i2c_do_start <= `CMD_NR[1];
+ i2c_do_stop <= `CMD_NR[2];
+ i2c_drive_ack <= `CMD_NR[3];
+ i2c_clock <= 0;
+ i2c_running <= 1;
+ i2c_nreset <= 1;
end
end
- end
+ `ASYNCPROC_END
- always @(posedge write) begin
- case (address)
- 8'h10: begin /* Run command */
- command <= data;
- cmd_busy[0] <= ~cmd_busy[1];
+ `DATAWRITE_BEGIN
+ `ADDR(0): begin /* Run command */
+ `CMD_RUN(in_data)
end
- 8'h11: begin /* Write to data buffer */
- data_buffer[7:0] <= data[7:0];
+ `ADDR(1): begin /* Write to data buffer */
+ data_buffer[7:0] <= in_data[7:0];
end
- 8'h12: begin /* Set control pins */
- chip_e0 <= data[0];
- chip_e0_en <= data[1];
- chip_e1 <= data[2];
- chip_e1_en <= data[3];
- chip_e2 <= data[4];
- chip_e2_en <= data[5];
- chip_wc <= data[6];
+ `ADDR(2): begin /* Set control pins */
+ chip_e0 <= in_data[0];
+ chip_e0_en <= in_data[1];
+ chip_e1 <= in_data[2];
+ chip_e1_en <= in_data[3];
+ chip_e2 <= in_data[4];
+ chip_e2_en <= in_data[5];
+ chip_wc <= in_data[6];
end
- endcase
- end
+ `DATAWRITE_END
- always @(negedge read) begin
- case (address)
- 8'h10: begin /* Read data buffer */
- read_data <= i2c_read_byte;
+ `DATAREAD_BEGIN
+ `ADDR(0): begin /* Read data buffer */
+ out_data <= i2c_read_byte;
end
- 8'h11: begin /* Status read */
- read_data[0] <= cmd_busy[0];
- read_data[1] <= cmd_busy[1];
+ `ADDR(1): begin /* Status read */
+ out_data[0] <= `CMD_IS_RUNNING;
+ out_data[1] <= i2c_ack;
end
-
- 8'hFD: read_data <= `RUNTIME_ID & 16'hFF;
- 8'hFE: read_data <= (`RUNTIME_ID >> 8) & 16'hFF;
- 8'hFF: read_data <= `RUNTIME_REV;
- endcase
- end
-
- wire ale;
- IBUFG ale_ibufg(.I(ale_in), .O(ale));
-
- always @(negedge ale) begin
- address <= data;
- end
-
- assign read_oe = !read && address[4];
-
- bufif0(zif[1], low, low);
- bufif0(zif[2], low, low);
- bufif0(zif[3], low, low);
- bufif0(zif[4], low, low);
- bufif0(zif[5], low, low);
- bufif0(zif[6], low, low);
- bufif0(zif[7], low, low);
- bufif0(zif[8], low, low);
- bufif0(zif[9], low, low);
- bufif0(zif[10], low, low);
- bufif0(zif[11], low, low);
- bufif0(zif[12], low, low);
- bufif0(zif[13], low, low);
- bufif0(zif[14], low, low);
- bufif0(zif[15], low, low);
- bufif0(zif[16], low, low);
- bufif0(zif[17], low, low);
- bufif0(zif[18], low, low);
- bufif0(zif[19], low, low);
- bufif0(zif[20], low, low);
- bufif0(zif[21], chip_e0, !chip_e0_en); /* E0 */
- bufif0(zif[22], chip_e1, !chip_e1_en); /* E1 */
- bufif0(zif[23], chip_e2, !chip_e2_en); /* E2 */
- bufif0(zif[24], low, low); /* VSS */
- bufif0(zif[25], chip_sda_out, !chip_sda_out_en); /* SDA */
- bufif0(zif[26], chip_scl, low); /* SCL */
- bufif0(zif[27], chip_wc, low); /* /WC */
- bufif0(zif[28], high, low); /* VCC */
- bufif0(zif[29], low, low);
- bufif0(zif[30], low, low);
- bufif0(zif[31], low, low);
- bufif0(zif[32], low, low);
- bufif0(zif[33], low, low);
- bufif0(zif[34], low, low);
- bufif0(zif[35], low, low);
- bufif0(zif[36], low, low);
- bufif0(zif[37], low, low);
- bufif0(zif[38], low, low);
- bufif0(zif[39], low, low);
- bufif0(zif[40], low, low);
- bufif0(zif[41], low, low);
- bufif0(zif[42], low, low);
- bufif0(zif[43], low, low);
- bufif0(zif[44], low, low);
- bufif0(zif[45], low, low);
- bufif0(zif[46], low, low);
- bufif0(zif[47], low, low);
- bufif0(zif[48], low, low);
-
- bufif1(data[0], read_data[0], read_oe);
- bufif1(data[1], read_data[1], read_oe);
- bufif1(data[2], read_data[2], read_oe);
- bufif1(data[3], read_data[3], read_oe);
- bufif1(data[4], read_data[4], read_oe);
- bufif1(data[5], read_data[5], read_oe);
- bufif1(data[6], read_data[6], read_oe);
- bufif1(data[7], read_data[7], read_oe);
-endmodule
+ `DATAREAD_END
+
+ `ZIF_UNUSED(1) `ZIF_UNUSED(2) `ZIF_UNUSED(3) `ZIF_UNUSED(4)
+ `ZIF_UNUSED(5) `ZIF_UNUSED(6) `ZIF_UNUSED(7) `ZIF_UNUSED(8)
+ `ZIF_UNUSED(9) `ZIF_UNUSED(10) `ZIF_UNUSED(11) `ZIF_UNUSED(12)
+ `ZIF_UNUSED(13) `ZIF_UNUSED(14) `ZIF_UNUSED(15) `ZIF_UNUSED(16)
+ `ZIF_UNUSED(17) `ZIF_UNUSED(18) `ZIF_UNUSED(19) `ZIF_UNUSED(20)
+ `ZIF_BUF1(21, chip_e0, chip_e0_en) /* E0 */
+ `ZIF_BUF1(22, chip_e1, chip_e1_en) /* E1 */
+ `ZIF_BUF1(23, chip_e2, chip_e2_en) /* E2 */
+ `ZIF_BUF1(24, low, high) /* VSS */
+ `ZIF_BUF1(25, chip_sda_out, chip_sda_out_en) /* SDA */
+ `ZIF_BUF1(26, chip_scl_out, chip_scl_out_en) /* SCL */
+ `ZIF_BUF1(27, chip_wc, high) /* /WC */
+ `ZIF_BUF1(28, high, high) /* VCC */
+ `ZIF_UNUSED(29) `ZIF_UNUSED(30) `ZIF_UNUSED(31) `ZIF_UNUSED(32)
+ `ZIF_UNUSED(33) `ZIF_UNUSED(34) `ZIF_UNUSED(35) `ZIF_UNUSED(36)
+ `ZIF_UNUSED(37) `ZIF_UNUSED(38) `ZIF_UNUSED(39) `ZIF_UNUSED(40)
+ `ZIF_UNUSED(41) `ZIF_UNUSED(42) `ZIF_UNUSED(43) `ZIF_UNUSED(44)
+ `ZIF_UNUSED(45) `ZIF_UNUSED(46) `ZIF_UNUSED(47) `ZIF_UNUSED(48)
+`BOTTOMHALF_END
diff --git a/libtoprammer/fpga/src/m24c16dip8/warning.filter b/libtoprammer/fpga/src/m24c16dip8/warning.filter
new file mode 100644
index 0000000..6218ade
--- /dev/null
+++ b/libtoprammer/fpga/src/m24c16dip8/warning.filter
@@ -0,0 +1 @@
+The\svalue\sinit\sof\sthe\sFF/Latch\si2c_nreset\shinder\sthe\sconstant\scleaning\sin\sthe\sblock
bues.ch cgit interface