168 lines
5.3 KiB
Verilog
168 lines
5.3 KiB
Verilog
// 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
|