`ifdef VERILATOR `include "sdvd_defs.sv" `endif import sdvd_defs::SPEED; module read_data_tb; logic clk, sd_clk, reset; // Control signals logic play, stop; SPEED speed; // Whether the audio buffer is currently playing logic playing; // A 16-bit audio sample to output logic [15:0] sample; logic [3:0] sd_data; audio_buffer_interface bufferInterface(); logic [10:0] counter; logic [15:0] test_memory [1023:0]; audio_buffer audioDut(.driver(bufferInterface.receiver), .*); read_data readerDut(sd_clk,reset,sd_data,bufferInterface.driver); // The writer's clock should be much faster than the 48khz buffer clock initial sd_clk = 0; always #5 sd_clk = ~sd_clk; // An order of magnitude difference is fine initial clk = 0; always #500 clk = ~clk; // Reader initial begin `ifdef DEBUG $monitor("PLAYING: %b ADDR: 0x%x DATA: 0x%x WILLDELAY: %b", playing, dut.address, dut.doutb,dut.delay); `endif fork //Reader begin play = 0; stop = 0; clk = 0; reset = 0; speed = 1; @(posedge clk) reset = 1; @(posedge clk) reset = 0; play = 1; @(posedge clk) assert (playing == 1) else $error("Audio buffer not playing"); // Wait an extra clock cycle because of the blockmem delay @(posedge clk) // The most basic test we can do here is an incrementing counter, // where the stored sample is the same as the address $display("Running linear test"); for (counter = 0; counter < 1024; counter++) begin #1 assert ({5'b0, counter} === sample) else $error("Invalid sample, expected 0x%x but found 0x%x",counter,sample); @(posedge clk); end $display("Running randomized test"); counter = 0; while(counter < 1024) begin #1 assert (test_memory[counter[9:0]] === sample) else $error("Invalid sample, expected 0x%x but found 0x%x at location 0x%x",test_memory[counter[9:0]],sample,counter); @(posedge clk); counter++; end end // Writer begin for (int i=0; i<1024; i++) test_memory[i]=$urandom; // Wait til buffer is done resetting @(posedge clk); @(posedge clk); // linear test write_linear_sd(0); write_linear_sd(256); write_linear_sd(512); write_linear_sd(256*3); wait (bufferInterface.address_half==1); // random test, write to lower half of memory write_random_sd(0); write_random_sd(256); wait (bufferInterface.address_half==0); // random test, write to upper half of memory write_random_sd(512); write_random_sd(256*3); end join $finish; end task automatic write_random_sd(int start); @(posedge sd_clk); sd_data = '1; // send start bit @(posedge sd_clk); // send 256 data bits sd_data = 0; for (int i = 0; i < 256; i++) begin write_byte(test_memory[start-i-1][7:0]); write_byte(test_memory[start-i-1][15:8]); end // Simulate randomized crc bits and stop bit repeat (16*4) @(posedge sd_clk) sd_data=$urandom; @(posedge sd_clk) sd_data='1; endtask task automatic write_linear_sd(int start); @(posedge sd_clk); sd_data = '1; // send start bit @(posedge sd_clk); // send 256 data bits sd_data = 0; start += 256; for (int i = 0; i < 256; i++) begin // NOTE: These are in the wrong order?? // One of the weird cases where simulation is different // than hardware write_byte(start[7:0]); write_byte(start[15:8]); start = start-1; end // Simulate crc bits and stop bit repeat (16*4+1) @(posedge sd_clk) sd_data='1; endtask task automatic write_byte(logic [7:0] b); @(posedge sd_clk) sd_data=b[7:4]; @(posedge sd_clk) sd_data=b[3:0]; endtask endmodule