// Designed and tested with icarus verilog module mst ( input clock, input reset, input enable, output reg [7:0] wra, output reg [7:0] wrd, output reg [7:0] rda, output reg [7:0] rdd, output reg we, output reg [8:0] t1attempts, output reg [8:0] t1fails, output reg [8:0] t2attempts, output reg [8:0] t2fails, output reg done ); wire [7:0] rddmem; memory u2 (.clock(clock), .reset(reset), .we(we), .wra(wra), .wrd(wrd), .rda(rda), .rdd(rddmem)); parameter NUM_BYTES = 256; parameter T1Write = 3'b001, T1Read = 3'b010, T1Verify = 3'b011, T2Write = 3'b100, T2Read = 3'b101, T2Verify = 3'b110, Done = 3'b111; // T1___ corresponds to test 1 (writing zeros), T2___ corresponds to test 2 (writing FF). reg [2:0] state = T1Write; // State machine outputs always@(negedge clock) begin rdd <= rddmem; // Update the memory read value every cycle case (state) T1Write: begin // Test 1 Write phase done <= 0; wrd <= 8'h00; // Test 1: write hex 00. we <= enable == 1 ? 1 : 0; // Moore machine, this state is also used as idle state wra <= t1attempts; // Address we care about can be indexed by test#. rda <= t1attempts; end T1Read: begin // Test 1 Read phase done <= 0; wrd <= 8'h00; we <= 0; // Begin read phase by setting write enable to 0. wra <= t1attempts; rda <= t1attempts; end T1Verify: begin // Test 1 Verify phase done <= 0; wrd <= 8'h00; we <= 0; wra <= t1attempts; rda <= t1attempts; if (enable && rddmem != 8'h00) t1fails <= t1fails + 1; // Fail the attempt if we read the wrong value. end T2Write: begin // Test 2 Write phase done <= 0; wrd <= 8'hFF; // Test 2: write hex FF. we <= 1; wra <= t2attempts; rda <= t2attempts; end T2Read: begin // Test 2 Read phase done <= 0; wrd <= 8'hFF; we <= 0; wra <= t2attempts; rda <= t2attempts; end T2Verify: begin // Test 2 Verify phase done <= 0; wrd <= 8'hFF; we <= 0; wra <= t2attempts; rda <= t2attempts; if (enable && rddmem != 8'hFF) t2fails <= t2fails + 1; // Fail the attempt if we read the wrong value. end default: begin // Done state done <= 1; end endcase end // State transitions always@(negedge clock) begin if (reset) begin // Handle synchronous reset signal state <= T1Write; // Idle state is handled by T1Write state. t1attempts <= 0; t2attempts <= 0; t1fails <= 0; t2fails <= 0; we <= 0; done <= 0; wrd <= 0; rda <= 0; wra <= 0; end else if (enable) case (state) // State transitions T1Write: begin state <= T1Read; end T1Read: begin state <= T1Verify; end T1Verify: begin t1attempts <= t1attempts + 1; if (t1attempts >= NUM_BYTES - 1) state <= T2Write; // Transition to test 2 if we are done with test 1. else state <= T1Write; end T2Write: begin state <= T2Read; end T2Read: begin state <= T2Verify; end T2Verify: begin t2attempts <= t2attempts + 1; if (t2attempts >= NUM_BYTES - 1) state <= Done; // Transition to done if we are done with test 2. else state <= T2Write; end default: begin state <= Done; end endcase end endmodule module memory( input clock, input reset, input we, input [7:0] wra, input [7:0] wrd, input [7:0] rda, output [7:0] rdd ); reg [7:0] mem[255:0]; reg [7:0] rddata; always @(posedge clock) begin if(reset) begin rddata <= 8'h00; end else begin if(we) begin mem[wra] <= wrd; end rddata <= mem[rda]; end end assign rdd = rddata; endmodule