summaryrefslogtreecommitdiffstats
path: root/libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v
diff options
context:
space:
mode:
Diffstat (limited to 'libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v')
-rw-r--r--libtoprammer/fpga/src/m24c16dip8/m24c16dip8.v483
1 files changed, 76 insertions, 407 deletions
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
bues.ch cgit interface