URL
https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk
Subversion Repositories or1k_soc_on_altera_embedded_dev_kit
[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [soc/] [rtl/] [altera_ddr_ctrl/] [testbench/] [altera_ddr_mem_model.v] - Rev 20
Go to most recent revision | Compare with Previous | Blame | View Log
//Legal Notice: (C)2009 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 / 1ps // synthesis translate_on // turn off superfluous verilog processor warnings // altera message_level Level1 // altera message_off 10034 10035 10036 10037 10230 10240 10030 //Default depth for this memory model is 2048, do these when //changing the depth. //1)Set ARRAY_DEPTH generic/parameter from 2048 to new depth. //2)Change mem_array depth from 2047 to (new depth - 1). //3)VHDL only, don't forget the generic in component declaration module altera_ddr_mem_model_ram_module ( // inputs: data, rdaddress, wraddress, wrclock, wren, // outputs: q ) ; parameter ARRAY_DEPTH = 2048; output [ 31: 0] q; input [ 31: 0] data; input [ 22: 0] rdaddress; input [ 22: 0] wraddress; input wrclock; input wren; wire [ 31: 0] aq; reg [ 55: 0] mem_array [2047: 0]; wire [ 31: 0] q; assign aq = mem_array[0][31:0]; //synthesis translate_off //////////////// SIMULATION-ONLY CONTENTS reg [ 32 - 1: 0] out; integer i; reg found_valid_data; reg data_written; initial begin for (i = 0; i < ARRAY_DEPTH; i = i + 1) mem_array[i][0] <= 1'b0; data_written <= 1'b0; end always @(rdaddress) begin found_valid_data <= 1'b0; for (i = 0; i < ARRAY_DEPTH; i = i + 1) begin if (rdaddress == mem_array[i][56 - 1:56 - 23] && mem_array[i][0]) begin out = mem_array[i][56 - 23 - 1:56 - 23 - 32]; found_valid_data = 1'b1; end end if (!found_valid_data) out = 32'dX; end always @(posedge wrclock) if (wren) begin data_written <= 1'b0; for (i = 0; i < ARRAY_DEPTH; i = i + 1) begin if (wraddress == mem_array[i][56 - 1:56 - 23] && !data_written) begin mem_array[i][56 - 23 - 1:56 - 23 - 32] <= data; mem_array[i][0] <= 1'b1; data_written = 1'b1; end else if (!mem_array[i][0] && !data_written) begin mem_array[i] <= {wraddress,data,1'b1}; data_written = 1'b1; end end if (!data_written) begin $write($time); $write(" --- Data could not be written, increase array depth or use full memory model --- "); $stop; end end assign q = out; //////////////// END SIMULATION-ONLY CONTENTS //synthesis translate_on endmodule // turn off superfluous verilog processor warnings // altera message_level Level1 // altera message_off 10034 10035 10036 10037 10230 10240 10030 module altera_ddr_mem_model ( // inputs: mem_addr, mem_ba, mem_cas_n, mem_cke, mem_clk, mem_clk_n, mem_cs_n, mem_dm, mem_ras_n, mem_we_n, // outputs: global_reset_n, mem_dq, mem_dqs ) ; output global_reset_n; inout [ 15: 0] mem_dq; inout [ 1: 0] mem_dqs; input [ 12: 0] mem_addr; input [ 1: 0] mem_ba; input mem_cas_n; input mem_cke; input mem_clk; input mem_clk_n; input mem_cs_n; input [ 1: 0] mem_dm; input mem_ras_n; input mem_we_n; wire [ 23: 0] CODE; wire [ 12: 0] a; wire [ 7: 0] addr_col; wire [ 1: 0] ba; wire burst_term; reg burst_term_cmd; reg [ 10: 0] burst_term_pipe; reg [ 2: 0] burstlength; reg burstmode; wire cas_n; wire cke; wire clk; wire [ 2: 0] cmd_code; wire cs_n; wire [ 1: 0] current_row; wire [ 1: 0] dm; reg [ 3: 0] dm_captured; reg [ 31: 0] dq_captured; wire [ 15: 0] dq_temp; wire dq_valid; wire [ 1: 0] dqs_temp; wire dqs_valid; reg dqs_valid_temp; reg [ 15: 0] first_half_dq; wire global_reset_n; reg [ 3: 0] index; wire [ 31: 0] mem_bytes; wire [ 15: 0] mem_dq; wire [ 1: 0] mem_dqs; reg [ 12: 0] open_rows [ 3: 0]; wire ras_n; reg [ 22: 0] rd_addr_pipe_0; reg [ 22: 0] rd_addr_pipe_1; reg [ 22: 0] rd_addr_pipe_10; reg [ 22: 0] rd_addr_pipe_2; reg [ 22: 0] rd_addr_pipe_3; reg [ 22: 0] rd_addr_pipe_4; reg [ 22: 0] rd_addr_pipe_5; reg [ 22: 0] rd_addr_pipe_6; reg [ 22: 0] rd_addr_pipe_7; reg [ 22: 0] rd_addr_pipe_8; reg [ 22: 0] rd_addr_pipe_9; reg [ 22: 0] rd_burst_counter; reg [ 10: 0] rd_valid_pipe; wire [ 22: 0] read_addr_delayed; reg read_cmd; reg read_cmd_echo; wire [ 31: 0] read_data; wire [ 15: 0] read_dq; wire read_valid; reg read_valid_r; reg read_valid_r2; reg read_valid_r3; reg read_valid_r4; reg reset_n; wire [ 22: 0] rmw_address; reg [ 31: 0] rmw_temp; reg [ 15: 0] second_half_dq; wire [ 23: 0] txt_code; wire we_n; wire [ 22: 0] wr_addr_delayed; reg [ 22: 0] wr_addr_delayed_r; reg [ 22: 0] wr_addr_pipe_0; reg [ 22: 0] wr_addr_pipe_1; reg [ 22: 0] wr_addr_pipe_10; reg [ 22: 0] wr_addr_pipe_2; reg [ 22: 0] wr_addr_pipe_3; reg [ 22: 0] wr_addr_pipe_4; reg [ 22: 0] wr_addr_pipe_5; reg [ 22: 0] wr_addr_pipe_6; reg [ 22: 0] wr_addr_pipe_7; reg [ 22: 0] wr_addr_pipe_8; reg [ 22: 0] wr_addr_pipe_9; reg [ 22: 0] wr_burst_counter; reg [ 10: 0] wr_valid_pipe; reg [ 10: 0] write_burst_length_pipe; reg write_cmd; reg write_cmd_echo; wire write_to_ram; reg write_to_ram_r; reg write_valid; reg write_valid_r; reg write_valid_r2; reg write_valid_r3; initial begin $write("\n"); $write("**********************************************************************\n"); $write("This testbench includes a generated Altera memory model:\n"); $write("'altera_ddr_mem_model.v', to simulate accesses to the DDR SDRAM memory.\n"); $write(" \n"); $write("**********************************************************************\n"); end //Synchronous write when (CODE == 24'h205752 (write)) altera_ddr_mem_model_ram_module altera_ddr_mem_model_ram ( .data (rmw_temp), .q (read_data), .rdaddress (rmw_address), .wraddress (wr_addr_delayed_r), .wrclock (clk), .wren (write_to_ram_r) ); assign clk = mem_clk; assign dm = mem_dm; assign cke = mem_cke; assign cs_n = mem_cs_n; assign ras_n = mem_ras_n; assign cas_n = mem_cas_n; assign we_n = mem_we_n; assign ba = mem_ba; assign a = mem_addr; //generate a fake reset inside the memory model assign global_reset_n = reset_n; initial begin reset_n <= 0; #100 reset_n <= 1; end assign cmd_code = (&cs_n) ? 3'b111 : {ras_n, cas_n, we_n}; assign CODE = (&cs_n) ? 24'h494e48 : txt_code; assign addr_col = a[8 : 1]; assign current_row = {ba}; // Decode commands into their actions always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin write_cmd_echo <= 0; read_cmd_echo <= 0; end else // No Activity if the clock is if (cke) begin // This is a read command if (cmd_code == 3'b101) read_cmd <= 1'b1; else read_cmd <= 1'b0; // This is a write command if (cmd_code == 3'b100) write_cmd <= 1'b1; else write_cmd <= 1'b0; // This is to terminate a burst if (cmd_code == 3'b110) burst_term_cmd <= 1'b1; else burst_term_cmd <= 1'b0; // This is an activate - store the chip/row/bank address in the same order as the DDR controller if (cmd_code == 3'b011) open_rows[current_row] <= a; end end // Pipes are flushed here always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin wr_addr_pipe_1 <= 0; wr_addr_pipe_2 <= 0; wr_addr_pipe_3 <= 0; wr_addr_pipe_4 <= 0; wr_addr_pipe_5 <= 0; wr_addr_pipe_6 <= 0; wr_addr_pipe_7 <= 0; wr_addr_pipe_8 <= 0; wr_addr_pipe_9 <= 0; wr_addr_pipe_10 <= 0; rd_addr_pipe_1 <= 0; rd_addr_pipe_2 <= 0; rd_addr_pipe_3 <= 0; rd_addr_pipe_4 <= 0; rd_addr_pipe_5 <= 0; rd_addr_pipe_6 <= 0; rd_addr_pipe_7 <= 0; rd_addr_pipe_8 <= 0; rd_addr_pipe_9 <= 0; rd_addr_pipe_10 <= 0; end else // No Activity if the clock is if (cke) begin rd_addr_pipe_10 <= rd_addr_pipe_9; rd_addr_pipe_9 <= rd_addr_pipe_8; rd_addr_pipe_8 <= rd_addr_pipe_7; rd_addr_pipe_7 <= rd_addr_pipe_6; rd_addr_pipe_6 <= rd_addr_pipe_5; rd_addr_pipe_5 <= rd_addr_pipe_4; rd_addr_pipe_4 <= rd_addr_pipe_3; rd_addr_pipe_3 <= rd_addr_pipe_2; rd_addr_pipe_2 <= rd_addr_pipe_1; rd_addr_pipe_1 <= rd_addr_pipe_0; rd_valid_pipe[10 : 1] <= rd_valid_pipe[9 : 0]; rd_valid_pipe[0] <= cmd_code == 3'b101; wr_addr_pipe_10 <= wr_addr_pipe_9; wr_addr_pipe_9 <= wr_addr_pipe_8; wr_addr_pipe_8 <= wr_addr_pipe_7; wr_addr_pipe_7 <= wr_addr_pipe_6; wr_addr_pipe_6 <= wr_addr_pipe_5; wr_addr_pipe_5 <= wr_addr_pipe_4; wr_addr_pipe_4 <= wr_addr_pipe_3; wr_addr_pipe_3 <= wr_addr_pipe_2; wr_addr_pipe_2 <= wr_addr_pipe_1; wr_addr_pipe_1 <= wr_addr_pipe_0; wr_valid_pipe[10 : 1] <= wr_valid_pipe[9 : 0]; wr_valid_pipe[0] <= cmd_code == 3'b100; wr_addr_delayed_r <= wr_addr_delayed; write_burst_length_pipe[10 : 1] <= write_burst_length_pipe[9 : 0]; end end // Decode CAS Latency from bits a[6:4] always @(posedge clk) begin // No Activity if the clock is if (cke) //Load mode register - set CAS latency, burst mode and length if (cmd_code == 3'b000 && ba == 2'b00) begin burstmode <= a[3]; burstlength <= a[2 : 0] << 1; //CAS Latency = 2.0 if (a[6 : 4] == 3'b010) index <= 4'b0001; else //CAS Latency = 2.5 if (a[6 : 4] == 3'b110) index <= 4'b0001; else //CAS Latency = 3.0 if (a[6 : 4] == 3'b011) index <= 4'b0010; else //CAS Latency = 4.0 if (a[6 : 4] == 3'b100) index <= 4'b0011; else index <= 4'b0100; end end // Burst support - make the wr_addr & rd_addr keep counting always @(posedge clk or negedge reset_n) begin if (reset_n == 0) begin wr_addr_pipe_0 <= 0; rd_addr_pipe_0 <= 0; end else begin // Reset write address otherwise if the first write is partial it breaks! if (cmd_code == 3'b000 && ba == 2'b00) begin wr_addr_pipe_0 <= 0; wr_burst_counter <= 0; end else if (cmd_code == 3'b100) begin wr_addr_pipe_0 <= {ba,open_rows[current_row],addr_col}; wr_burst_counter[22 : 1] <= {ba,open_rows[current_row],addr_col[7 : 1]}; wr_burst_counter[0] <= addr_col[0] + 1; end else if (write_cmd || write_to_ram || write_cmd_echo) begin wr_addr_pipe_0 <= wr_burst_counter; wr_burst_counter[0] <= wr_burst_counter[0] + 1; end else wr_addr_pipe_0 <= 0; // Reset read address otherwise if the first write is partial it breaks! if (cmd_code == 3'b000 && ba == 2'b00) rd_addr_pipe_0 <= 0; else if (cmd_code == 3'b101) begin rd_addr_pipe_0 <= {ba,open_rows[current_row],addr_col}; rd_burst_counter[22 : 1] <= {ba,open_rows[current_row],addr_col[7 : 1]}; rd_burst_counter[0] <= addr_col[0] + 1; end else if (read_cmd || dq_valid || read_valid || read_cmd_echo) begin rd_addr_pipe_0 <= rd_burst_counter; rd_burst_counter[0] <= rd_burst_counter[0] + 1; end else rd_addr_pipe_0 <= 0; end end // read data transition from single to double clock rate always @(posedge clk) begin first_half_dq <= read_data[31 : 16]; second_half_dq <= read_data[15 : 0]; end assign read_dq = clk ? second_half_dq : first_half_dq; assign dq_temp = dq_valid ? read_dq : {16{1'bz}}; assign dqs_temp = dqs_valid ? {2{clk}} : {2{1'bz}}; assign mem_dqs = dqs_temp; assign mem_dq = dq_temp; //Pipelining registers for burst counting always @(posedge clk) begin write_valid_r <= write_valid; read_valid_r <= read_valid; write_valid_r2 <= write_valid_r; write_valid_r3 <= write_valid_r2; write_to_ram_r <= write_to_ram; read_valid_r2 <= read_valid_r; read_valid_r3 <= read_valid_r2; read_valid_r4 <= read_valid_r3; end assign write_to_ram = write_valid || write_valid_r; assign dq_valid = read_valid_r || read_valid_r2 && burst_term; assign dqs_valid = dq_valid || dqs_valid_temp; // always @(negedge clk) begin dqs_valid_temp <= read_valid; end //capture first half of write data with rising edge of DQS, for simulation use only 1 DQS pin always @(posedge mem_dqs[0]) begin #0.1 dq_captured[15 : 0] <= mem_dq[15 : 0]; #0.1 dm_captured[1 : 0] <= mem_dm[1 : 0]; end //capture second half of write data with falling edge of DQS, for simulation use only 1 DQS pin always @(negedge mem_dqs[0]) begin #0.1 dq_captured[31 : 16] <= mem_dq[15 : 0]; #0.1 dm_captured[3 : 2] <= mem_dm[1 : 0]; end //Support for incomplete writes, do a read-modify-write with mem_bytes and the write data always @(posedge clk) begin if (write_to_ram) rmw_temp[7 : 0] <= dm_captured[0] ? mem_bytes[7 : 0] : dq_captured[7 : 0]; end always @(posedge clk) begin if (write_to_ram) rmw_temp[15 : 8] <= dm_captured[1] ? mem_bytes[15 : 8] : dq_captured[15 : 8]; end always @(posedge clk) begin if (write_to_ram) rmw_temp[23 : 16] <= dm_captured[2] ? mem_bytes[23 : 16] : dq_captured[23 : 16]; end always @(posedge clk) begin if (write_to_ram) rmw_temp[31 : 24] <= dm_captured[3] ? mem_bytes[31 : 24] : dq_captured[31 : 24]; end assign wr_addr_delayed = wr_addr_pipe_1; //Pipelining registers for burst counting always @(posedge clk) begin write_valid <= write_cmd; end //Registering burst term command always @(posedge clk) begin burst_term_pipe[0] <= ~burst_term_cmd; burst_term_pipe[10 : 1] <= burst_term_pipe[9 : 0]; end //burst terminate piped along cas latency assign burst_term = (index == 0)? burst_term_pipe[0] : (index == 1)? burst_term_pipe[1] : (index == 2)? burst_term_pipe[2] : (index == 3)? burst_term_pipe[3] : (index == 4)? burst_term_pipe[4] : (index == 5)? burst_term_pipe[5] : (index == 6)? burst_term_pipe[6] : (index == 7)? burst_term_pipe[7] : (index == 8)? burst_term_pipe[8] : (index == 9)? burst_term_pipe[9] : burst_term_pipe[10]; assign mem_bytes = read_data; assign rmw_address = (write_to_ram) ? wr_addr_delayed : read_addr_delayed; //use index to select which pipeline stage drives addr assign read_addr_delayed = (index == 0)? rd_addr_pipe_0 : (index == 1)? rd_addr_pipe_1 : (index == 2)? rd_addr_pipe_2 : (index == 3)? rd_addr_pipe_3 : (index == 4)? rd_addr_pipe_4 : (index == 5)? rd_addr_pipe_5 : (index == 6)? rd_addr_pipe_6 : (index == 7)? rd_addr_pipe_7 : (index == 8)? rd_addr_pipe_8 : (index == 9)? rd_addr_pipe_9 : rd_addr_pipe_10; //use index to select which pipeline stage drives valid assign read_valid = (index == 0)? rd_valid_pipe[0] : (index == 1)? rd_valid_pipe[1] : (index == 2)? rd_valid_pipe[2] : (index == 3)? rd_valid_pipe[3] : (index == 4)? rd_valid_pipe[4] : (index == 5)? rd_valid_pipe[5] : (index == 6)? rd_valid_pipe[6] : (index == 7)? rd_valid_pipe[7] : (index == 8)? rd_valid_pipe[8] : (index == 9)? rd_valid_pipe[9] : rd_valid_pipe[10]; //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; //////////////// END SIMULATION-ONLY CONTENTS //synthesis translate_on endmodule
Go to most recent revision | Compare with Previous | Blame | View Log