initial
[fpgammix.git] / rtl / memory_interface.v
blobfa987673f1635cde15523022afb7004691550635
1 /*
2 * TODO: optimize for multiple writes in sequence
3 */
5 module memory_interface
6 (clkin,
7 fse_a, fse_d,
8 flash_cs_n, enet_aen,
9 sram_cs_n, sram_be_n, sram_oe_n, sram_we_n,
11 transfer_request,
12 address,
13 wren,
14 wrdata,
15 wrmask,
16 wait_request,
17 read_data_valid,
18 read_data);
20 parameter debug = 0;
22 input wire clkin;
24 // Flash-SRAM-Ethernet bus
25 output reg [22:0] fse_a; // Mainboard common bus address
26 inout wire [31:0] fse_d; // Mainboard common bus data
27 output wire flash_cs_n; // Flash ROM CS#
28 output wire enet_aen; // Ethernet Access Enable
29 output wire sram_cs_n; // SRAM CS#
30 output reg [3:0] sram_be_n; // SRAM byte enables
31 output wire sram_oe_n; // SRAM OE#
32 output wire sram_we_n; // SRAM WE#
34 // Interface
35 input wire transfer_request;
36 input wire [31:0] address;
37 input wire wren;
38 input wire [31:0] wrdata;
39 input wire [ 3:0] wrmask;
41 output wire wait_request;
42 output wire read_data_valid;
43 // output reg [31:0] read_data;
44 output wire [31:0] read_data; // XXX a bit reckless!
46 parameter N = 4; // 0 1 2 3 4 5
47 parameter MAX_CYCLES = (1 << (N - 1)) - 1; // X 0 1 3 7 15
50 * @ 200MHz/5ns the address must be asserted for two cycles but
51 * apparently that isn't enough...
53 parameter READ_CYCLES = 0; // 25MHz
54 parameter LATENCY = 1; // data is ready LATENCY cycles from accepted request
56 /* How many cycles to assert the data and address
57 * *while* writing, that is, not counting setup and teardown
59 parameter WRITE_CYCLES = 1; // 25MHz
61 parameter IDLE = 0;
62 parameter READ = 1;
63 parameter WRITE_PREPARE = 2;
64 parameter WRITE_DO = 3;
65 parameter DELAY_WRITE = 4;
67 // Encode {cs_n,oe_n,we_n} as a command
68 parameter SRAM_CMD_READ = 3'b001; // 'h1
69 parameter SRAM_CMD_WRITE = 3'b010; // 'h2
70 parameter SRAM_CMD_PRE_WRITE= 3'b011; // 'h3
71 parameter SRAM_CMD_NOP = 3'b111; // 'h7
73 reg [31:0] state = IDLE;
74 reg [31:0] fse_d_out;
75 reg [ N:0] countdown;
76 reg [ 2:0] sram_cmd;
77 reg [LATENCY:0] read_data_pipeline;
78 /* XXX really should be LATENCY-1 but then the read_data_pipeline assignment
79 * below fails for LATENCY == 1 It doesn't really affect anything
82 assign flash_cs_n = 1'b1; // Disable flash ROM
83 assign enet_aen = 1'b1; // Disable Ethernet
84 assign {sram_cs_n,sram_oe_n,sram_we_n} = sram_cmd;
85 assign fse_d = sram_oe_n ? fse_d_out : 32'hZZZZZZZZ;
87 assign wait_request = state != IDLE;
88 assign read_data_valid = read_data_pipeline[LATENCY-1];
89 assign read_data = fse_d;
91 integer i;
92 always @(posedge clkin) begin
93 //read_data <= fse_d;
94 //if(debug)$display("%06d MI: fse_d %x", $time, fse_d);
95 countdown <= countdown - 1;
96 read_data_pipeline <= {read_data_pipeline[LATENCY-1:0], 1'b0};
98 if (read_data_valid)
99 if(debug)$display("%06d MI: read data %x", $time, read_data);
101 case (state)
102 IDLE: begin
103 sram_cmd <= SRAM_CMD_READ;
105 if (transfer_request)
106 if (~wren) begin
107 if(debug)$display("%06d MI: got a read command for address %x", $time, address);
108 fse_a <= address; // XXX Notice, only 20-bit are valid for SRAM (18 if aligned)
109 sram_be_n <= 0;
110 if (READ_CYCLES) begin
111 countdown <= READ_CYCLES - 2; // These underflow downcounters always use T - 2
112 state <= READ;
113 end else begin
114 // I _can_ run @100+ MHz with a ~ 25 ns latency (strange)
115 read_data_pipeline[0] <= 1;
117 end else begin
118 if(debug)$display("%06d MI: got a write command for address %x <- %x mask %x", $time, address, wrdata, wrmask);
119 fse_a <= address; // Notice, only 18-bit are valid for SRAM
120 fse_d_out <= wrdata;
121 sram_be_n <= ~wrmask;
122 if (|read_data_pipeline) begin
123 /* If there is an outstanding read command we have to wait
124 for it to finish */
125 state <= DELAY_WRITE;
126 end else begin
127 sram_cmd <= SRAM_CMD_PRE_WRITE;
128 state <= WRITE_PREPARE;
131 end // case: IDLE
133 READ: if (countdown[N]) begin
134 read_data_pipeline[0] <= 1;
135 state <= IDLE;
138 DELAY_WRITE: if (~|read_data_pipeline) begin
139 sram_cmd <= SRAM_CMD_PRE_WRITE;
140 state <= WRITE_PREPARE;
143 WRITE_PREPARE: begin
144 sram_cmd <= SRAM_CMD_WRITE;
145 countdown <= WRITE_CYCLES - 2;// These underflow downcounters always use T - 2
146 state <= WRITE_DO;
149 WRITE_DO: if (countdown[N]) begin
150 if(debug)$display("%06d MI: done writing", $time);
151 sram_cmd <= SRAM_CMD_PRE_WRITE;
152 state <= IDLE;
154 endcase
156 endmodule