//Legal Notice: (C)2005 Altera Corporation. All rights reserved. Your //use of Altera Corporation's design tools, logic functions and other //software and tools, and its AMPP partner logic functions, and any //output files 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 Altera Program //License Subscription Agreement or other applicable license agreement, //including, without limitation, that your use is for the sole purpose //of programming logic devices manufactured by Altera and sold by Altera //or its authorized distributors. Please refer to the applicable //agreement for further details. // synthesis translate_off `timescale 1ns / 100ps // synthesis translate_on module sdram_0_input_efifo_module ( // inputs: clk, rd, reset_n, wr, wr_data, // outputs: almost_empty, almost_full, empty, full, rd_data ); output almost_empty; output almost_full; output empty; output full; output [ 40: 0] rd_data; input clk; input rd; input reset_n; input wr; input [ 40: 0] wr_data; wire almost_empty; wire almost_full; wire empty; reg [ 1: 0] entries; reg [ 40: 0] entry_0; reg [ 40: 0] entry_1; wire full; reg rd_address; reg [ 40: 0] rd_data; wire [ 1: 0] rdwr; reg wr_address; assign rdwr = {rd, wr}; assign full = entries == 2; assign almost_full = entries >= 1; assign empty = entries == 0; assign almost_empty = entries <= 1; always @(entry_0 or entry_1 or rd_address) begin case (rd_address) // synthesis parallel_case full_case 1'd0: begin rd_data <= entry_0; end // 1'd0 1'd1: begin rd_data <= entry_1; end // 1'd1 default: begin end // default endcase // rd_address end always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin wr_address <= 0; rd_address <= 0; entries <= 0; end else case (rdwr) // synthesis parallel_case full_case 2'd1: begin // Write data if (!full) begin entries <= entries + 1; wr_address <= (wr_address == 1) ? 0 : (wr_address + 1); end end // 2'd1 2'd2: begin // Read data if (!empty) begin entries <= entries - 1; rd_address <= (rd_address == 1) ? 0 : (rd_address + 1); end end // 2'd2 2'd3: begin wr_address <= (wr_address == 1) ? 0 : (wr_address + 1); rd_address <= (rd_address == 1) ? 0 : (rd_address + 1); end // 2'd3 default: begin end // default endcase // rdwr end always @(posedge clk) begin //Write data if (wr & !full) case (wr_address) // synthesis parallel_case full_case 1'd0: begin entry_0 <= wr_data; end // 1'd0 1'd1: begin entry_1 <= wr_data; end // 1'd1 default: begin end // default endcase // wr_address end endmodule module sdram_0 ( // inputs: az_addr, az_be_n, az_cs, az_data, az_rd_n, az_wr_n, clk, reset_n, // outputs: za_data, za_valid, za_waitrequest, zs_addr, zs_ba, zs_cas_n, zs_cke, zs_cs_n, zs_dq, zs_dqm, zs_ras_n, zs_we_n ); output [ 15: 0] za_data; output za_valid; output za_waitrequest; output [ 11: 0] zs_addr; output [ 1: 0] zs_ba; output zs_cas_n; output zs_cke; output zs_cs_n; inout [ 15: 0] zs_dq; output [ 1: 0] zs_dqm; output zs_ras_n; output zs_we_n; input [ 21: 0] az_addr; input [ 1: 0] az_be_n; input az_cs; input [ 15: 0] az_data; input az_rd_n; input az_wr_n; input clk; input reset_n; wire [ 23: 0] CODE; reg ack_refresh_request; reg [ 21: 0] active_addr; wire [ 1: 0] active_bank; reg active_cs_n; reg [ 15: 0] active_data; reg [ 1: 0] active_dqm; reg active_rnw; wire almost_empty; wire almost_full; wire bank_match; wire [ 7: 0] cas_addr; wire clk_en; wire [ 3: 0] cmd_all; wire [ 2: 0] cmd_code; wire cs_n; wire csn_decode; wire csn_match; wire [ 21: 0] f_addr; wire [ 1: 0] f_bank; wire f_cs_n; wire [ 15: 0] f_data; wire [ 1: 0] f_dqm; wire f_empty; reg f_pop; wire f_rnw; wire f_select; wire [ 40: 0] fifo_read_data; reg [ 11: 0] i_addr; reg [ 3: 0] i_cmd; reg [ 2: 0] i_count; reg [ 2: 0] i_next; reg [ 2: 0] i_refs; reg [ 2: 0] i_state; reg init_done; reg [ 11: 0] m_addr /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */; reg [ 1: 0] m_bank /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */; reg [ 3: 0] m_cmd /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */; reg [ 2: 0] m_count; reg [ 15: 0] m_data /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON ; FAST_OUTPUT_ENABLE_REGISTER=ON" */; reg [ 1: 0] m_dqm /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */; reg [ 8: 0] m_next; reg [ 8: 0] m_state; reg oe /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_ENABLE_REGISTER=ON" */; wire pending; wire rd_strobe; reg [ 2: 0] rd_valid; reg [ 12: 0] refresh_counter; reg refresh_request; wire rnw_match; wire row_match; wire [ 23: 0] txt_code; reg za_cannotrefresh; reg [ 15: 0] za_data /* synthesis ALTERA_ATTRIBUTE = "FAST_INPUT_REGISTER=ON" */; reg za_valid; wire za_waitrequest; wire [ 11: 0] zs_addr; wire [ 1: 0] zs_ba; wire zs_cas_n; wire zs_cke; wire zs_cs_n; wire [ 15: 0] zs_dq; wire [ 1: 0] zs_dqm; wire zs_ras_n; wire zs_we_n; assign clk_en = 1; //s1, which is an e_avalon_slave assign {zs_cs_n, zs_ras_n, zs_cas_n, zs_we_n} = m_cmd; assign zs_addr = m_addr; assign zs_cke = clk_en; assign zs_dq = oe?m_data:{16{1'bz}}; assign zs_dqm = m_dqm; assign zs_ba = m_bank; assign f_select = f_pop & pending; assign f_cs_n = 1'b0; assign cs_n = f_select ? f_cs_n : active_cs_n; assign csn_decode = cs_n; assign {f_rnw, f_addr, f_dqm, f_data} = fifo_read_data; sdram_0_input_efifo_module the_sdram_0_input_efifo_module ( .almost_empty (almost_empty), .almost_full (almost_full), .clk (clk), .empty (f_empty), .full (za_waitrequest), .rd (f_select), .rd_data (fifo_read_data), .reset_n (reset_n), .wr ((~az_wr_n | ~az_rd_n) & !za_waitrequest), .wr_data ({az_wr_n, az_addr, az_wr_n ? 2'b0 : az_be_n, az_data}) ); assign f_bank = {f_addr[21],f_addr[8]}; // Refresh/init counter. always @(posedge clk or negedge reset_n) begin if (reset_n == 0) refresh_counter <= 5000; else if (refresh_counter == 0) refresh_counter <= 781; else refresh_counter <= refresh_counter - 1'b1; end // Refresh request signal. always @(posedge clk or negedge reset_n) begin if (reset_n == 0) refresh_request <= 0; else if (1) refresh_request <= ((refresh_counter == 0) | refresh_request) & ~ack_refresh_request & init_done; end // Generate an Interrupt if two ref_reqs occur before one ack_refresh_request always @(posedge clk or negedge reset_n) begin if (reset_n == 0) za_cannotrefresh <= 0; else if (1) za_cannotrefresh <= (refresh_counter == 0) & refresh_request; end // Initialization-done flag. always @(posedge clk or negedge reset_n) begin if (reset_n == 0) init_done <= 0; else if (1) init_done <= init_done | (i_state == 3'b101); end // **** Init FSM **** always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin i_state <= 3'b000; i_next <= 3'b000; i_cmd <= 4'b1111; i_addr <= {12{1'b1}}; i_count <= {3{1'b0}}; end else begin i_addr <= {12{1'b1}}; case (i_state) // synthesis parallel_case full_case 3'b000: begin i_cmd <= 4'b1111; i_refs <= 3'b0; //Wait for refresh count-down after reset if (refresh_counter == 0) i_state <= 3'b001; end // 3'b000 3'b001: begin i_state <= 3'b011; i_cmd <= {{1{1'b0}},3'h2}; i_count <= 0; i_next <= 3'b010; end // 3'b001 3'b010: begin i_cmd <= {{1{1'b0}},3'h1}; i_refs <= i_refs + 1'b1; i_state <= 3'b011; i_count <= 3; // Count up init_refresh_commands if (i_refs == 3'h1) i_next <= 3'b111; else i_next <= 3'b010; end // 3'b010 3'b011: begin i_cmd <= {{1{1'b0}},3'h7}; //WAIT til safe to Proceed... if (i_count > 1) i_count <= i_count - 1'b1; else i_state <= i_next; end // 3'b011 3'b101: begin i_state <= 3'b101; end // 3'b101 3'b111: begin i_state <= 3'b011; i_cmd <= {{1{1'b0}},3'h0}; i_addr <= {{2{1'b0}},1'b0,2'b00,3'h3,4'h0}; i_count <= 4; i_next <= 3'b101; end // 3'b111 default: begin i_state <= 3'b000; end // default endcase // i_state end end assign active_bank = {active_addr[21],active_addr[8]}; assign csn_match = active_cs_n == f_cs_n; assign rnw_match = active_rnw == f_rnw; assign bank_match = active_bank == f_bank; assign row_match = {active_addr[20 : 9]} == {f_addr[20 : 9]}; assign pending = csn_match && rnw_match && bank_match && row_match && !f_empty; assign cas_addr = f_select ? { {4{1'b0}},f_addr[7 : 0] } : { {4{1'b0}},active_addr[7 : 0] }; // **** Main FSM **** always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin m_state <= 9'b000000001; m_next <= 9'b000000001; m_cmd <= 4'b1111; m_bank <= 2'b00; m_addr <= 12'b000000000000; m_data <= 16'b0000000000000000; m_dqm <= 2'b00; m_count <= 3'b000; ack_refresh_request <= 1'b0; f_pop <= 1'b0; oe <= 1'b0; end else begin f_pop <= 1'b0; oe <= 1'b0; case (m_state) // synthesis parallel_case full_case 9'b000000001: begin //Wait for init-fsm to be done... if (init_done) begin //Hold bus if another cycle ended to arf. if (refresh_request) m_cmd <= {{1{1'b0}},3'h7}; else m_cmd <= 4'b1111; ack_refresh_request <= 1'b0; //Wait for a read/write request. if (refresh_request) begin m_state <= 9'b001000000; m_next <= 9'b010000000; m_count <= 0; active_cs_n <= 1'b1; end else if (!f_empty) begin f_pop <= 1'b1; active_cs_n <= f_cs_n; active_rnw <= f_rnw; active_addr <= f_addr; active_data <= f_data; active_dqm <= f_dqm; m_state <= 9'b000000010; end end else begin m_addr <= i_addr; m_state <= 9'b000000001; m_next <= 9'b000000001; m_cmd <= i_cmd; end end // 9'b000000001 9'b000000010: begin m_state <= 9'b000000100; m_cmd <= {csn_decode,3'h3}; m_bank <= active_bank; m_addr <= active_addr[20 : 9]; m_data <= active_data; m_dqm <= active_dqm; m_count <= 1; m_next <= active_rnw ? 9'b000001000 : 9'b000010000; end // 9'b000000010 9'b000000100: begin // precharge all if arf, else precharge csn_decode if (m_next == 9'b010000000) m_cmd <= {{1{1'b0}},3'h7}; else m_cmd <= {csn_decode,3'h7}; //Count down til safe to Proceed... if (m_count > 1) m_count <= m_count - 1'b1; else m_state <= m_next; end // 9'b000000100 9'b000001000: begin m_cmd <= {csn_decode,3'h5}; m_bank <= f_select ? f_bank : active_bank; m_dqm <= f_select ? f_dqm : active_dqm; m_addr <= cas_addr; //Do we have a transaction pending? if (pending) begin //if we need to ARF, bail, else spin if (refresh_request) begin m_state <= 9'b000000100; m_next <= 9'b000000001; m_count <= 2; end else begin f_pop <= 1'b1; active_cs_n <= f_cs_n; active_rnw <= f_rnw; active_addr <= f_addr; active_data <= f_data; active_dqm <= f_dqm; end end else begin //correctly end RD spin cycle if fifo mt if (~pending & f_pop) m_cmd <= {csn_decode,3'h7}; m_state <= 9'b100000000; end end // 9'b000001000 9'b000010000: begin m_cmd <= {csn_decode,3'h4}; oe <= 1'b1; m_data <= f_select ? f_data : active_data; m_dqm <= f_select ? f_dqm : active_dqm; m_bank <= f_select ? f_bank : active_bank; m_addr <= cas_addr; //Do we have a transaction pending? if (pending) begin //if we need to ARF, bail, else spin if (refresh_request) begin m_state <= 9'b000000100; m_next <= 9'b000000001; m_count <= 1; end else begin f_pop <= 1'b1; active_cs_n <= f_cs_n; active_rnw <= f_rnw; active_addr <= f_addr; active_data <= f_data; active_dqm <= f_dqm; end end else begin //correctly end WR spin cycle if fifo empty if (~pending & f_pop) begin m_cmd <= {csn_decode,3'h7}; oe <= 1'b0; end m_state <= 9'b100000000; end end // 9'b000010000 9'b000100000: begin m_cmd <= {csn_decode,3'h7}; //Count down til safe to Proceed... if (m_count > 1) m_count <= m_count - 1'b1; else begin m_state <= 9'b001000000; m_count <= 0; end end // 9'b000100000 9'b001000000: begin m_state <= 9'b000000100; m_addr <= {12{1'b1}}; // precharge all if arf, else precharge csn_decode if (refresh_request) m_cmd <= {{1{1'b0}},3'h2}; else m_cmd <= {csn_decode,3'h2}; end // 9'b001000000 9'b010000000: begin ack_refresh_request <= 1'b1; m_state <= 9'b000000100; m_cmd <= {{1{1'b0}},3'h1}; m_count <= 3; m_next <= 9'b000000001; end // 9'b010000000 9'b100000000: begin m_cmd <= {csn_decode,3'h7}; //if we need to ARF, bail, else spin if (refresh_request) begin m_state <= 9'b000000100; m_next <= 9'b000000001; m_count <= 1; end else //wait for fifo to have contents if (!f_empty) //Are we 'pending' yet? if (csn_match && rnw_match && bank_match && row_match) begin m_state <= f_rnw ? 9'b000001000 : 9'b000010000; f_pop <= 1'b1; active_cs_n <= f_cs_n; active_rnw <= f_rnw; active_addr <= f_addr; active_data <= f_data; active_dqm <= f_dqm; end else begin m_state <= 9'b000100000; m_next <= 9'b000000001; m_count <= 1; end end // 9'b100000000 // synthesis translate_off default: begin m_state <= m_state; m_cmd <= 4'b1111; f_pop <= 1'b0; oe <= 1'b0; end // default // synthesis translate_on endcase // m_state end end assign rd_strobe = m_cmd[2 : 0] == 3'h5; //Track RD Req's based on cas_latency w/shift reg always @(posedge clk or negedge reset_n) begin if (reset_n == 0) rd_valid <= {3{1'b0}}; else rd_valid <= (rd_valid << 1) | { {2{1'b0}}, rd_strobe }; end // Register dq data. always @(posedge clk or negedge reset_n) begin if (reset_n == 0) za_data <= 0; else if (1) za_data <= zs_dq; end // Delay za_valid to match registered data. always @(posedge clk or negedge reset_n) begin if (reset_n == 0) za_valid <= 0; else if (1) za_valid <= rd_valid[2]; end assign cmd_code = m_cmd[2 : 0]; assign cmd_all = m_cmd; //synthesis translate_off //////////////// SIMULATION-ONLY CONTENTS assign txt_code = (cmd_code == 3'h0)? 24'h4c4d52 : (cmd_code == 3'h1)? 24'h415246 : (cmd_code == 3'h2)? 24'h505245 : (cmd_code == 3'h3)? 24'h414354 : (cmd_code == 3'h4)? 24'h205752 : (cmd_code == 3'h5)? 24'h205244 : (cmd_code == 3'h6)? 24'h425354 : (cmd_code == 3'h7)? 24'h4e4f50 : 24'h424144; assign CODE = &(cmd_all|4'h7) ? 24'h494e48 : txt_code; //////////////// END SIMULATION-ONLY CONTENTS //synthesis translate_on endmodule