aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2014-11-18 15:29:31 -0500
committerPaul Selkirk <paul@psgd.org>2014-11-18 15:29:31 -0500
commit2ab8de5bcae8fd8f529a49d03dc69dc1e3377260 (patch)
treecc08b1d8d44820d582e54f54cb48d31525d1baec
parent283dea2f82bdfac2aeb0d026bc86c9d57b131915 (diff)
i2c_device_addr as output
-rw-r--r--build/Makefile20
-rw-r--r--src/rtl/coretest_hashes.v2
-rw-r--r--src/rtl/i2c_core.v581
3 files changed, 14 insertions, 589 deletions
diff --git a/build/Makefile b/build/Makefile
index 4188adb..b12183f 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -6,12 +6,20 @@ top_module = novena_fpga
isedir = /opt/Xilinx/14.3/ISE_DS
xil_env = . $(isedir)/settings64.sh
-vfiles = ../src/rtl/novena_fpga.v ../src/rtl/coretest_hashes.v ../src/rtl/i2c_core.v \
- ../src/rtl/sha1.v ../src/rtl/sha256.v ../src/rtl/sha512.v \
- ../../sha1/src/rtl/sha1_core.v ../../sha1/src/rtl/sha1_w_mem.v \
- ../../sha256/src/rtl/sha256_core.v ../../sha256/src/rtl/sha256_k_constants.v \
+vfiles = ../src/rtl/novena_fpga.v \
+ ../src/rtl/coretest_hashes.v \
+ ../src/rtl/sha1.v \
+ ../src/rtl/sha256.v \
+ ../src/rtl/sha512.v \
+ ../../i2c/src/rtl/i2c_core.v \
+ ../../sha1/src/rtl/sha1_core.v \
+ ../../sha1/src/rtl/sha1_w_mem.v \
+ ../../sha256/src/rtl/sha256_core.v \
+ ../../sha256/src/rtl/sha256_k_constants.v \
../../sha256/src/rtl/sha256_w_mem.v \
- ../../sha512/src/rtl/sha512_core.v ../../sha512/src/rtl/sha512_h_constants.v \
- ../../sha512/src/rtl/sha512_k_constants.v ../../sha512/src/rtl/sha512_w_mem.v
+ ../../sha512/src/rtl/sha512_core.v \
+ ../../sha512/src/rtl/sha512_h_constants.v \
+ ../../sha512/src/rtl/sha512_k_constants.v \
+ ../../sha512/src/rtl/sha512_w_mem.v
include xilinx.mk
diff --git a/src/rtl/coretest_hashes.v b/src/rtl/coretest_hashes.v
index 567d4f7..9067674 100644
--- a/src/rtl/coretest_hashes.v
+++ b/src/rtl/coretest_hashes.v
@@ -115,8 +115,6 @@ module coretest_hashes(
.SCL(SCL),
.SDA(SDA),
.SDA_pd(SDA_pd),
- .i2c_addr_low(I2C_SHA1_ADDR),
- .i2c_addr_high(I2C_SHA512_ADDR),
.i2c_device_addr(i2c_device_addr),
.rxd_syn(i2c_rxd_syn),
diff --git a/src/rtl/i2c_core.v b/src/rtl/i2c_core.v
deleted file mode 100644
index cbf76c6..0000000
--- a/src/rtl/i2c_core.v
+++ /dev/null
@@ -1,581 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2011, Andrew "bunnie" Huang
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation and/or
-// other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-//////////////////////////////////////////////////////////////////////////////
-// A simple I2C slave implementation. Oversampled for robustness.
-// The slave is extended into the snoop & surpress version for the DDC bus;
-// this is just a starting point for basic testing and also simple comms
-// with the CPU.
-//
-// i2c slave module requires the top level module to implement the IOBs
-// This is just to keep the tri-state easy to implemen across the hierarchy
-//
-// The code required on the top level is:
-// IOBUF #(.DRIVE(12), .SLEW("SLOW")) IOBUF_sda (.IO(SDA), .I(1'b0), .T(!SDA_pd));
-//
-///////////
-`timescale 1 ns / 1 ps
-
-module i2c_core (
- input wire clk,
- input wire reset,
-
- // External data interface
- input wire SCL,
- input wire SDA,
- output reg SDA_pd,
- input wire [6:0] i2c_addr_low,
- input wire [6:0] i2c_addr_high,
- output wire [6:0] i2c_device_addr,
-
- // Internal receive interface.
- output wire rxd_syn,
- output [7 : 0] rxd_data,
- input wire rxd_ack,
-
- // Internal transmit interface.
- input wire txd_syn,
- input wire [7 : 0] txd_data,
- output wire txd_ack
- );
-
- /////// I2C physical layer components
- /// SDA is stable when SCL is high.
- /// If SDA moves while SCL is high, this is considered a start or stop condition.
- ///
- /// Otherwise, SDA can move around when SCL is low (this is where we suppress bits or
- /// overdrive as needed). SDA is a wired-AND bus, so you only "drive" zero.
- ///
- /// In an oversampled implementation, a rising and falling edge de-glitcher is needed
- /// for SCL and SDA.
- ///
-
- // rise fall time cycles computation:
- // At 400kHz operation, 2.5us is a cycle. "chatter" from transition should be about
- // 5% of total cycle time max (just rule of thumb), so 0.125us should be the equiv
- // number of cycles.
- // For the demo board, a 25 MHz clock is provided, and 0.125us ~ 4 cycles
- // At 100kHz operation, 10us is a cycle, so 0.5us ~ 12 cycles
- parameter TRF_CYCLES = 5'd4; // number of cycles for rise/fall time
-
- ////////////////
- ///// protocol-level state machine
- ////////////////
- parameter I2C_START = 16'b1 << 0; // should only pass through this state for one cycle
- parameter I2C_RESTART = 16'b1 << 1;
- parameter I2C_DADDR = 16'b1 << 2;
- parameter I2C_ACK_DADDR = 16'b1 << 3;
- parameter I2C_WR_DATA = 16'b1 << 4;
- parameter I2C_ACK_WR = 16'b1 << 5;
- parameter I2C_END_WR = 16'b1 << 6;
- parameter I2C_RD_DATA = 16'b1 << 7;
- parameter I2C_ACK_RD = 16'b1 << 8;
- parameter I2C_END_RD = 16'b1 << 9;
- parameter I2C_END_RD2 = 16'b1 << 10;
- parameter I2C_WAITSTOP = 16'b1 << 11;
- parameter I2C_RXD_SYN = 16'b1 << 12;
- parameter I2C_RXD_ACK = 16'b1 << 13;
- parameter I2C_TXD_SYN = 16'b1 << 14;
- parameter I2C_TXD_ACK = 16'b1 << 15;
-
- parameter I2C_nSTATES = 16;
-
- reg [(I2C_nSTATES-1):0] I2C_cstate = {{(I2C_nSTATES-1){1'b0}}, 1'b1}; //current and next states
- reg [(I2C_nSTATES-1):0] I2C_nstate;
-
-//`define SIMULATION
-`ifdef SIMULATION
- // synthesis translate_off
- reg [8*20:1] I2C_state_ascii = "I2C_START ";
- always @(I2C_cstate) begin
- if (I2C_cstate == I2C_START) I2C_state_ascii <= "I2C_START ";
- else if (I2C_cstate == I2C_RESTART) I2C_state_ascii <= "I2C_RESTART ";
- else if (I2C_cstate == I2C_DADDR) I2C_state_ascii <= "I2C_DADDR ";
- else if (I2C_cstate == I2C_ACK_DADDR) I2C_state_ascii <= "I2C_ACK_DADDR ";
- else if (I2C_cstate == I2C_WR_DATA) I2C_state_ascii <= "I2C_WR_DATA ";
- else if (I2C_cstate == I2C_ACK_WR) I2C_state_ascii <= "I2C_ACK_WR ";
- else if (I2C_cstate == I2C_END_WR) I2C_state_ascii <= "I2C_END_WR ";
- else if (I2C_cstate == I2C_RD_DATA) I2C_state_ascii <= "I2C_RD_DATA ";
- else if (I2C_cstate == I2C_ACK_RD) I2C_state_ascii <= "I2C_ACK_RD ";
- else if (I2C_cstate == I2C_END_RD) I2C_state_ascii <= "I2C_END_RD ";
- else if (I2C_cstate == I2C_END_RD2) I2C_state_ascii <= "I2C_END_RD2 ";
- else if (I2C_cstate == I2C_WAITSTOP) I2C_state_ascii <= "I2C_WAITSTOP ";
- else if (I2C_cstate == I2C_RXD_SYN) I2C_state_ascii <= "I2C_RXD_SYN ";
- else if (I2C_cstate == I2C_RXD_ACK) I2C_state_ascii <= "I2C_RXD_ACK ";
- else if (I2C_cstate == I2C_TXD_SYN) I2C_state_ascii <= "I2C_TXD_SYN ";
- else if (I2C_cstate == I2C_TXD_ACK) I2C_state_ascii <= "I2C_TXD_ACK ";
- else I2C_state_ascii <= "WTF ";
- end
- // synthesis translate_on
-`endif
-
- reg [3:0] I2C_bitcnt;
- reg [7:0] I2C_daddr;
- reg [7:0] I2C_wdata;
- reg [7:0] I2C_rdata;
-
- reg rxd_syn_reg;
- reg txd_ack_reg;
-
- assign rxd_data = I2C_wdata;
- assign rxd_syn = rxd_syn_reg;
- assign txd_ack = txd_ack_reg;
-
- assign i2c_device_addr = I2C_daddr[7:1];
-
-
- ////////// code begins here
- always @ (posedge clk) begin
- if (reset || ((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_RISE))) // stop condition always resets
- I2C_cstate <= I2C_START;
- else
- I2C_cstate <= I2C_nstate;
- end
-
- always @ (*) begin
- case (I2C_cstate) //synthesis parallel_case full_case
- I2C_START: begin // wait for the start condition
- I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_DADDR : I2C_START;
- end
- I2C_RESTART: begin // repeated start moves immediately to DADDR
- I2C_nstate = I2C_DADDR;
- end
-
- // device address branch
- I2C_DADDR: begin // 8 bits to get the address
- I2C_nstate = ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_ACK_DADDR : I2C_DADDR;
- end
- I2C_ACK_DADDR: begin // depending upon W/R bit state, go to one of two branches
- I2C_nstate = (SCL_cstate == SCL_FALL) ?
- ((I2C_daddr[7:1] >= i2c_addr_low) &&
- (I2C_daddr[7:1] <= i2c_addr_high)) ?
- (I2C_daddr[0] == 1'b0 ? I2C_WR_DATA : I2C_TXD_SYN) :
- I2C_WAITSTOP : // !I2C_daddr match
- I2C_ACK_DADDR; // !SCL_FALL
- end
-
- // write branch
- I2C_WR_DATA: begin // 8 bits to get the write data
- I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
- ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_RXD_SYN : I2C_WR_DATA;
- end
- I2C_RXD_SYN: begin // put data on the coretest bus
- I2C_nstate = I2C_RXD_ACK;
- end
- I2C_RXD_ACK: begin // wait for coretest ack
- I2C_nstate = rxd_ack ? I2C_ACK_WR : I2C_RXD_ACK;
- end
- I2C_ACK_WR: begin // trigger the ack response (pull SDA low until next falling edge)
- // and stay in this state until the next falling edge of SCL
- I2C_nstate = (SCL_cstate == SCL_FALL) ? I2C_END_WR : I2C_ACK_WR;
- end
- I2C_END_WR: begin // one-cycle state to update address+1, reset SDA pulldown
- I2C_nstate = I2C_WR_DATA; // SCL is now low
- end
-
- // read branch
- I2C_TXD_SYN: begin // get data from the coretest bus
- // if data isn't available (txd_syn isn't asserted) by the time we
- // get to this state, it probably never will be, so skip it
- I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
- end
- I2C_TXD_ACK: begin // send coretest ack
- // hold ack high until syn is lowered
- I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
- end
- I2C_RD_DATA: begin // 8 bits to get the read data
- I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
- ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_ACK_RD : I2C_RD_DATA;
- end
- I2C_ACK_RD: begin // wait for an (n)ack response
- // need to sample (n)ack on a rising edge
- I2C_nstate = (SCL_cstate == SCL_RISE) ? I2C_END_RD : I2C_ACK_RD;
- end
- I2C_END_RD: begin // if nack, just go to start state (don't explicitly check stop event)
- // single cycle state for adr+1 update
- I2C_nstate = (SDA_cstate == SDA_LOW) ? I2C_END_RD2 : I2C_START;
- end
- I2C_END_RD2: begin // before entering I2C_RD_DATA, we need to have seen a falling edge.
- I2C_nstate = (SCL_cstate == SCL_FALL) ? I2C_RD_DATA : I2C_END_RD2;
- end
-
- // we're not the addressed device, so we just idle until we see a stop
- I2C_WAITSTOP: begin
- I2C_nstate = (((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_RISE))) ? // stop
- I2C_START :
- (((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_FALL))) ? // or start
- I2C_RESTART :
- I2C_WAITSTOP;
- end
- endcase // case (cstate)
- end
-
- always @ (posedge clk) begin
- if( reset ) begin
- I2C_bitcnt <= 4'b0;
- I2C_daddr <= 8'b0;
- I2C_wdata <= 8'b0;
- SDA_pd <= 1'b0;
- I2C_rdata <= 8'b0;
- end else begin
- case (I2C_cstate) // synthesis parallel_case full_case
- I2C_START: begin // everything in reset
- I2C_bitcnt <= 4'b0;
- I2C_daddr <= 8'b0;
- I2C_wdata <= 8'b0;
- I2C_rdata <= 8'b0;
- SDA_pd <= 1'b0;
- end
-
- I2C_RESTART: begin
- I2C_bitcnt <= 4'b0;
- I2C_daddr <= 8'b0;
- I2C_wdata <= 8'b0;
- I2C_rdata <= 8'b0;
- SDA_pd <= 1'b0;
- end
-
- // get my i2c device address (am I being talked to?)
- I2C_DADDR: begin // shift in the address on rising edges of clock
- if( SCL_cstate == SCL_RISE ) begin
- I2C_bitcnt <= I2C_bitcnt + 4'b1;
- I2C_daddr[7] <= I2C_daddr[6];
- I2C_daddr[6] <= I2C_daddr[5];
- I2C_daddr[5] <= I2C_daddr[4];
- I2C_daddr[4] <= I2C_daddr[3];
- I2C_daddr[3] <= I2C_daddr[2];
- I2C_daddr[2] <= I2C_daddr[1];
- I2C_daddr[1] <= I2C_daddr[0];
- I2C_daddr[0] <= (SDA_cstate == SDA_HIGH) ? 1'b1 : 1'b0;
- end else begin // we're oversampled so we need a hold-state gutter
- I2C_bitcnt <= I2C_bitcnt;
- I2C_daddr <= I2C_daddr;
- end // else: !if( SCL_cstate == SCL_RISE )
- SDA_pd <= 1'b0;
- I2C_wdata <= 8'b0;
- I2C_rdata <= 8'b0;
- end // case: I2C_DADDR
- I2C_ACK_DADDR: begin
- SDA_pd <= 1'b1; // active pull down ACK
- I2C_daddr <= I2C_daddr;
- I2C_bitcnt <= 4'b0;
- I2C_wdata <= 8'b0;
- I2C_rdata <= 8'b0;
- end
-
- // write branch
- I2C_WR_DATA: begin // shift in data on rising edges of clock
- if( SCL_cstate == SCL_RISE ) begin
- I2C_bitcnt <= I2C_bitcnt + 4'b1;
- I2C_wdata[7] <= I2C_wdata[6];
- I2C_wdata[6] <= I2C_wdata[5];
- I2C_wdata[5] <= I2C_wdata[4];
- I2C_wdata[4] <= I2C_wdata[3];
- I2C_wdata[3] <= I2C_wdata[2];
- I2C_wdata[2] <= I2C_wdata[1];
- I2C_wdata[1] <= I2C_wdata[0];
- I2C_wdata[0] <= (SDA_cstate == SDA_HIGH) ? 1'b1 : 1'b0;
- end else begin
- I2C_bitcnt <= I2C_bitcnt; // hold state gutter
- I2C_wdata <= I2C_wdata;
- end // else: !if( SCL_cstate == SCL_RISE )
- SDA_pd <= 1'b0;
- I2C_daddr <= I2C_daddr;
- I2C_rdata <= I2C_rdata;
- end // case: I2C_WR_DATA
- I2C_RXD_SYN: begin // put data on the coretest bus and raise syn
- rxd_syn_reg <= 1;
- end
- I2C_RXD_ACK: begin // wait for coretest ack
- if (rxd_ack)
- rxd_syn_reg <= 0;
- end
- I2C_ACK_WR: begin
- SDA_pd <= 1'b1; // active pull down ACK
- I2C_daddr <= I2C_daddr;
- I2C_bitcnt <= 4'b0;
- I2C_wdata <= I2C_wdata;
- I2C_rdata <= I2C_rdata;
- end
- I2C_END_WR: begin
- SDA_pd <= 1'b0; // let SDA rise (host may look for this to know ack is done
- I2C_bitcnt <= 4'b0;
- I2C_wdata <= 8'b0;
- I2C_rdata <= I2C_rdata;
- I2C_daddr <= I2C_daddr;
- end
-
- // read branch
- I2C_TXD_SYN: begin // get data from the coretest bus
- if (txd_syn) begin
- I2C_rdata <= txd_data;
- txd_ack_reg <= 1;
- end
- end
- I2C_TXD_ACK: begin // send coretest ack
- if (!txd_syn)
- txd_ack_reg <= 0;
- end
- I2C_RD_DATA: begin // shift out data on falling edges of clock
- SDA_pd <= I2C_rdata[7] ? 1'b0 : 1'b1;
- if( SCL_cstate == SCL_RISE ) begin
- I2C_bitcnt <= I2C_bitcnt + 4'b1;
- end else begin
- I2C_bitcnt <= I2C_bitcnt; // hold state gutter
- end
-
- if( SCL_cstate == SCL_FALL ) begin
- I2C_rdata[7] <= I2C_rdata[6];
- I2C_rdata[6] <= I2C_rdata[5];
- I2C_rdata[5] <= I2C_rdata[4];
- I2C_rdata[4] <= I2C_rdata[3];
- I2C_rdata[3] <= I2C_rdata[2];
- I2C_rdata[2] <= I2C_rdata[1];
- I2C_rdata[1] <= I2C_rdata[0];
- I2C_rdata[0] <= 1'b0;
- end else begin
- I2C_rdata <= I2C_rdata;
- end // else: !if( SCL_cstate == SCL_RISE )
- I2C_daddr <= I2C_daddr;
- I2C_wdata <= I2C_wdata;
- end // case: I2C_RD_DATA
- I2C_ACK_RD: begin
- SDA_pd <= 1'b0; // in ack state don't pull down, we are listening to host
- I2C_daddr <= I2C_daddr;
- I2C_bitcnt <= 4'b0;
- I2C_rdata <= I2C_rdata;
- I2C_wdata <= I2C_wdata;
- end
- I2C_END_RD: begin
- SDA_pd <= 1'b0; // let SDA rise (host may look for this to know ack is done
- I2C_daddr <= I2C_daddr;
- I2C_bitcnt <= 4'b0;
- I2C_rdata <= I2C_rdata;
- I2C_wdata <= I2C_wdata;
- end
- I2C_END_RD2: begin
- SDA_pd <= 1'b0;
- I2C_daddr <= 8'b0;
- I2C_bitcnt <= 4'b0;
- I2C_rdata <= I2C_rdata;
- I2C_wdata <= I2C_wdata;
- end
-
- I2C_WAITSTOP: begin
- SDA_pd <= 1'b0;
- I2C_daddr <= 8'b0;
- I2C_bitcnt <= 4'b0;
- I2C_rdata <= I2C_rdata;
- I2C_wdata <= I2C_wdata;
- end
- endcase // case (cstate)
- end // else: !if( reset )
- end // always @ (posedge clk or posedge reset)
-
-
- ///////////////////////////////////////////////////////////////
- /////////// low level state machines //////////////////////////
- ///////////////////////////////////////////////////////////////
-
-
- ////////////////
- ///// SCL low-level sampling state machine
- ////////////////
- parameter SCL_HIGH = 4'b1 << 0; // should only pass through this state for one cycle
- parameter SCL_FALL = 4'b1 << 1;
- parameter SCL_LOW = 4'b1 << 2;
- parameter SCL_RISE = 4'b1 << 3;
- parameter SCL_nSTATES = 4;
-
- reg [(SCL_nSTATES-1):0] SCL_cstate = {{(SCL_nSTATES-1){1'b0}}, 1'b1}; //current and next states
- reg [(SCL_nSTATES-1):0] SCL_nstate;
-
-//`define SIMULATION
-`ifdef SIMULATION
- // synthesis translate_off
- reg [8*20:1] SCL_state_ascii = "SCL_HIGH ";
-
- always @(SCL_cstate) begin
- if (SCL_cstate == SCL_HIGH) SCL_state_ascii <= "SCL_HIGH ";
- else if (SCL_cstate == SCL_FALL) SCL_state_ascii <= "SCL_FALL ";
- else if (SCL_cstate == SCL_LOW ) SCL_state_ascii <= "SCL_LOW ";
- else if (SCL_cstate == SCL_RISE) SCL_state_ascii <= "SCL_RISE ";
- else SCL_state_ascii <= "WTF ";
- end
- // synthesis translate_on
-`endif
-
- reg [4:0] SCL_rfcnt;
- reg SCL_s, SCL_sync;
- reg SDA_s, SDA_sync;
-
- always @ (posedge clk) begin
- if (reset)
- SCL_cstate <= SCL_HIGH; // always start here even if it's wrong -- easier to test
- else
- SCL_cstate <= SCL_nstate;
- end
-
- always @ (*) begin
- case (SCL_cstate) //synthesis parallel_case full_case
- SCL_HIGH: begin
- SCL_nstate = ((SCL_rfcnt > TRF_CYCLES) && (SCL_sync == 1'b0)) ? SCL_FALL : SCL_HIGH;
- end
- SCL_FALL: begin
- SCL_nstate = SCL_LOW;
- end
- SCL_LOW: begin
- SCL_nstate = ((SCL_rfcnt > TRF_CYCLES) && (SCL_sync == 1'b1)) ? SCL_RISE : SCL_LOW;
- end
- SCL_RISE: begin
- SCL_nstate = SCL_HIGH;
- end
- endcase // case (cstate)
- end // always @ (*)
-
- always @ (posedge clk) begin
- if( reset ) begin
- SCL_rfcnt <= 5'b0;
- end else begin
- case (SCL_cstate) // synthesis parallel_case full_case
- SCL_HIGH: begin
- if( SCL_sync == 1'b1 ) begin
- SCL_rfcnt <= 5'b0;
- end else begin
- SCL_rfcnt <= SCL_rfcnt + 5'b1;
- end
- end
- SCL_FALL: begin
- SCL_rfcnt <= 5'b0;
- end
- SCL_LOW: begin
- if( SCL_sync == 1'b0 ) begin
- SCL_rfcnt <= 5'b0;
- end else begin
- SCL_rfcnt <= SCL_rfcnt + 5'b1;
- end
- end
- SCL_RISE: begin
- SCL_rfcnt <= 5'b0;
- end
- endcase // case (cstate)
- end // else: !if( reset )
- end // always @ (posedge clk or posedge reset)
-
-
- ////////////////
- ///// SDA low-level sampling state machine
- ////////////////
- parameter SDA_HIGH = 4'b1 << 0; // should only pass through this state for one cycle
- parameter SDA_FALL = 4'b1 << 1;
- parameter SDA_LOW = 4'b1 << 2;
- parameter SDA_RISE = 4'b1 << 3;
- parameter SDA_nSTATES = 4;
-
- reg [(SDA_nSTATES-1):0] SDA_cstate = {{(SDA_nSTATES-1){1'b0}}, 1'b1}; //current and next states
- reg [(SDA_nSTATES-1):0] SDA_nstate;
-
-//`define SIMULATION
-`ifdef SIMULATION
- // synthesis translate_off
- reg [8*20:1] SDA_state_ascii = "SDA_HIGH ";
-
- always @(SDA_cstate) begin
- if (SDA_cstate == SDA_HIGH) SDA_state_ascii <= "SDA_HIGH ";
- else if (SDA_cstate == SDA_FALL) SDA_state_ascii <= "SDA_FALL ";
- else if (SDA_cstate == SDA_LOW ) SDA_state_ascii <= "SDA_LOW ";
- else if (SDA_cstate == SDA_RISE) SDA_state_ascii <= "SDA_RISE ";
- else SDA_state_ascii <= "WTF ";
- end
- // synthesis translate_on
-`endif
-
- reg [4:0] SDA_rfcnt;
-
- always @ (posedge clk) begin
- if (reset)
- SDA_cstate <= SDA_HIGH; // always start here even if it's wrong -- easier to test
- else
- SDA_cstate <= SDA_nstate;
- end
-
- always @ (*) begin
- case (SDA_cstate) //synthesis parallel_case full_case
- SDA_HIGH: begin
- SDA_nstate = ((SDA_rfcnt > TRF_CYCLES) && (SDA_sync == 1'b0)) ? SDA_FALL : SDA_HIGH;
- end
- SDA_FALL: begin
- SDA_nstate = SDA_LOW;
- end
- SDA_LOW: begin
- SDA_nstate = ((SDA_rfcnt > TRF_CYCLES) && (SDA_sync == 1'b1)) ? SDA_RISE : SDA_LOW;
- end
- SDA_RISE: begin
- SDA_nstate = SDA_HIGH;
- end
- endcase // case (cstate)
- end // always @ (*)
-
- always @ (posedge clk) begin
- if( reset ) begin
- SDA_rfcnt <= 5'b0;
- end else begin
- case (SDA_cstate) // synthesis parallel_case full_case
- SDA_HIGH: begin
- if( SDA_sync == 1'b1 ) begin
- SDA_rfcnt <= 5'b0;
- end else begin
- SDA_rfcnt <= SDA_rfcnt + 5'b1;
- end
- end
- SDA_FALL: begin
- SDA_rfcnt <= 5'b0;
- end
- SDA_LOW: begin
- if( SDA_sync == 1'b0 ) begin
- SDA_rfcnt <= 5'b0;
- end else begin
- SDA_rfcnt <= SDA_rfcnt + 5'b1;
- end
- end
- SDA_RISE: begin
- SDA_rfcnt <= 5'b0;
- end
- endcase // case (cstate)
- end // else: !if( reset )
- end // always @ (posedge clk or posedge reset)
-
-
-
- /////////////////////
- /////// synchronizers
- /////////////////////
- always @ (posedge clk) begin
- SCL_s <= SCL;
- SCL_sync <= SCL_s;
- SDA_s <= SDA;
- SDA_sync <= SDA_s;
- end // always @ (posedge clk or posedge reset)
-
-endmodule // i2c_slave