`define state_wait 4'b0000 `define state_read 4'b0001 `define state_write 4'b0010 `define state_read_burst 4'b0011 `define state_write_burst 4'b0100 `define state_finish_read 4'b0101 `define state_write2 4'b0110 `define state_finish_burst_write 4'b0111 `define state_burst_write_wait 4'b1000 `define LO 1'b0 `define HI 1'b1 // Mueller Paul Memory-Interface with 64 Bit data width module mp_mem_interface_64( sys_rst_l, sys_clk, // Isytec SDRAM-Controller CONNECTIONS sdc_address, sdc_in_data, sdc_out_data, sdc_rnw, sdc_req, sdc_ack, sdc_out_data_valid, // Mueller-Paul Microprocessor Connections MAd, MDat_in, MDat_out, req, reqp, BRdy, wr, burst); // SYSTEM LEVEL CONNECTIONS input sys_clk; // global system clock. Runs the sdram state machine input sys_rst_l; // global active low asynchronous system reset // Isytec SDRAM-Controller CONNECTIONS output [21:0] sdc_address; output [63:0] sdc_in_data; input [63:0] sdc_out_data; output sdc_rnw; output sdc_req; input sdc_ack; input sdc_out_data_valid; // Mueller-Paul Microprocessor Connections input [31:0] MAd; input [63:0] MDat_in; output [63:0] MDat_out; input req; output reqp; output BRdy; input wr; input burst; // Processor-Side Connections of Isytec SDRAM-Interface reg [21:0] sdc_address; wire [63:0] sdc_in_data; reg [63:0] sdc_in_data_dly; // only test HHH reg sdc_rnw; reg sdc_req; // State register reg [3:0] next_state; // registered values reg BRdy; reg [63:0] MDat_out; reg reqp; // delayed registers reg [63:0] MDat_out_delay; reg [21:0] delayed_address; // registers for storing data during burst writes reg still_reading; reg [63:0] reg_burst_write1; reg [63:0] reg_burst_write2; reg [63:0] reg_burst_write3; reg burst3written; // burst_counter reg [1:0] burst_counter; // dieser counter zählt wieviele Addressen dem Isytec-Controller geschickt wurden reg [1:0] burst_counter2; // dieser counter zählt, wieviele Daten vom Isytec-Controller empfangen worden sind // State Machine assign sdc_in_data = sdc_in_data_dly; always @ (posedge sys_clk) begin if (sys_rst_l==0) begin // initial state // reset is actice next_state <= #100 `state_wait; BRdy <= #100 `LO; MDat_out <= #100 64'bx; reqp <= #100 `LO; still_reading <= #100 `LO; sdc_req <= #100 `LO; end // if (~sys_rst_l) else begin MDat_out <= #100 MDat_out_delay; // mp-protocol liefert daten erst einen Takt nach Ready-Signal case (next_state) `state_wait: begin burst_counter <= #100 2'b00; burst_counter2 <= #100 2'b00; BRdy <= #100 `LO; MDat_out_delay <= #100 64'bx; still_reading <= #100 `LO; sdc_req <= #100 `LO; if (req | reqp) begin reqp <= #100 `HI; if (burst) if (!wr) begin sdc_address <= #100 MAd; sdc_rnw <= #100 `HI; sdc_req <= #100 `HI; next_state <= #100 `state_read_burst; end else begin BRdy <= #100 `HI; delayed_address <= #100 MAd; still_reading <= #100 `HI; next_state <= #100 `state_burst_write_wait; end else if (!wr) begin // bei einem Read-Zugriff können die Daten schon hier gesetzt werden, da alles schon vorhanden ist sdc_address <= #100 MAd; sdc_rnw <= #100 `HI; sdc_req <= #100 `HI; next_state <= #100 `state_read; end else begin // bei einem Write-Zugriff liegen die Daten erst im nächsten Takt an, deshalb // wird hier noch kein Request generiert sondern erst im nächsten Takt next_state <= #100 `state_write; end end end // case: `state_wait `state_write: begin sdc_address <= #100 MAd; sdc_in_data_dly <= #100 MDat_in; sdc_rnw <= #100 `LO; sdc_req <= #100 `HI; if (sdc_ack) begin BRdy <= #100 `HI; reqp <= #100 `LO; next_state <= #100 `state_wait; end end // case: `state_write `state_burst_write_wait: begin burst3written <= #100 `LO; next_state <= #100 `state_write_burst; end `state_write_burst: begin if (still_reading) burst_counter <= #100 burst_counter + 1; // clocken der Daten in das passende Register case (burst_counter) 2'b00: begin sdc_in_data_dly <= #100 MDat_in; end 2'b01: begin reg_burst_write1 <= #100 MDat_in; reqp <= #100 `LO; end 2'b10: begin reg_burst_write2 <= #100 MDat_in; still_reading <= #100 `LO; BRdy <= #100 `LO; end 2'b11: begin if (!burst3written) reg_burst_write3 <= #100 MDat_in; burst3written <= #100 `HI; end endcase // case(burst_counter) // falls ein neuer Request von der CPU kommt, bevor das SD-RAM // fertig ist, wird er zwischengespeichert und das reqp auf hi gesetzt if (still_reading==`LO) begin if (req) reqp <= #100 `HI; end if (burst_counter==0) begin sdc_req <= #100 `HI; sdc_rnw <= #100 `LO; sdc_address <= #100 MAd; end else begin if (sdc_ack) begin burst_counter2 <= #100 burst_counter2 + 1; case (burst_counter2) 2'b00: begin sdc_in_data_dly <= #100 reg_burst_write1; end 2'b01: begin sdc_in_data_dly <= #100 reg_burst_write2; end 2'b10: begin sdc_in_data_dly <= #100 reg_burst_write3; end endcase if (burst_counter2==3) begin sdc_req <= #100 `LO; next_state <= #100 `state_wait; end else begin sdc_address <= #100 sdc_address + 1; end end end end // case: `state_write_burst `state_read: begin if (sdc_ack) begin sdc_req <= #100 `LO; next_state <= #100 `state_finish_read; end end // case: `state_read `state_finish_read: begin if (sdc_out_data_valid) begin BRdy <= #100 `HI; reqp <= #100 `LO; MDat_out_delay <= #100 sdc_out_data; next_state <= #100 `state_wait; end end // case: `state_finish_read `state_read_burst: begin // anlegen der gerade passenden Addresse an den Isytec-Controller if (burst_counter==2'b11) begin sdc_req <= #100 `LO; end else begin if (sdc_ack) begin sdc_address <= #100 sdc_address + 1; burst_counter <= #100 burst_counter + 1; end end // else: !if(burst_counter==2'b11) // Empfang der vom Isytec-Controller zurückgelieferten Daten if (sdc_out_data_valid) begin MDat_out_delay <= #100 sdc_out_data; BRdy <= #100 `HI; burst_counter2 <= #100 burst_counter2 + 1; if (burst_counter2==2'b11) // in burst_counter2 steht hier noch der alte Wert (nicht der um eins erhöhte)!!! begin // der burst-read ist abgeschlossen, weil gerade das 4.Datum gelesen wurde reqp <= #100 `LO; next_state <= #100 `state_wait; end end // if (sdc_out_data_valid) else begin BRdy <= #100 `LO; MDat_out_delay <= #100 64'bx; end // else: !if(sdc_out_data_valid) end endcase end end endmodule