text:
/////////////////////////////////////////////////////////////////////
////                                                             ////
////  WISHBONE rev.B2 compliant I2C Master bit-controller        ////
////                                                             ////
////                                                             ////
////  Author: Richard Herveille                                  ////
////          richard@asics.ws                                   ////
////          www.asics.ws                                       ////
////                                                             ////
////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2001 Richard Herveille                        ////
////                    richard@asics.ws                         ////
////                                                             ////
//// This source file may be used and distributed without        ////
//// restriction provided that this copyright statement is not   ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
////                                                             ////
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
//// 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.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////

//  CVS Log
//
//  $Id: i2c_master_bit_ctrl.v,v 1.14 2009-01-20 10:25:29 rherveille Exp $
//
//  $Date: 2009-01-20 10:25:29 $
//  $Revision: 1.14 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: $
//               Revision 1.14  2009/01/20 10:25:29  rherveille
//               Added clock synchronization logic
//               Fixed slave_wait signal
//
//               Revision 1.13  2009/01/19 20:29:26  rherveille
//               Fixed synopsys miss spell (synopsis)
//               Fixed cr[0] register width
//               Fixed ! usage instead of ~
//               Fixed bit controller parameter width to 18bits
//
//               Revision 1.12  2006/09/04 09:08:13  rherveille
//               fixed short scl high pulse after clock stretch
//               fixed slave model not returning correct '(n)ack' signal
//
//               Revision 1.11  2004/05/07 11:02:26  rherveille
//               Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
//
//               Revision 1.10  2003/08/09 07:01:33  rherveille
//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
//               Fixed a potential bug in the byte controller's host-acknowledge generation.
//
//               Revision 1.9  2003/03/10 14:26:37  rherveille
//               Fixed cmd_ack generation item (no bug).
//
//               Revision 1.8  2003/02/05 00:06:10  rherveille
//               Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
//
//               Revision 1.7  2002/12/26 16:05:12  rherveille
//               Small code simplifications
//
//               Revision 1.6  2002/12/26 15:02:32  rherveille
//               Core is now a Multimaster I2C controller
//
//               Revision 1.5  2002/11/30 22:24:40  rherveille
//               Cleaned up code
//
//               Revision 1.4  2002/10/30 18:10:07  rherveille
//               Fixed some reported minor start/stop generation timing issuess.
//
//               Revision 1.3  2002/06/15 07:37:03  rherveille
//               Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
//
//               Revision 1.2  2001/11/05 11:59:25  rherveille
//               Fixed wb_ack_o generation bug.
//               Fixed bug in the byte_controller statemachine.
//               Added headers.
//

//
/////////////////////////////////////
// Bit controller section
/////////////////////////////////////
//
// Translate simple commands into SCL/SDA transitions
// Each command has 5 states, A/B/C/D/idle
//
// start:	SCL	~~~~~~~~~~\____
//	SDA	~~~~~~~~\______
//		 x | A | B | C | D | i
//
// repstart	SCL	____/~~~~\___
//	SDA	__/~~~\______
//		 x | A | B | C | D | i
//
// stop	SCL	____/~~~~~~~~
//	SDA	==\____/~~~~~
//		 x | A | B | C | D | i
//
//- write	SCL	____/~~~~\____
//	SDA	==X=========X=
//		 x | A | B | C | D | i
//
//- read	SCL	____/~~~~\____
//	SDA	XXXX=====XXXX
//		 x | A | B | C | D | i
//

// Timing:     Normal mode      Fast mode
///////////////////////////////////////////////////////////////////////
// Fscl        100KHz           400KHz
// Th_scl      4.0us            0.6us   High period of SCL
// Tl_scl      4.7us            1.3us   Low period of SCL
// Tsu:sta     4.7us            0.6us   setup time for a repeated start condition
// Tsu:sto     4.0us            0.6us   setup time for a stop conditon
// Tbuf        4.7us            1.3us   Bus free time between a stop and start condition
//

// synopsys translate_off
`include "timescale.v"
// synopsys translate_on

`include "i2c_master_defines.v"

module i2c_master_bit_ctrl (
    input             clk,      // system clock
    input             rst,      // synchronous active high reset
    input             nReset,   // asynchronous active low reset
    input             ena,      // core enable signal

    input      [15:0] clk_cnt,  // clock prescale value

    input      [ 3:0] cmd,      // command (from byte controller)
    output reg        cmd_ack,  // command complete acknowledge
    output reg        busy,     // i2c bus busy
    output reg        al,       // i2c bus arbitration lost

    input             din,
    output reg        dout,

    input             scl_i,    // i2c clock line input
    output            scl_o,    // i2c clock line output
    output reg        scl_oen,  // i2c clock line output enable (active low)
    input             sda_i,    // i2c data line input
    output            sda_o,    // i2c data line output
    output reg        sda_oen   // i2c data line output enable (active low)
);

    //
    // variable declarations
    //

    reg [ 1:0] cSCL, cSDA;      // capture SCL and SDA
    reg [ 2:0] fSCL, fSDA;      // SCL and SDA filter inputs
    reg        sSCL, sSDA;      // filtered and synchronized SCL and SDA inputs
    reg        dSCL, dSDA;      // delayed versions of sSCL and sSDA
    reg        dscl_oen;        // delayed scl_oen
    reg        sda_chk;         // check SDA output (Multi-master arbitration)
    reg        clk_en;          // clock generation signals
    reg        slave_wait;      // slave inserts wait states
    reg [15:0] cnt;             // clock divider counter (synthesis)
    reg [13:0] filter_cnt;      // clock divider for filter

    // state machine variable
    reg [17:0] c_state; // Removed attribute: synopsys enum_state

    //
    // module body
    //

    // whenever the slave is not ready it can delay the cycle by pulling SCL low
    // delay scl_oen
    always @(posedge clk)
      dscl_oen <= #1 scl_oen;

    // slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low
    // slave_wait remains asserted until the slave releases SCL
    always @(posedge clk or negedge nReset)
      if (!nReset) slave_wait <= 1'b0;
      else         slave_wait <= (scl_oen & ~dscl_oen & ~sSCL) | (slave_wait & ~sSCL);

    // master drives SCL high, but another master pulls it low
    // master start counting down its low cycle now (clock synchronization)
    wire scl_sync   = dSCL & ~sSCL & scl_oen;

    // generate clk enable signal
    always @(posedge clk or negedge nReset)
      if (~nReset)
      begin
          cnt    <= #1 16'h0;
          clk_en <= #1 1'b1;
      end
      else if (rst || ~|cnt || !ena || scl_sync)
      begin
          cnt    <= #1 clk_cnt;
          clk_en <= #1 1'b1;
      end
      else if (slave_wait)
      begin
          cnt    <= #1 cnt;
          clk_en <= #1 1'b0;
      end
      else
      begin
          cnt    <= #1 cnt - 16'h1;
          clk_en <= #1 1'b0;
      end

    // generate bus status controller

    // capture SDA and SCL
    // reduce metastability risk
    always @(posedge clk or negedge nReset)
      if (!nReset)
      begin
          cSCL <= #1 2'b00;
          cSDA <= #1 2'b00;
      end
      else if (rst)
      begin
          cSCL <= #1 2'b00;
          cSDA <= #1 2'b00;
      end
      else
      begin
          cSCL <= {cSCL[0],scl_i};
          cSDA <= {cSDA[0],sda_i};
      end

    // filter SCL and SDA signals; (attempt to) remove glitches
    always @(posedge clk or negedge nReset)
      if      (!nReset     ) filter_cnt <= 14'h0;
      else if (rst || !ena ) filter_cnt <= 14'h0;
      else if (~|filter_cnt) filter_cnt <= clk_cnt[15:2]; //16x I2C bus frequency
      else                   filter_cnt <= filter_cnt - 14'd1;

    always @(posedge clk or negedge nReset)
      if (!nReset)
      begin
          fSCL <= 3'b111;
          fSDA <= 3'b111;
      end
      else if (rst)
      begin
          fSCL <= 3'b111;
          fSDA <= 3'b111;
      end
      else if (~|filter_cnt)
      begin
          fSCL <= {fSCL[1:0],cSCL[1]};
          fSDA <= {fSDA[1:0],cSDA[1]};
      end

    // generate filtered SCL and SDA signals
    always @(posedge clk or negedge nReset)
      if (~nReset)
      begin
          sSCL <= #1 1'b1;
          sSDA <= #1 1'b1;

          dSCL <= #1 1'b1;
          dSDA <= #1 1'b1;
      end
      else if (rst)
      begin
          sSCL <= #1 1'b1;
          sSDA <= #1 1'b1;

          dSCL <= #1 1'b1;
          dSDA <= #1 1'b1;
      end
      else
      begin
          sSCL <= #1 &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]);
          sSDA <= #1 &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]);

          dSCL <= #1 sSCL;
          dSDA <= #1 sSDA;
      end

    // detect start condition => detect falling edge on SDA while SCL is high
    // detect stop condition => detect rising edge on SDA while SCL is high
    reg sta_condition;
    reg sto_condition;
    always @(posedge clk or negedge nReset)
      if (~nReset)
      begin
          sta_condition <= #1 1'b0;
          sto_condition <= #1 1'b0;
      end
      else if (rst)
      begin
          sta_condition <= #1 1'b0;
          sto_condition <= #1 1'b0;
      end
      else
      begin
          sta_condition <= #1 ~sSDA &  dSDA & sSCL;
          sto_condition <= #1  sSDA & ~dSDA & sSCL;
      end

    // generate i2c bus busy signal
    always @(posedge clk or negedge nReset)
      if      (!nReset) busy <= #1 1'b0;
      else if (rst    ) busy <= #1 1'b0;
      else              busy <= #1 (sta_condition | busy) & ~sto_condition;

    // generate arbitration lost signal
    // aribitration lost when:
    // 1) master drives SDA high, but the i2c bus is low
    // 2) stop detected while not requested
    reg cmd_stop;
    always @(posedge clk or negedge nReset)
      if (~nReset)
          cmd_stop <= #1 1'b0;
      else if (rst)
          cmd_stop <= #1 1'b0;
      else if (clk_en)
          cmd_stop <= #1 cmd == `I2C_CMD_STOP;

    always @(posedge clk or negedge nReset)
      if (~nReset)
          al <= #1 1'b0;
      else if (rst)
          al <= #1 1'b0;
      else
          al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);

    // generate dout signal (store SDA on rising edge of SCL)
    always @(posedge clk)
      if (sSCL & ~dSCL) dout <= #1 sSDA;

    // generate statemachine

    // nxt_state decoder
    parameter [17:0] idle    = 18'b0_0000_0000_0000_0000;
    parameter [17:0] start_a = 18'b0_0000_0000_0000_0001;
    parameter [17:0] start_b = 18'b0_0000_0000_0000_0010;
    parameter [17:0] start_c = 18'b0_0000_0000_0000_0100;
    parameter [17:0] start_d = 18'b0_0000_0000_0000_1000;
    parameter [17:0] start_e = 18'b0_0000_0000_0001_0000;
    parameter [17:0] stop_a  = 18'b0_0000_0000_0010_0000;
    parameter [17:0] stop_b  = 18'b0_0000_0000_0100_0000;
    parameter [17:0] stop_c  = 18'b0_0000_0000_1000_0000;
    parameter [17:0] stop_d  = 18'b0_0000_0001_0000_0000;
    parameter [17:0] rd_a    = 18'b0_0000_0010_0000_0000;
    parameter [17:0] rd_b    = 18'b0_0000_0100_0000_0000;
    parameter [17:0] rd_c    = 18'b0_0000_1000_0000_0000;
    parameter [17:0] rd_d    = 18'b0_0001_0000_0000_0000;
    parameter [17:0] wr_a    = 18'b0_0010_0000_0000_0000;
    parameter [17:0] wr_b    = 18'b0_0100_0000_0000_0000;
    parameter [17:0] wr_c    = 18'b0_1000_0000_0000_0000;
    parameter [17:0] wr_d    = 18'b1_0000_0000_0000_0000;

    always @(posedge clk or negedge nReset)
      if (!nReset)
      begin
          c_state <= #1 idle;
          cmd_ack <= #1 1'b0;
          scl_oen <= #1 1'b1;
          sda_oen <= #1 1'b1;
          sda_chk <= #1 1'b0;
      end
      else if (rst | al)
      begin
          c_state <= #1 idle;
          cmd_ack <= #1 1'b0;
          scl_oen <= #1 1'b1;
          sda_oen <= #1 1'b1;
          sda_chk <= #1 1'b0;
      end
      else
      begin
          cmd_ack   <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle

          if (clk_en)
              case (c_state) // Removed attribute: synopsys full_case parallel_case
                    // idle state
                    idle:
                    begin
                        case (cmd) // Removed attribute: synopsys full_case parallel_case
                             `I2C_CMD_START: c_state <= #1 start_a;
                             `I2C_CMD_STOP:  c_state <= #1 stop_a;
                             `I2C_CMD_WRITE: c_state <= #1 wr_a;
                             `I2C_CMD_READ:  c_state <= #1 rd_a;
                             default:        c_state <= #1 idle;
                        endcase

                        scl_oen <= #1 scl_oen; // keep SCL in same state
                        sda_oen <= #1 sda_oen; // keep SDA in same state
                        sda_chk <= #1 1'b0;    // don't check SDA output
                    end

                    // start
                    start_a:
                    begin
                        c_state <= #1 start_b;
                        scl_oen <= #1 scl_oen; // keep SCL in same state
                        sda_oen <= #1 1'b1;    // set SDA high
                        sda_chk <= #1 1'b0;    // don't check SDA output
                    end

                    start_b:
                    begin
                        c_state <= #1 start_c;
                        scl_oen <= #1 1'b1; // set SCL high
                        sda_oen <= #1 1'b1; // keep SDA high
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    start_c:
                    begin
                        c_state <= #1 start_d;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 1'b0; // set SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    start_d:
                    begin
                        c_state <= #1 start_e;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 1'b0; // keep SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    start_e:
                    begin
                        c_state <= #1 idle;
                        cmd_ack <= #1 1'b1;
                        scl_oen <= #1 1'b0; // set SCL low
                        sda_oen <= #1 1'b0; // keep SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    // stop
                    stop_a:
                    begin
                        c_state <= #1 stop_b;
                        scl_oen <= #1 1'b0; // keep SCL low
                        sda_oen <= #1 1'b0; // set SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    stop_b:
                    begin
                        c_state <= #1 stop_c;
                        scl_oen <= #1 1'b1; // set SCL high
                        sda_oen <= #1 1'b0; // keep SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    stop_c:
                    begin
                        c_state <= #1 stop_d;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 1'b0; // keep SDA low
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    stop_d:
                    begin
                        c_state <= #1 idle;
                        cmd_ack <= #1 1'b1;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 1'b1; // set SDA high
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    // read
                    rd_a:
                    begin
                        c_state <= #1 rd_b;
                        scl_oen <= #1 1'b0; // keep SCL low
                        sda_oen <= #1 1'b1; // tri-state SDA
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    rd_b:
                    begin
                        c_state <= #1 rd_c;
                        scl_oen <= #1 1'b1; // set SCL high
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    rd_c:
                    begin
                        c_state <= #1 rd_d;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    rd_d:
                    begin
                        c_state <= #1 idle;
                        cmd_ack <= #1 1'b1;
                        scl_oen <= #1 1'b0; // set SCL low
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
                        sda_chk <= #1 1'b0; // don't check SDA output
                    end

                    // write
                    wr_a:
                    begin
                        c_state <= #1 wr_b;
                        scl_oen <= #1 1'b0; // keep SCL low
                        sda_oen <= #1 din;  // set SDA
                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
                    end

                    wr_b:
                    begin
                        c_state <= #1 wr_c;
                        scl_oen <= #1 1'b1; // set SCL high
                        sda_oen <= #1 din;  // keep SDA
                        sda_chk <= #1 1'b0; // don't check SDA output yet
                                            // allow some time for SDA and SCL to settle
                    end

                    wr_c:
                    begin
                        c_state <= #1 wr_d;
                        scl_oen <= #1 1'b1; // keep SCL high
                        sda_oen <= #1 din;
                        sda_chk <= #1 1'b1; // check SDA output
                    end

                    wr_d:
                    begin
                        c_state <= #1 idle;
                        cmd_ack <= #1 1'b1;
                        scl_oen <= #1 1'b0; // set SCL low
                        sda_oen <= #1 din;
                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
                    end

              endcase
      end

    // assign scl and sda output (always gnd)
    assign scl_o = 1'b0;
    assign sda_o = 1'b0;

endmodule


text:
module sram_arbiter(
    input               clk200,

    //output              SR_CE_n,
    output              SR_OE_n,
    output              SR_WE_n,
    output              SR_LB_n,
    output              SR_UB_n,
    output      [19:0]  SR_A,
    inout       [15:0]  SR_D,

    input               spi_req,
    output              spi_ack,
    input               spi_read,
    input       [19:0]  spi_address,
    input               spi_ub,
    input       [7:0]   spi_out_sram_in,
    output reg  [15:0]  spi_in_sram_out,

    input               dram_req,
    output              dram_ack,
    input               dram_read,
    input       [19:0]  dram_address,
    input               dram_lb,
    input               dram_ub,
    input       [15:0]  dram_out_sram_in,
    output reg  [15:0]  dram_in_sram_out
    );

    reg dram_ack_reg = 1'b0;
    assign dram_ack = dram_ack_reg;

    reg spi_ack_reg = 1'b0;
    assign spi_ack = spi_ack_reg;

    reg sr_oe_n = 1'b1;
    reg sr_we_n = 1'b1;
    reg sr_lb_n = 1'b1;
    reg sr_ub_n = 1'b1;
    reg [19:0] sr_a = 20'd0;

    assign SR_OE_n = sr_oe_n;
    assign SR_WE_n = sr_we_n;
    assign SR_LB_n = sr_lb_n;
    assign SR_UB_n = sr_ub_n;
    assign SR_A = sr_a;

    localparam DIR_READ   = 1'b0;
    localparam DIR_WRITE  = 1'b1;
    localparam SOURCE_DRAM = 1'b0;
    localparam SOURCE_SPI = 1'b1;

    reg [1:0] phase = 2'd0;
    reg accessing = 1'b0;
    reg access_source = 1'b0;
    reg access_dir = 1'b0;

    wire dram_wants = dram_req != dram_ack;
    wire spi_wants = spi_req != spi_ack;

    reg sram_drive = 1'b0;
    reg [15:0] sram_data_out = 16'd0;

    assign SR_D = sram_drive ? sram_data_out : 16'bz;

    always @(posedge clk200)
    begin
        case (phase)
            2'd0 : begin
                if (spi_wants)
                begin
                    accessing <= 1'b1;
                    access_source <= SOURCE_SPI;
                    access_dir <= spi_read ? DIR_READ : DIR_WRITE;
                    phase <= 2'd3;

                    sr_oe_n <= !spi_read;
                    sr_we_n <= 1'b1;
                    sr_lb_n <= spi_ub;
                    sr_ub_n <= !spi_ub;
                    sr_a <= spi_address;
                    sram_drive <= 1'b0;
                    sram_data_out <= spi_ub ? {spi_out_sram_in, 8'b0} : {8'b0, spi_out_sram_in};

                    spi_ack_reg <= spi_req;
                end
                else if (dram_wants)
                begin
                    accessing <= 1'b1;
                    access_source <= SOURCE_DRAM;
                    access_dir <= dram_read ? DIR_READ : DIR_WRITE;
                    phase <= 2'd3;

                    sr_oe_n <= !dram_read;
                    sr_we_n <= 1'b1;
                    sr_lb_n <= !dram_lb;
                    sr_ub_n <= !dram_ub;
                    sr_a <= dram_address;
                    sram_drive <= 1'b0;
                    sram_data_out <= dram_out_sram_in;

                    dram_ack_reg <= dram_req;
                end
                else
                begin
                    accessing <= 1'b0;
                    access_source <= SOURCE_DRAM;
                    access_dir <= DIR_READ;
                    phase <= 2'd0;

                    sr_oe_n <= 1'b1;
                    sr_we_n <= 1'b1;
                    sr_lb_n <= 1'b1;
                    sr_ub_n <= 1'b1;
                    sram_drive <= 1'b0;
                end
            end
            2'd3 : begin
                if (access_dir == DIR_WRITE)
                begin
                    sr_we_n <= 1'b0;
                    sram_drive <= 1'b1;
                end
                phase <= 2'd2;
            end
            2'd2 : begin
                phase <= 2'd1;
            end
            2'd1 : begin
                phase <= 2'd0;
            end
        endcase
    end

    always @(posedge clk200)
        if (phase == 2'd0 && accessing && access_dir == DIR_READ && access_source == SOURCE_SPI)
            spi_in_sram_out <= SR_D;

    always @(posedge clk200)
        if (phase == 2'd0 && accessing && access_dir == DIR_READ && access_source == SOURCE_DRAM)
            dram_in_sram_out <= SR_D;

endmodule

repo_language: C

mime_type: text/xml


text: `timescale 1ns / 10ps


text:
## VENDOR  "Altera"
## PROGRAM "Quartus Prime"
## VERSION "Version 18.0.0 Build 614 04/24/2018 SJ Lite Edition"

## DATE    "Sat Feb 09 15:38:50 2019"

##
## DEVICE  "10M08SCE144C8G"
##

#**************************************************************
# Time Information
#**************************************************************

set_time_format -unit ns -decimal_places 3

#**************************************************************
# Create Clock
#**************************************************************

create_clock -name clk14 -period 70.482 -waveform { 0.000 35.241 } [get_ports {CLK_14M}]
create_clock -name rpi_sclk -period 15.000 [get_ports {RPI_SCLK0}]

#**************************************************************
# Create Generated Clock
#**************************************************************

create_generated_clock -name clk200 -source [get_pins {a314_pll_inst|altpll_component|auto_generated|pll1|inclk[0]}] -duty_cycle 50/1 -multiply_by 14 -master_clock clk14 [get_pins {a314_pll_inst|altpll_component|auto_generated|pll1|clk[0]}]

#**************************************************************
# Set Clock Latency
#**************************************************************

#**************************************************************
# Set Clock Uncertainty
#**************************************************************

derive_clock_uncertainty

#**************************************************************
# Set Input Delay
#**************************************************************

create_clock -period [get_clock_info -period clk200] -name clk200_vin
create_clock -period 285 -name clk3_vin
create_clock -period 3571 -name clk280k_vin
create_clock -period 15.000 -name clk_spi_vin

set_input_delay -clock clk200_vin -max 0 [get_ports {SR_D[*]}]
set_input_delay -clock clk200_vin -min 0 [get_ports {SR_D[*]}]

set_input_delay -clock clk3_vin -max 0 [get_ports {DR_*}]
set_input_delay -clock clk3_vin -min 0 [get_ports {DR_*}]

set_input_delay -clock clk3_vin -max 0 [get_ports {CP_*}]
set_input_delay -clock clk3_vin -min 0 [get_ports {CP_*}]

set_input_delay -clock clk280k_vin -max 0 [get_ports {RTC_SDA}]
set_input_delay -clock clk280k_vin -min 0 [get_ports {RTC_SDA}]

set_input_delay -clock clk_spi_vin -clock_fall -max 0 [get_ports {RPI_MOSI0}]
set_input_delay -clock clk_spi_vin -clock_fall -min 0 [get_ports {RPI_MOSI0}]

#**************************************************************
# Set Output Delay
#**************************************************************

create_clock -period [get_clock_info -period clk200] -name clk200_vout
create_clock -period 285 -name clk3_vout
create_clock -period 3571 -name clk280k_vout
create_clock -period 15.000 -name clk_spi_vout

set_output_delay -clock clk200_vout -max 0 [get_ports {SR_*}]
set_output_delay -clock clk200_vout -min 0 [get_ports {SR_*}]

set_output_delay -clock clk3_vout -max 0 [get_ports {DR_D[*]}]
set_output_delay -clock clk3_vout -min 0 [get_ports {DR_D[*]}]

set_output_delay -clock clk3_vout -max 0 [get_ports {CP_D[*]}]
set_output_delay -clock clk3_vout -min 0 [get_ports {CP_D[*]}]

set_output_delay -clock clk280k_vout -max 0 [get_ports {RTC_*}]
set_output_delay -clock clk280k_vout -min 0 [get_ports {RTC_*}]

set_output_delay -clock clk_spi_vout -max 0 [get_ports {RPI_MISO0}]
set_output_delay -clock clk_spi_vout -min 0 [get_ports {RPI_MISO0}]

#**************************************************************
# Set Clock Groups
#**************************************************************

set_clock_groups -asynchronous -group {clk14 clk200 clk200_vin clk200_vout} -group {clk3_vin clk3_vout} -group {clk280k_vin clk280k_vout} -group {rpi_sclk clk_spi_vin clk_spi_vout}

#**************************************************************
# Set False Path
#**************************************************************

set_false_path -from [get_keepers {rtc_emulation:rtc_emu_inst|*}] -to [get_keepers {clock_port:clock_port_inst|*}]
set_false_path -from [get_keepers {clock_port:clock_port_inst|*}] -to [get_keepers {rtc_emulation:rtc_emu_inst|*}]

set_false_path -from [get_ports {RPI_SCE0}]

set_false_path -to [get_ports {AMI_INT2 RPI_IRQ}]

#**************************************************************
# Set Multicycle Path
#**************************************************************

#**************************************************************
# Set Maximum Delay
#**************************************************************

set_max_delay -from [get_clocks {clk200}] -to [get_ports {SR_A[*] SR_LB_n SR_OE_n SR_UB_n SR_WE_n}] 7.1

set_max_delay -from [get_clocks {clk200}] -to [get_ports {SR_D[*]}] 7.5

#**************************************************************
# Set Minimum Delay
#**************************************************************

#**************************************************************
# Set Input Transition
#**************************************************************


text:
/////////////////////////////////////////////////////////////////////
////                                                             ////
////  WISHBONE rev.B2 compliant I2C Master controller defines    ////
////                                                             ////
////                                                             ////
////  Author: Richard Herveille                                  ////
////          richard@asics.ws                                   ////
////          www.asics.ws                                       ////
////                                                             ////
////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2001 Richard Herveille                        ////
////                    richard@asics.ws                         ////
////                                                             ////
//// This source file may be used and distributed without        ////
//// restriction provided that this copyright statement is not   ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
////                                                             ////
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
//// 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.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////

//  CVS Log
//
//  $Id: i2c_master_defines.v,v 1.3 2001-11-05 11:59:25 rherveille Exp $
//
//  $Date: 2001-11-05 11:59:25 $
//  $Revision: 1.3 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: not supported by cvs2svn $

// I2C registers wishbone addresses

// bitcontroller states
`define I2C_CMD_NOP   4'b0000
`define I2C_CMD_START 4'b0001
`define I2C_CMD_STOP  4'b0010
`define I2C_CMD_WRITE 4'b0100
`define I2C_CMD_READ  4'b1000


text:
module cmem(
    input   clk200,

    output  AMI_INT2_n,
    output  RASP_IRQ,

    input spi_read,
    input spi_write,
    input [3:0] spi_address,
    input [3:0] spi_out_cmem_in,
    output reg [3:0] spi_in_cmem_out,

    input cp_read,
    input cp_write,
    input [3:0] cp_address,
    input [3:0] cp_out_cmem_in,
    output reg [3:0] cp_in_cmem_out,

    input dram_req,
    input dram_read,
    input [19:0] dram_address,

    output swap_address_mapping
    );

    reg [3:0] data[15:0];

    assign swap_address_mapping = data[11][0];
    wire autodetect_mode = data[11][1];

    reg dram_ack = 1'b0;
    reg [20:0] autodetect_address;

    reg [3:0] r_events = 4'd0;
    reg [3:0] r_enable = 4'd7;
    reg [3:0] a_events = 4'd0;
    reg [3:0] a_enable = 4'd3;

    reg a_block = 1'b0;
    reg drive_int2 = 1'b0;
    assign AMI_INT2_n = drive_int2 ? 1'b0 : 1'bz;

    reg r_armed = 1'b1;
    reg r_irq = 1'b0;
    assign RASP_IRQ = r_irq;

    /*
    Address map:

    reg0-5 - BA0-5
    regA   - multiple values
    regB   - autodetect, swap
    regC   - r-events
    regD   - r-enable
    regE   - a-events
    regF   - a-enable
    */

    wire rd_r_events = spi_read && spi_address == 4'd12;
    wire wr_r_events = cp_write && cp_address == 4'd12;
    wire wr_r_enable = spi_write && spi_address == 4'd13;

    wire rd_a_events = cp_read && cp_address == 4'd14;
    wire wr_a_events = spi_write && spi_address == 4'd14;
    wire wr_a_enable = cp_write && cp_address == 4'd15;

    wire r_trigger = ((wr_r_events ? (r_events | cp_out_cmem_in) : r_events) & (wr_r_enable ? spi_out_cmem_in : r_enable)) != 4'd0;

    reg [27:0] block_timeout = 28'd1;
    wire block_timed_out = block_timeout == 28'd0;

    wire a_should_drive = ((wr_a_events ? (a_events | spi_out_cmem_in) : a_events) & (wr_a_enable ? cp_out_cmem_in : a_enable)) != 4'd0 && !a_block;

    reg [20:0] rega_shift_out;

    always @(posedge clk200)
    begin
        if (spi_read)
            case (spi_address)
            4'd12: spi_in_cmem_out <= wr_r_events ? (r_events | cp_out_cmem_in) : r_events;
            4'd13: spi_in_cmem_out <= r_enable;
            4'd14, 4'd15: spi_in_cmem_out <= 4'd0;
            default: spi_in_cmem_out <= data[spi_address];
            endcase

        if (cp_read)
            case (cp_address)
            4'd10: cp_in_cmem_out <= rega_shift_out[3:0];
            4'd12, 4'd13: cp_in_cmem_out <= 4'd0;
            4'd14: cp_in_cmem_out <= wr_a_events ? (a_events | spi_out_cmem_in) : a_events;
            4'd15: cp_in_cmem_out <= a_enable;
            default: cp_in_cmem_out <= data[cp_address];
            endcase

        if (cp_write)
            data[cp_address] <= cp_out_cmem_in;

        if (cp_write && cp_address == 4'd11 && cp_out_cmem_in[1])
            autodetect_address <= 21'h1fffff;
        else if (autodetect_mode && dram_req != dram_ack && !dram_read)
            autodetect_address <= {dram_address, 1'b0};

        dram_ack <= dram_req;

        if (cp_address == 4'd10)
        begin
            if (cp_write)
                case (cp_out_cmem_in)
`ifdef is_a600
                    4'd0: rega_shift_out <= 21'h3; // {a600, autodetect}
`else
                    4'd0: rega_shift_out <= 21'h1; // {autodetect}
`endif
                    4'd1: rega_shift_out <= autodetect_address;
                    default: rega_shift_out <= 21'd0;
                endcase
            else if (cp_read)
                rega_shift_out[20:0] <= {4'd0, rega_shift_out[20:4]};
        end

        if (wr_a_enable)
            a_enable <= cp_out_cmem_in;

        if (wr_r_enable)
            r_enable <= spi_out_cmem_in;

        if (rd_r_events)
            r_armed <= 1'b1;
        else if (r_armed && r_trigger)
        begin
            r_irq <= !r_irq;
            r_armed <= 1'b0;
        end

        if (rd_r_events)
            r_events <= 4'd0;
        else if (wr_r_events)
            r_events <= r_events | cp_out_cmem_in;

        if (rd_a_events)
            a_events <= 4'd0;
        else if (wr_a_events)
            a_events <= a_events | spi_out_cmem_in;

        if (rd_a_events)
            block_timeout <= 28'd1;
        else if (drive_int2)
            block_timeout <= block_timeout + 28'd1;

        if (rd_a_events)
            a_block <= 1'b0;
        else if (block_timed_out)
            a_block <= 1'b1;

        if (!drive_int2 && a_should_drive)
            drive_int2 <= 1'b1;
        else if (drive_int2 && !a_should_drive)
            drive_int2 <= 1'b0;

    end

endmodule


text:
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2018  Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel FPGA IP License Agreement, or other applicable license
# agreement, including, without limitation, that your use is for
# the sole purpose of programming logic devices manufactured by
# Intel and sold by Intel or its authorized distributors.  Please
# refer to the applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 18.0.0 Build 614 04/24/2018 SJ Lite Edition
# Date created = 14:38:01  February 09, 2019
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
#		a314_600_assignment_defaults.qdf
#    If this file doesn't exist, see file:
#		assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
#    file is updated automatically by the Quartus Prime software
#    and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #

set_location_assignment PIN_27 -to CLK_14M
#
set_location_assignment PIN_131 -to CP_A[2]
set_location_assignment PIN_130 -to CP_A[3]
set_location_assignment PIN_129 -to CP_A[4]
set_location_assignment PIN_127 -to CP_A[5]
set_location_assignment PIN_136 -to CP_D[0]
set_location_assignment PIN_135 -to CP_D[1]
set_location_assignment PIN_134 -to CP_D[2]
set_location_assignment PIN_132 -to CP_D[3]
set_location_assignment PIN_122 -to CP_RD_n
set_location_assignment PIN_121 -to CP_WR_n
set_location_assignment PIN_123 -to CP_RTC_CS_n
#
set_location_assignment PIN_25 -to DR_A[0]
set_location_assignment PIN_24 -to DR_A[1]
set_location_assignment PIN_22 -to DR_A[2]
set_location_assignment PIN_21 -to DR_A[3]
set_location_assignment PIN_17 -to DR_A[4]
set_location_assignment PIN_15 -to DR_A[5]
set_location_assignment PIN_14 -to DR_A[6]
set_location_assignment PIN_13 -to DR_A[7]
set_location_assignment PIN_12 -to DR_A[8]
set_location_assignment PIN_11 -to DR_A[9]
set_location_assignment PIN_54 -to DR_D[0]
set_location_assignment PIN_52 -to DR_D[1]
set_location_assignment PIN_39 -to DR_D[10]
set_location_assignment PIN_38 -to DR_D[11]
set_location_assignment PIN_33 -to DR_D[12]
set_location_assignment PIN_32 -to DR_D[13]
set_location_assignment PIN_30 -to DR_D[14]
set_location_assignment PIN_29 -to DR_D[15]
set_location_assignment PIN_50 -to DR_D[2]
set_location_assignment PIN_48 -to DR_D[3]
set_location_assignment PIN_47 -to DR_D[4]
set_location_assignment PIN_46 -to DR_D[5]
set_location_assignment PIN_45 -to DR_D[6]
set_location_assignment PIN_44 -to DR_D[7]
set_location_assignment PIN_43 -to DR_D[8]
set_location_assignment PIN_41 -to DR_D[9]
set_location_assignment PIN_138 -to DR_WE_n
set_location_assignment PIN_140 -to DR_RAS_n[1]
set_location_assignment PIN_141 -to DR_RAS_n[0]
set_location_assignment PIN_10 -to DR_CASU_n[0]
set_location_assignment PIN_6 -to DR_CASU_n[1]
set_location_assignment PIN_7 -to DR_CASL_n[1]
set_location_assignment PIN_8 -to DR_CASL_n[0]
#
set_location_assignment PIN_124 -to AMI_INT2
set_location_assignment PIN_120 -to AMI_LED
#
set_location_assignment PIN_56 -to RPI_MISO0
set_location_assignment PIN_55 -to RPI_MOSI0
set_location_assignment PIN_80 -to RPI_SCE0
set_location_assignment PIN_57 -to RPI_SCLK0
#
set_location_assignment PIN_61 -to RPI_IRQ
#
set_location_assignment PIN_97 -to RTC_SCL
set_location_assignment PIN_112 -to RTC_SDA
#
set_location_assignment PIN_93 -to SR_A[0]
set_location_assignment PIN_92 -to SR_A[1]
set_location_assignment PIN_64 -to SR_A[10]
set_location_assignment PIN_65 -to SR_A[11]
set_location_assignment PIN_66 -to SR_A[12]
set_location_assignment PIN_69 -to SR_A[13]
set_location_assignment PIN_70 -to SR_A[14]
set_location_assignment PIN_110 -to SR_A[15]
set_location_assignment PIN_111 -to SR_A[16]
set_location_assignment PIN_113 -to SR_A[17]
set_location_assignment PIN_114 -to SR_A[18]
set_location_assignment PIN_118 -to SR_A[19]
set_location_assignment PIN_91 -to SR_A[2]
set_location_assignment PIN_90 -to SR_A[3]
set_location_assignment PIN_89 -to SR_A[4]
set_location_assignment PIN_88 -to SR_A[5]
set_location_assignment PIN_87 -to SR_A[6]
set_location_assignment PIN_86 -to SR_A[7]
set_location_assignment PIN_85 -to SR_A[8]
set_location_assignment PIN_62 -to SR_A[9]
set_location_assignment PIN_96 -to SR_D[0]
set_location_assignment PIN_98 -to SR_D[1]
set_location_assignment PIN_58 -to SR_D[10]
set_location_assignment PIN_74 -to SR_D[11]
set_location_assignment PIN_75 -to SR_D[12]
set_location_assignment PIN_76 -to SR_D[13]
set_location_assignment PIN_77 -to SR_D[14]
set_location_assignment PIN_78 -to SR_D[15]
set_location_assignment PIN_99 -to SR_D[2]
set_location_assignment PIN_100 -to SR_D[3]
set_location_assignment PIN_101 -to SR_D[4]
set_location_assignment PIN_102 -to SR_D[5]
set_location_assignment PIN_105 -to SR_D[6]
set_location_assignment PIN_106 -to SR_D[7]
set_location_assignment PIN_60 -to SR_D[8]
set_location_assignment PIN_59 -to SR_D[9]
set_location_assignment PIN_79 -to SR_LB_n
set_location_assignment PIN_84 -to SR_OE_n
set_location_assignment PIN_81 -to SR_UB_n
set_location_assignment PIN_119 -to SR_WE_n
#
set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M08SCE144C8G
set_global_assignment -name TOP_LEVEL_ENTITY a314_top
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 19.1.0
set_global_assignment -name PROJECT_CREATION_TIME_DATE "18:32:41  AUGUST 07, 2020"
set_global_assignment -name LAST_QUARTUS_VERSION "19.1.0 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PACKAGE EQFP
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name USE_CONFIGURATION_DEVICE ON
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[0] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[1] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[2] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[3] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[4] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[5] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[6] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[7] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[8] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[9] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[10] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[11] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[12] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[13] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[14] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[15] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[16] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[17] -disable
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SR_A[18] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[0] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[1] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[2] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[3] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[4] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[5] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[6] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[7] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[8] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[9] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[10] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[11] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[12] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[13] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[14] -disable
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SR_D[15] -disable
set_global_assignment -name VERILOG_FILE rtc_emulation.v
set_global_assignment -name VERILOG_FILE timescale.v
set_global_assignment -name VERILOG_FILE i2c_master_defines.v
set_global_assignment -name VERILOG_FILE i2c_master_byte_ctrl.v
set_global_assignment -name VERILOG_FILE i2c_master_bit_ctrl.v
set_global_assignment -name VERILOG_FILE a314_top.v
set_global_assignment -name QIP_FILE a314_pll.qip
set_global_assignment -name SDC_FILE a314.sdc
set_global_assignment -name VERILOG_FILE dram_port.v
set_global_assignment -name VERILOG_FILE sram_arbiter.v
set_global_assignment -name VERILOG_FILE clock_port.v
set_global_assignment -name VERILOG_FILE rtc_controller.v
set_global_assignment -name VERILOG_FILE cmem.v
set_global_assignment -name VERILOG_FILE spi_controller.v
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name VERILOG_MACRO "is_a600=1"
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top


text:
module rtc_controller(
    input           clk14,
    input           reset_n,

    input           scl_i,
    output          scl_o,
    output          scl_oen,
    input           sda_i,
    output          sda_o,
    output          sda_oen,

    input           read,
    input           write,
    output reg      ack,

    input   [3:0]   oki_second1,
    input   [3:0]   oki_second10,
    input   [3:0]   oki_minute1,
    input   [3:0]   oki_minute10,
    input   [3:0]   oki_hour1,
    input   [3:0]   oki_hour10,
    input   [3:0]   oki_day1,
    input   [3:0]   oki_day10,
    input   [3:0]   oki_month1,
    input   [3:0]   oki_month10,
    input   [3:0]   oki_year1,
    input   [3:0]   oki_year10,
    input   [3:0]   oki_weekday,

    output  [7:0]   ds_second,
    output  [7:0]   ds_minute,
    output  [7:0]   ds_hour,
    output  [7:0]   ds_weekday,
    output  [7:0]   ds_day,
    output  [7:0]   ds_month,
    output  [7:0]   ds_year
    );

    localparam      I2C_ADDRESS = 7'b1101000;

    reg     [4:0]   i2c_cmd;
    reg     [7:0]   i2c_din;

    wire            i2c_cmd_ack;
    wire            i2c_ack_out;
    wire    [7:0]   i2c_dout;
    wire            i2c_busy;
    wire            i2c_al;

    reg     [4:0]   state;
    reg     [7:0]   data[6:0];

    assign ds_second   = data[0];
    assign ds_minute   = data[1];
    assign ds_hour     = data[2];
    assign ds_weekday  = data[3];
    assign ds_day      = data[4];
    assign ds_month    = data[5];
    assign ds_year     = data[6];

    wire go = (read | write) && !ack;

    always @(posedge clk14 or negedge reset_n)
    begin
        if (!reset_n)
        begin
            i2c_cmd <= 5'b00000;
            state <= 5'd0;
        end
        else
        begin
            ack <= 1'b0;

            case (state)
            5'd0:
            if (go)
            begin
                i2c_cmd <= 5'b10010;
                i2c_din <= {I2C_ADDRESS, 1'b0};
                state <= state + 5'd1;
                if (write)
                begin
                    data[0] <= {oki_second10, oki_second1};
                    data[1] <= {oki_minute10, oki_minute1};
                    data[2] <= {oki_hour10, oki_hour1};
                    data[3] <= {4'd0, oki_weekday} + 8'd1;
                    data[4] <= {oki_day10, oki_day1};
                    data[5] <= {oki_month10, oki_month1};
                    data[6] <= {oki_year10, oki_year1};
                end
            end

            5'd1:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b00010;
                i2c_din <= 8'd0;

                if (read)
                    state <= 5'd2;
                else // if (write)
                    state <= 5'd11;
            end

            5'd2:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b10010;
                i2c_din <= {I2C_ADDRESS, 1'b1};
                state <= state + 5'd1;
            end

            5'd3:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b00100;
                state <= state + 5'd1;
            end

            5'd4, 5'd5, 5'd6, 5'd7, 5'd8:
            if (i2c_cmd_ack)
            begin
                data[state - 5'd4] <= i2c_dout;
                i2c_cmd <= 5'b00100;
                state <= state + 5'd1;
            end

            5'd9:
            if (i2c_cmd_ack)
            begin
                data[state - 5'd4] <= i2c_dout;
                i2c_cmd <= 5'b01101;
                state <= state + 5'd1;
            end

            5'd10:
            if (i2c_cmd_ack)
            begin
                data[state - 5'd4] <= i2c_dout;
                i2c_cmd <= 5'b00000;
                state <= 5'd0;
                ack <= 1'b1;
            end

            5'd11, 5'd12, 5'd13, 5'd14, 5'd15, 5'd16:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b00010;
                i2c_din <= data[state - 5'd11];
                state <= state + 5'd1;
            end

            5'd17:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b01010;
                i2c_din <= data[state - 5'd11];
                state <= state + 5'd1;
            end

            5'd18:
            if (i2c_cmd_ack)
            begin
                i2c_cmd <= 5'b00000;
                state <= 5'd0;
                ack <= 1'b1;
            end

            endcase
        end
    end

    i2c_master_byte_ctrl i2c_inst(
        .clk(clk14),
        .rst(1'b0),
        .nReset(reset_n),
        .ena(1'b1),
        .clk_cnt(16'd9), // 14 MHz / (5 * 280 kHz) - 1 = 9
        .start(i2c_cmd[4]),
        .stop(i2c_cmd[3]),
        .read(i2c_cmd[2]),
        .write(i2c_cmd[1]),
        .ack_in(i2c_cmd[0]),
        .din(i2c_din),
        .cmd_ack(i2c_cmd_ack),
        .ack_out(i2c_ack_out),
        .dout(i2c_dout),
        .i2c_busy(i2c_busy),
        .i2c_al(i2c_al),
        .scl_i(scl_i),
        .scl_o(scl_o),
        .scl_oen(scl_oen),
        .sda_i(sda_i),
        .sda_o(sda_o),
        .sda_oen(sda_oen)
    );

endmodule


text:
reset_config none
interface bcm2835gpio

bcm2835gpio_peripheral_base 0x3F000000

# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
# These depend on system clock, calibrated for stock 700MHz
# bcm2835gpio_speed SPEED_COEFF SPEED_OFFSET
#bcm2835gpio_speed_coeffs 146203 36
bcm2835gpio_speed_coeffs 194938 48

reset_config none
adapter_khz 100

# JTAG                tck tms tdi tdo
bcm2835gpio_jtag_nums 17 22   23  27

# Dummy reset to make openocd happy, GPIO5 is disconnected
bcm2835gpio_srst_num 5
reset_config srst_only srst_open_drain

transport select jtag
jtag newtap max10 tap -irlen 11 -expected-id 0x031820dd
init
svf a314-500.svf -quiet
sleep 200
shutdown