Added modules to read sdcard data and cmd response
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful

These were realy headaches but the testbenches are passing. We need to
take a look at the audio_buffer testbench for sure, it is way wrong and
needs reworked to use the interface. Should do a pass through every
module probably.
This commit is contained in:
Waylon Cude 2025-06-07 21:57:17 -07:00
parent e32563131f
commit 71eecd18e8
8 changed files with 662 additions and 4 deletions

View File

@ -45,7 +45,7 @@
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
<Option Name="BoardPart" Val=""/>
<Option Name="SourceMgmtMode" Val="DisplayOnly"/>
<Option Name="ActiveSimSet" Val="send_command_tb"/>
<Option Name="ActiveSimSet" Val="read_data_tb"/>
<Option Name="DefaultLib" Val="xil_defaultlib"/>
<Option Name="ProjectType" Val="Default"/>
<Option Name="IPRepoPath" Val="$PPRDIR/../../../fpga/vivado-library"/>
@ -61,7 +61,7 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="nexys-a7-100t"/>
<Option Name="WTXSimLaunchSim" Val="145"/>
<Option Name="WTXSimLaunchSim" Val="201"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
@ -216,6 +216,20 @@
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/design/sd/read_command.sv">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/design/sd/read_data.sv">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="nexys_a7_top"/>
@ -509,6 +523,70 @@
<Option Name="xsim.simulate.runtime" Val="1s"/>
</Config>
</FileSet>
<FileSet Name="read_command_tb" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/read_command_tb" RelGenDir="$PGENDIR/read_command_tb">
<File Path="$PPRDIR/verification/sd/read_command_tb.sv">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/verification/waveform_configs/read_command_tb_behav.wcfg">
<FileInfo>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="read_command_tb"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
<Option Name="PamDesignTestbench" Val=""/>
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
<Option Name="SrcSet" Val="sources_1"/>
<Option Name="XSimWcfgFile" Val="$PPRDIR/verification/waveform_configs/read_command_tb_behav.wcfg"/>
<Option Name="CosimPdi" Val=""/>
<Option Name="CosimPlatform" Val=""/>
<Option Name="CosimElf" Val=""/>
<Option Name="xsim.simulate.runtime" Val="1s"/>
</Config>
</FileSet>
<FileSet Name="read_data_tb" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/read_data_tb" RelGenDir="$PGENDIR/read_data_tb">
<File Path="$PPRDIR/verification/sd/read_data_tb.sv">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/verification/waveform_configs/read_data_tb_behav.wcfg">
<FileInfo>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="read_data_tb"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
<Option Name="PamDesignTestbench" Val=""/>
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
<Option Name="SrcSet" Val="sources_1"/>
<Option Name="XSimWcfgFile" Val="$PPRDIR/verification/waveform_configs/read_data_tb_behav.wcfg"/>
<Option Name="CosimPdi" Val=""/>
<Option Name="CosimPlatform" Val=""/>
<Option Name="CosimElf" Val=""/>
<Option Name="xsim.simulate.runtime" Val="1s"/>
</Config>
</FileSet>
</FileSets>
<Simulators>
<Simulator Name="XSim">
@ -534,7 +612,9 @@
<Runs Version="1" Minor="22">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a100tcsg324-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="true" IncrementalCheckpoint="$PSRCDIR/utils_1/imports/synth_1/nexys_a7_top.dcp" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1" ParallelReportGen="true">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2024"/>
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2024">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
@ -544,7 +624,9 @@
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a100tcsg324-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 2 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024"/>
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>

119
design/sd/read_command.sv Normal file
View File

@ -0,0 +1,119 @@
module read_command(
input logic clk,
input logic reset,
input logic listen,
// 8 types of responses??? so hard to tell
input logic[2:0] response_type,
input logic sd_cmd,
output logic received,
// This has to be large enough to capture each possible response
output logic [135:0] out_data
);
enum logic [2:0] {IDLE,START,LISTEN,RECEIVING,DONE} state, next_state;
// This should be large enough to capture the largest 136-bit response
logic [$clog2(136):0] counter;
logic [135:0] data_reg;
logic [2:0] response_type_reg;
always_comb begin
case (state)
IDLE:
if (listen)
next_state=START;
else
next_state=IDLE;
START:
if (sd_cmd == 0)
next_state=RECEIVING;
else
next_state=LISTEN;
LISTEN:
// check for the start bit
if (sd_cmd == 0)
next_state=RECEIVING;
else
next_state=LISTEN;
RECEIVING:
if (counter == 0)
next_state=DONE;
else
next_state=RECEIVING;
DONE:
if (listen)
next_state=START;
else
next_state=DONE;
default:
next_state=IDLE;
endcase
end
always_ff @(posedge clk) begin
case (state)
IDLE:
begin
received <= 0;
out_data <= 0;
if (listen)
response_type_reg <= response_type;
end
START:
begin
// off-by-one/cycle timing issues accumulated to a counter offset
// of 3.
counter <= get_bits(response_type_reg) - 3;
data_reg <= 0;
received <= 0;
end
LISTEN:
// This is kinda a hack
// I don't fully understand why the receiving state misses two
// whole bits, I get why it misses the first but not the second...
data_reg[0] <= sd_cmd;
RECEIVING:
begin
counter <= counter - 1;
data_reg <= {data_reg[134:0],sd_cmd};
end
DONE:
begin
received <= 1;
out_data <= data_reg;
if (listen)
response_type_reg <= response_type;
end
default: ;
endcase
end
always_ff @(posedge clk) begin
if (reset)
state<=IDLE;
else
state<=next_state;
end
function automatic logic [$clog2(136):0] get_bits(logic [2:0] response);
case (response)
// Response 2 is extra long
2:
return 136;
// Most responses are 48 bits
default:
return 48;
endcase
endfunction
endmodule

64
design/sd/read_data.sv Normal file
View File

@ -0,0 +1,64 @@
// Whenever we receive a data block, start spitting bytes out into the audio
// buffer bram. This could always be clocked at the 25MHz default speed clock,
// or it could switch over like the writer has to
module read_data(
input clk,
input reset,
input sd_data,
audio_buffer_interface.driver buffer
);
// Block data is a start bit, 512 bytes sent msb first, then a CRC16 and end
// bit.
// NOTE: This doesn't check which side of the buffer the audio player is
// reading from, so theoretically it could overwrite audio that's being
// played. However, as long as the sd card controller doesn't request extra
// blocks this shouldn't be an issue
localparam BLOCK_SIZE=512*8+16+2;
logic [$clog2(BLOCK_SIZE):0] counter;
logic [7:0] byte_shift;
logic [3:0] byte_counter;
assign buffer.clka = clk;
always_ff @(posedge clk) begin
if (reset) begin
buffer.ena <= 0;
buffer.addra <= '1;
buffer.dina <= 0;
end
else begin
// We ignore the lower 17 bits of the block
if (counter > 16) begin
counter <= counter - 1;
byte_shift <= {byte_shift[6:0],sd_data};
byte_counter <= byte_counter - 1;
// Store received byte in audio buffer and reset counter
if (byte_counter == 0) begin
byte_counter <= 7;
buffer.dina <= byte_shift;//{byte_shift[6:0],sd_data};
buffer.ena <= 1;
end
// Turn the enable signal off so we don't accidentally write
// anything weird
if (byte_counter == 4) begin
buffer.ena <= 0;
buffer.addra <= buffer.addra + 1;
end
end
else if (counter != 0)
counter<=counter-1;
else if (sd_data == 0) begin
counter <= BLOCK_SIZE-1;
byte_counter <= 8;
end
end
end
endmodule

View File

@ -30,3 +30,12 @@
### command_sender
- output ready signal was delay a cycle because it was set by sequential logic,
detected in testing, changed it to a combinational output for 1 cycle speedup
### read_command
- response_type was not getting correctly stored/set, breaking the module
entirely. Detected in testbench
- off-by-one error detected in the counter
## read_data
- audio buffer address to write to was never changing, caught in simulation
- some off-by-one errors in the byte shifting were found and corrected

View File

@ -0,0 +1,81 @@
module read_command_tb;
bit clk;
logic reset;
logic listen;
logic [2:0] response_type;
logic sd_cmd;
wire received;
wire [135:0] out_data;
read_command dut (.*);
initial forever #10 clk = ~clk;
initial begin
$display("Testing read_command module");
sd_cmd = 1;
response_type = 0;
reset = 1;
listen = 0;
repeat (2) @(posedge clk);
reset = 0;
listen = 1;
response_type = 2;
@(posedge clk);
listen = 0;
response_type = 0;
repeat (5) @(posedge clk);
send_byte('h01);
for (int i=0; i<15; i++)
send_byte('hAA);
send_byte('h01);
@(posedge clk);
// NOTE: the received signal takes an extra cycle to propogate because
// it is loaded into a register
@(posedge clk);
#1;
assert (received === 1)
else $error("received signal not high");
assert (out_data === 'h01AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA01)
else $error("out_dat incorrect, found 0x%x but expected 0x01AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA01",out_data);
repeat (7) @(posedge clk);
listen = 1;
response_type = 3;
@(posedge clk);
listen = 0;
response_type = 0;
send_byte('h00);
send_byte('hAB);
send_byte('hCD);
send_byte('hEF);
send_byte('h12);
send_byte('h01);
// Return sd_cmd to inactive state
@(posedge clk) sd_cmd = 1;
@(posedge clk);
#1;
assert (received === 1)
else $error("received signal not high");
assert (out_data === 136'h00ABCDEF1201)
else $error("out_dat incorrect, found %b but expected 0x00ABCDEF1201",out_data);
@(posedge clk);
$finish;
end
task automatic send_byte(logic [7:0] b);
for (int i = 8; i != 0; i--) begin
@(posedge clk) sd_cmd = b[i-1];
end
endtask
endmodule

View File

@ -0,0 +1,140 @@
`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 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][7:0]);
write_byte(test_memory[start+i][15:8]);
end
// Simulate randomized crc bits and stop bit
repeat (16) @(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;
for (int i = 0; i < 256; i++) begin
write_byte(start[7:0]);
write_byte(start[15:8]);
start = start+1;
end
// Simulate crc bits and stop bit
repeat (17) @(posedge sd_clk) sd_data=1;
endtask
task automatic write_byte(logic [7:0] b);
for (int i=0; i<8; i++)
@(posedge sd_clk) sd_data=b[7-i];
endtask
endmodule

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<wave_config>
<wave_state>
</wave_state>
<db_ref_list>
<db_ref path="read_command_tb_behav.wdb" id="1">
<top_modules>
<top_module name="glbl" />
<top_module name="read_command_tb" />
</top_modules>
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="0.000 ns"></ZoomStartTime>
<ZoomEndTime time="1,370.001 ns"></ZoomEndTime>
<Cursor1Time time="330.000 ns"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="533"></NameColumnWidth>
<ValueColumnWidth column_width="187"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="11" />
<wvobject type="logic" fp_name="/read_command_tb/clk">
<obj_property name="ElementShortName">clk</obj_property>
<obj_property name="ObjectShortName">clk</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_command_tb/reset">
<obj_property name="ElementShortName">reset</obj_property>
<obj_property name="ObjectShortName">reset</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_command_tb/listen">
<obj_property name="ElementShortName">listen</obj_property>
<obj_property name="ObjectShortName">listen</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_command_tb/sd_cmd">
<obj_property name="ElementShortName">sd_cmd</obj_property>
<obj_property name="ObjectShortName">sd_cmd</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_command_tb/received">
<obj_property name="ElementShortName">received</obj_property>
<obj_property name="ObjectShortName">received</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/out_data">
<obj_property name="ElementShortName">out_data[39:0]</obj_property>
<obj_property name="ObjectShortName">out_data[39:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/dut/state">
<obj_property name="ElementShortName">state[2:0]</obj_property>
<obj_property name="ObjectShortName">state[2:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/dut/counter">
<obj_property name="ElementShortName">counter[6:0]</obj_property>
<obj_property name="ObjectShortName">counter[6:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/dut/data_reg">
<obj_property name="ElementShortName">data_reg[39:0]</obj_property>
<obj_property name="ObjectShortName">data_reg[39:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/response_type">
<obj_property name="ElementShortName">response_type[2:0]</obj_property>
<obj_property name="ObjectShortName">response_type[2:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_command_tb/dut/response_type_reg">
<obj_property name="ElementShortName">response_type_reg[2:0]</obj_property>
<obj_property name="ObjectShortName">response_type_reg[2:0]</obj_property>
</wvobject>
</wave_config>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<wave_config>
<wave_state>
</wave_state>
<db_ref_list>
<db_ref path="read_data_tb_behav.wdb" id="1">
<top_modules>
<top_module name="glbl" />
<top_module name="read_data_tb" />
<top_module name="sdvd_defs" />
</top_modules>
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="1,438.800 ns"></ZoomStartTime>
<ZoomEndTime time="1,718.201 ns"></ZoomEndTime>
<Cursor1Time time="618.800 ns"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="533"></NameColumnWidth>
<ValueColumnWidth column_width="155"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="18" />
<wvobject type="logic" fp_name="/read_data_tb/clk">
<obj_property name="ElementShortName">clk</obj_property>
<obj_property name="ObjectShortName">clk</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/sd_clk">
<obj_property name="ElementShortName">sd_clk</obj_property>
<obj_property name="ObjectShortName">sd_clk</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/reset">
<obj_property name="ElementShortName">reset</obj_property>
<obj_property name="ObjectShortName">reset</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/play">
<obj_property name="ElementShortName">play</obj_property>
<obj_property name="ObjectShortName">play</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/stop">
<obj_property name="ElementShortName">stop</obj_property>
<obj_property name="ObjectShortName">stop</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/speed">
<obj_property name="ElementShortName">speed[3:0]</obj_property>
<obj_property name="ObjectShortName">speed[3:0]</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/playing">
<obj_property name="ElementShortName">playing</obj_property>
<obj_property name="ObjectShortName">playing</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/sample">
<obj_property name="ElementShortName">sample[15:0]</obj_property>
<obj_property name="ObjectShortName">sample[15:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/counter">
<obj_property name="ElementShortName">counter[10:0]</obj_property>
<obj_property name="ObjectShortName">counter[10:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/test_memory">
<obj_property name="ElementShortName">test_memory[1023:0][15:0]</obj_property>
<obj_property name="ObjectShortName">test_memory[1023:0][15:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/bufferInterface/driver/addra">
<obj_property name="ElementShortName">addra[10:0]</obj_property>
<obj_property name="ObjectShortName">addra[10:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/bufferInterface/driver/dina">
<obj_property name="ElementShortName">dina[7:0]</obj_property>
<obj_property name="ObjectShortName">dina[7:0]</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/bufferInterface/driver/ena">
<obj_property name="ElementShortName">ena</obj_property>
<obj_property name="ObjectShortName">ena</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/bufferInterface/driver/address_half">
<obj_property name="ElementShortName">address_half</obj_property>
<obj_property name="ObjectShortName">address_half</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/read_data_tb/sd_data">
<obj_property name="ElementShortName">sd_data</obj_property>
<obj_property name="ObjectShortName">sd_data</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/readerDut/byte_shift">
<obj_property name="ElementShortName">byte_shift[7:0]</obj_property>
<obj_property name="ObjectShortName">byte_shift[7:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/readerDut/byte_counter">
<obj_property name="ElementShortName">byte_counter[3:0]</obj_property>
<obj_property name="ObjectShortName">byte_counter[3:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/read_data_tb/readerDut/counter">
<obj_property name="ElementShortName">counter[13:0]</obj_property>
<obj_property name="ObjectShortName">counter[13:0]</obj_property>
</wvobject>
</wave_config>