aboutsummaryrefslogtreecommitdiff
/*
 * | *WISHBONE DATASHEET*                                                      |
 * |---------------------------------------------------------------------------|
 * | *Description*                   | *Specification*                         |
 * |---------------------------------+-----------------------------------------|
 * | General description             | 262144x16-bit memory core (512 KB)      |
 * |---------------------------------+-----------------------------------------|
 * | Supported cycles                | SLAVE, pipelined READ/WRITE             |
 * |---------------------------------+-----------------------------------------|
 * | Data port, size                 | 16-bit                                  |
 * | Data port, granularity          | 16-bit                                  |
 * | Data port, maximum operand size | 16-bit                                  |
 * | Data transfer ordering          | Big endian and/or little endian         |
 * | Data transfer ordering          | Undefined                               |
 * | Address port, size              | 18-bit                                  |
 * |---------------------------------+-----------------------------------------|
 * | Clock frequency constraints     | NONE (determined by memory primitive,   |
 * |                                 |     about 100 MHz if using K6R4016V1D)  |
 * |---------------------------------+-----------------------------------------|
 * |                                 | *Signal name*    | *WISHBONE Equiv.*    |
 * |                                 |------------------+----------------------|
 * |                                 | ACK_O            | ACK_O                |
 * |                                 | ADR_I            | ADR_I()              |
 * | Supported signal list and cross | CLK_I            | CLK_I                |
 * |     reference to equivalent     | DAT_I            | DAT_I()              |
 * |     WISHBONE signals            | DAT_O            | DAT_O()              |
 * |                                 | STB_I            | STB_I                |
 * |                                 | WE_I             | WE_I                 |
 * |                                 | RST_I            | RST_I                |
 * |                                 | STALL_O          | STALL_O              |
 * |---------------------------------+-----------------------------------------|
 * | Special requirements            | Circuit assumes the use of asynchronous |
 * |                                 |     RAM primitive, e.g. K6R4016V1D.     |
 */

`default_nettype none

module sram_slave
  (
   /* Interface to memory */
   output wire [17:0] sram_addr,
   inout wire [15:0]  sram_io,

   output wire 	      sram_cs_n,
   output wire 	      sram_oe_n,
   output wire 	      sram_we_n,

   /* Wishbone slave interface */
   output wire 	      ACK_O,
   input wire [17:0]  ADR_I,
   input wire 	      CLK_I,
   input wire [15:0]  DAT_I,
   output wire [15:0] DAT_O,
   input wire 	      RST_I,
   input wire 	      STB_I,
   input wire 	      WE_I,
   output wire 	      STALL_O
   );

   reg 		      writing;
   reg [15:0] 	      write_data;
   assign sram_io = sram_we_n ? 16'hZZZZ : write_data;

   reg 		      sram_cs_not;
   reg 		      sram_oe_not;
   reg 		      sram_we_not;
   assign sram_cs_n = sram_cs_not;
   assign sram_oe_n = sram_oe_not;
   assign sram_we_n = sram_we_not;

   reg [17:0] 	      address;
   assign sram_addr = address;

   reg 		      ack;
   assign ACK_O = ack;

   reg 		      stall;
   assign STALL_O = stall;

   reg [15:0] 	      output_data;
   assign DAT_O = output_data;

   reg [2:0] 	      state;

   always @ (posedge CLK_I) begin
      output_data <= sram_io;

      if (RST_I) begin
	 sram_cs_not <= 1;
	 sram_oe_not <= 1;
	 writing <= 0;

	 ack <= 0;
	 stall <= 0;

	 state <= 0;
      end else begin
	 if (state == 0 || state == 2) begin /* possibly starting new job */
	    if (STB_I) begin
	       address <= ADR_I;

	       sram_cs_not <= 0;
	       sram_oe_not <= WE_I;
	       writing <= WE_I;
	       write_data <= DAT_I;

	       state <= WE_I ? 1 : 2;
	       stall <= WE_I ? 1 : 0;
	    end else begin // if (STB_I)
	       sram_cs_not <= 1;
	       sram_oe_not <= 1;
	       writing <= 0;

	       state <= 0;
	    end
	 end // if (state == 0 || state == 2)

	 if (state == 1) begin /* performing write; it takes 2 CLK_I cycles */
	    state <= 2;
	    stall <= 0;
	 end

	 if (state == 2) begin /* finishing job */
	    ack <= 1;
	 end else begin
	    ack <= 0;
	 end
      end
   end // always @ (posedge CLK_I)

   /*
    * avoid bus congestion by only driving sram_io
    * during the middle part of write cycle
    */
   always @ (negedge CLK_I) begin
      if (writing)
	sram_we_not <= !sram_we_not;
      else
	sram_we_not <= 1;
   end
endmodule // sram_slave