|  | module RAM_TEST #( | 
|  | parameter ADDR_WIDTH = 6, | 
|  | parameter DATA_WIDTH = 1, | 
|  | parameter IS_DUAL_PORT = 1, | 
|  | parameter RANDOM_ITERATION_PER_LOOP = 10, | 
|  | parameter LFSR_WIDTH = 16, | 
|  | parameter LFSR_POLY = 16'hD008, | 
|  | // How much to increment the address to move 1 full data width. | 
|  | parameter ADDRESS_STEP = 1, | 
|  | // Max address for this memory | 
|  | parameter MAX_ADDRESS = 63 | 
|  | ) ( | 
|  | input rst, | 
|  | input clk, | 
|  | // Memory connection | 
|  | input [DATA_WIDTH-1:0] read_data, | 
|  | output reg [DATA_WIDTH-1:0] write_data, | 
|  | output reg write_enable, | 
|  | output reg [ADDR_WIDTH-1:0] read_address, | 
|  | output reg [ADDR_WIDTH-1:0] write_address, | 
|  | // INIT ROM | 
|  | // When the memory is first initialized, it is expected to match the ROM | 
|  | // port. | 
|  | input [DATA_WIDTH-1:0] rom_read_data, | 
|  | output reg [ADDR_WIDTH-1:0] rom_read_address, | 
|  | // When an iteration is complete, success will be 1 for 1 cycle | 
|  | output reg loop_complete, | 
|  | // If an error occurs during a test, error will be 1 for each cycle | 
|  | // with an error. | 
|  | output reg error, | 
|  | // error_state will contain the state of test FSM when the error occured. | 
|  | output reg [7:0] error_state, | 
|  | // error_address will be the read address where the error occurred. | 
|  | output reg [ADDR_WIDTH-1:0] error_address, | 
|  | // expected_data will be the read value expected. | 
|  | output reg [DATA_WIDTH-1:0] expected_data, | 
|  | // actual_data will be the read value read. | 
|  | output reg [DATA_WIDTH-1:0] actual_data | 
|  | ); | 
|  | reg [7:0] state; | 
|  | reg [DATA_WIDTH-1:0] test_value; | 
|  |  | 
|  | reg [$clog2(RANDOM_ITERATION_PER_LOOP)-1:0] rand_count; | 
|  |  | 
|  | localparam START = 8'd1, | 
|  | VERIFY_INIT = 8'd2, | 
|  | WRITE_ZEROS = 8'd3, | 
|  | VERIFY_ZEROS = 8'd4, | 
|  | WRITE_ONES = 8'd5, | 
|  | VERIFY_ONES = 8'd6, | 
|  | WRITE_10 = 8'd7, | 
|  | VERIFY_10 = 8'd8, | 
|  | WRITE_01 = 8'd9, | 
|  | VERIFY_01 = 8'd10, | 
|  | WRITE_RANDOM = 8'd11, | 
|  | VERIFY_RANDOM = 8'd12, | 
|  | RESTART_LOOP = 8'd13; | 
|  |  | 
|  | reg pause; | 
|  | reg lfsr_reset; | 
|  | reg wait_for_lfsr_reset; | 
|  | reg [LFSR_WIDTH-1:0] lfsr_seed; | 
|  | reg [LFSR_WIDTH-1:0] start_lfsr_seed; | 
|  | wire [LFSR_WIDTH-1:0] rand_data; | 
|  |  | 
|  | LFSR #( | 
|  | .WIDTH(LFSR_WIDTH), | 
|  | .POLY(LFSR_POLY) | 
|  | ) lfsr ( | 
|  | .rst(lfsr_reset), | 
|  | .clk(clk), | 
|  | .seed(lfsr_seed), | 
|  | .r(rand_data) | 
|  | ); | 
|  |  | 
|  | always @(posedge clk) begin | 
|  | if(rst) begin | 
|  | state <= START; | 
|  | error <= 0; | 
|  | write_enable <= 0; | 
|  | lfsr_reset <= 1; | 
|  | lfsr_seed <= 1; | 
|  | end else begin | 
|  | case(state) | 
|  | START: begin | 
|  | lfsr_reset <= 0; | 
|  | state <= VERIFY_INIT; | 
|  | read_address <= 0; | 
|  | rom_read_address <= 0; | 
|  | write_enable <= 0; | 
|  | error <= 0; | 
|  | end | 
|  | VERIFY_INIT: begin | 
|  | if(rom_read_data != read_data) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= rom_read_data; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  |  | 
|  | if(read_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | read_address <= read_address + ADDRESS_STEP; | 
|  | rom_read_address <= rom_read_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 1; | 
|  | write_data <= {DATA_WIDTH{1'b0}}; | 
|  | state <= WRITE_ZEROS; | 
|  | end | 
|  | end | 
|  | WRITE_ZEROS: begin | 
|  | loop_complete <= 0; | 
|  | if(write_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | write_address <= write_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 0; | 
|  | pause <= 1; | 
|  | state <= VERIFY_ZEROS; | 
|  | end | 
|  | end | 
|  | VERIFY_ZEROS: begin | 
|  | if(pause) begin | 
|  | pause <= 0; | 
|  | end else begin | 
|  | if(read_data != {DATA_WIDTH{1'b0}}) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= {DATA_WIDTH{1'b0}}; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  |  | 
|  | if(read_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | read_address <= read_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 1; | 
|  | write_data <= {DATA_WIDTH{1'b1}}; | 
|  | state <= WRITE_ONES; | 
|  | end | 
|  | end | 
|  | end | 
|  | WRITE_ONES: begin | 
|  | // If dual port, data should still be zero. | 
|  | if(IS_DUAL_PORT) begin | 
|  | if(read_data != {DATA_WIDTH{1'b0}}) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= {DATA_WIDTH{1'b0}}; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  | end else begin | 
|  | if(read_data != {DATA_WIDTH{1'b1}}) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= {DATA_WIDTH{1'b1}}; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  | end | 
|  |  | 
|  | if(write_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | read_address <= read_address + ADDRESS_STEP; | 
|  | write_address <= write_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 0; | 
|  | state <= VERIFY_ONES; | 
|  | pause <= 1; | 
|  | end | 
|  | end | 
|  | VERIFY_ONES: begin | 
|  | if(pause) begin | 
|  | pause <= 0; | 
|  | end else begin | 
|  | if(read_data != {DATA_WIDTH{1'b1}}) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= {DATA_WIDTH{1'b1}}; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  |  | 
|  | if(read_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | read_address <= read_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | state <= WRITE_RANDOM; | 
|  | write_enable <= 1; | 
|  | write_address <= 0; | 
|  | lfsr_seed <= rand_data; | 
|  | write_data <= rand_data[DATA_WIDTH-1:0]; | 
|  | read_address <= 0; | 
|  | end | 
|  | end | 
|  | end | 
|  | WRITE_RANDOM: begin | 
|  | if(write_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | write_address <= write_address + ADDRESS_STEP; | 
|  | write_data <= rand_data[DATA_WIDTH-1:0]; | 
|  | end else begin | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 0; | 
|  | state <= VERIFY_RANDOM; | 
|  |  | 
|  | // Return LFSR to state at beginning of WRITE_RANDOM. | 
|  | lfsr_reset <= 1; | 
|  | wait_for_lfsr_reset <= 1; | 
|  | end | 
|  | end | 
|  | VERIFY_RANDOM: begin | 
|  | if(wait_for_lfsr_reset) begin | 
|  | wait_for_lfsr_reset <= 0; | 
|  | lfsr_reset <= 1; | 
|  | end else begin | 
|  | lfsr_reset <= 0; | 
|  | if(read_data != rand_data[DATA_WIDTH-1:0]) begin | 
|  | error <= 1; | 
|  | error_state <= state; | 
|  | error_address <= read_address; | 
|  | expected_data <= rand_data[DATA_WIDTH-1:0]; | 
|  | actual_data <= read_data; | 
|  | end else begin | 
|  | error <= 0; | 
|  | end | 
|  |  | 
|  | if(read_address + ADDRESS_STEP <= MAX_ADDRESS) begin | 
|  | read_address <= read_address + ADDRESS_STEP; | 
|  | end else begin | 
|  | state <= RESTART_LOOP; | 
|  | end | 
|  | end | 
|  | end | 
|  | RESTART_LOOP: begin | 
|  | loop_complete <= 1; | 
|  | error <= 0; | 
|  | read_address <= 0; | 
|  | write_address <= 0; | 
|  | write_enable <= 1; | 
|  | write_data <= {DATA_WIDTH{1'b0}}; | 
|  | state <= WRITE_ZEROS; | 
|  | end | 
|  | default: begin | 
|  | state <= START; | 
|  | error <= 0; | 
|  | end | 
|  | endcase | 
|  |  | 
|  | end | 
|  | end | 
|  | endmodule |