aboutsummaryrefslogtreecommitdiff
path: root/design/sram_slave.v
blob: 420626d9d7065e03e6f28dd85ff54df2bcf492a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * | *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