From fe43d581568f1e6dfee245de80281814ee523cb0 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Mon, 11 Mar 2019 00:08:56 +0300 Subject: [PATCH] Drastically simplyfied universal SPI master --- spi_master.sv | 309 ++++++++++++++----------------- spi_master_tb/compile.sh | 9 + spi_master_tb/compile.tcl | 1 + spi_master_tb/modelsim.ini | 324 --------------------------------- spi_master_tb/spi_master_tb.sv | 148 ++++++++------- spi_master_tb/wave.do | 32 ++-- 6 files changed, 236 insertions(+), 587 deletions(-) create mode 100644 spi_master_tb/compile.sh delete mode 100644 spi_master_tb/modelsim.ini diff --git a/spi_master.sv b/spi_master.sv index 63b695a..dee433c 100644 --- a/spi_master.sv +++ b/spi_master.sv @@ -6,34 +6,27 @@ // INFO ------------------------------------------------------------------------ // Universal spi master // -// * Supports all SPI bus modes +// * Supports following SPI bus modes // mode 0 (CPOL = 0, CPHA = 0) -// mode 1 (CPOL = 0, CPHA = 1) // mode 2 (CPOL = 1, CPHA = 0) -// mode 3 (CPOL = 1, CPHA = 1) -// * Moreover, universal spi master features separate parameters to set -// clock edge to update data by spi master and -// clock edge to latch data by spi master +// // * Spi clock can be made free-running (some slaves require that) // * OE pin for bidirectional buffer connection, in case DO and DI pins are combined // -// * Universal spi master successfully synthesize at clk speeds up to 200MHz -// * That means, that SPI clocks up to 50MHz are supported +// * Universal spi master successfully synthesize at clk speeds 200MHz and above +// * That means, that SPI clocks up to 100MHz are supported // /* --- INSTANTIATION TEMPLATE BEGIN --- spi_master #( - .WRITE_WIDTH( 8 ), + .CPOL( 0 ), + .FREE_RUNNING_SPI_CLK( 0 ), + .MOSI_DATA_WIDTH( 8 ), .WRITE_MSB_FIRST( 1 ), - .WRITE_DATA_EDGE( 1 ), - - .READ_WIDTH( 8 ), - .READ_MSB_FIRST( 1 ), - .READ_DATA_EDGE( 1 ), - - .FREE_RUNNING_SPI_CLK( 0 ) + .MISO_DATA_WIDTH( 8 ), + .READ_MSB_FIRST( 1 ) ) SM1 ( .clk( ), .nrst( ), @@ -47,9 +40,9 @@ spi_master #( .clk_pin( ), .ncs_pin( ), - .d_out_pin( ), - .d_oe( ), - .d_in_pin( ) + .mosi_pin( ), + .oe_pin( ), + .miso_pin( ) ); --- INSTANTIATION TEMPLATE END ---*/ @@ -57,56 +50,53 @@ spi_master #( module spi_master #( parameter - bit [4:0] WRITE_WIDTH = 8, // data word width in bits + bit CPOL = 0, // Clock polarity for SPI interface + // 0 - SPI mode 0 + // data updates on rising edge + // data reads on falling edge + // 1 - SPI mode 2 + // data updates on falling edge + // data reads on rising edge + bit FREE_RUNNING_SPI_CLK = 0, // 0 - clk_pin is active only when ncs_pin = 0 + // 1 - clk pin is always active + bit [5:0] MOSI_DATA_WIDTH = 8, // data word width in bits bit WRITE_MSB_FIRST = 1, // 0 - LSB first // 1 - MSB first - bit WRITE_DATA_EDGE = 0, // 0 - master updates on rising edge - // slave reads data on falling edge - // 1 - master updates on falling edge - // slave reads data on rising edge - - bit [4:0] READ_WIDTH = 8, // data word width in bits - bit READ_MSB_FIRST = 1, // 0 - LSB first + bit [5:0] MISO_DATA_WIDTH = 8, // data word width in bits + bit READ_MSB_FIRST = 1 // 0 - LSB first // 1 - MSB first - bit READ_DATA_EDGE = 1, // 0 - slave updates on rising edge - // master reads data on falling edge - // 1 - slave updates on falling edge - // master reads data on rising edge - - bit FREE_RUNNING_SPI_CLK = 0 // 0 - clk_pin is active only when ncs_pin = 0 - // 1 - clk pin is always active )( input clk, // system clock input nrst, // reset (inversed) input spi_clk, // prescaler clock - // spi_clk must be >= 4 clk cycles + // spi_clk must be >= 2 clk cycles // must be synchronous multiple of clk cycles input spi_wr_cmd, // spi write command, shifting begins on rising edge input spi_rd_cmd, // spi read command, shifting begins on rising edge output logic spi_busy, // shifting is active - input [WRITE_WIDTH-1:0] mosi_data, // data for shifting out from master - output logic [READ_WIDTH-1:0] miso_data = 0, // shifted in data from slave + input [MOSI_DATA_WIDTH-1:0] mosi_data, // data for shifting out from master + output logic [MISO_DATA_WIDTH-1:0] miso_data, // shifted in data from slave - output logic clk_pin = 0, // spi master's clock pin + output logic clk_pin, // spi master's clock pin output logic ncs_pin = 1, // spi master's chip select (inversed) - output logic d_out_pin = 0, // spi master's data in - output logic d_oe = 1, // spi master's output enable - // in case of slave has only one SDIO pin - input d_in_pin // spi master's data out + output logic mosi_pin = 0, // spi master's data in + output logic oe_pin = 0, // spi master's output enable + // in case of using bidirectional buffer for SDIO pin + input miso_pin // spi master's data in ); -// sequence_cntr[7:0]==0 - waiting for spi_wr_cmd or spi_wr_cmd -// WRITE_SEQ_START - switching mode or transaction end -// WRITE_SEQ_END - waiting for right edge to set first data -localparam WRITE_SEQ_START = 1; -localparam WRITE_SEQ_END = WRITE_SEQ_START+2*WRITE_WIDTH; +// first extra state for getting command and buffering +// second extra state to initialize outputs +localparam WRITE_SEQ_START = 2; +localparam WRITE_SEQ_END = WRITE_SEQ_START+2*MOSI_DATA_WIDTH; + +localparam READ_SEQ_START = WRITE_SEQ_END; +localparam READ_SEQ_END = READ_SEQ_START+2*MISO_DATA_WIDTH; -localparam READ_SEQ_START = WRITE_SEQ_END+1; -localparam READ_SEQ_END = READ_SEQ_START+2*READ_WIDTH; logic spi_clk_rise; logic spi_clk_fall; @@ -130,195 +120,141 @@ edge_detect ed_cmds [1:0] ( .both( ) ); -// input synchronizer for d_in_pin in clk domain, 2 cycles delay -// making similar delay for clk edges for read operation timing -logic d_in_pin_d2; -logic spi_clk_rise_d2; -logic spi_clk_fall_d2; -delay #( - .LENGTH( 2 ) -) d_in_pin_synch [2:0] ( - .clk( {3{clk}} ), - .nrst( {3{nrst}} ), - .ena( {3{1'b1}} ), - .in( {d_in_pin,spi_clk_rise,spi_clk_fall} ), - .out( {d_in_pin_d2,spi_clk_rise_d2,spi_clk_fall_d2} ) +// no need to synchronize miso pin because that is a slave`s responsibility +// to hold stable signal and avoid metastability + + +// shifting out is always LSB first +// optionally reversing miso data if requested +logic [MOSI_DATA_WIDTH-1:0] mosi_data_rev; +reverse_vector #( + .WIDTH( MOSI_DATA_WIDTH ) +) reverse_mosi_data ( + .in( mosi_data[MOSI_DATA_WIDTH-1:0] ), + .out( mosi_data_rev[MOSI_DATA_WIDTH-1:0] ) ); + +logic clk_pin_before_inversion; // inversion is optional, see CPOL parameter logic [7:0] sequence_cntr = 0; -logic rd_nwr = 0; // buffering data direction -logic [WRITE_WIDTH-1:0] mosi_data_buf = 0; // buffering mosi_data +logic rd_nwr = 0; // buffering data direction +logic [MOSI_DATA_WIDTH-1:0] mosi_data_buf = 0; // buffering mosi_data +logic [MISO_DATA_WIDTH-1:0] miso_data_buf = 0; // buffering miso_data always_ff @(posedge clk) begin if( ~nrst ) begin - miso_data[READ_WIDTH-1:0] <= 0; - - clk_pin <= ~WRITE_DATA_EDGE; + clk_pin_before_inversion <= CPOL; ncs_pin <= 1'b1; - d_out_pin <= 1'b0; - d_oe <= 1'b1; + mosi_pin <= 1'b0; + oe_pin <= 1'b0; + sequence_cntr[7:0] <= 0; rd_nwr <= 0; - mosi_data_buf[WRITE_WIDTH-1:0] <= 0; + mosi_data_buf[MOSI_DATA_WIDTH-1:0] <= 0; + miso_data_buf[MISO_DATA_WIDTH-1:0] <= 0; end else begin if( FREE_RUNNING_SPI_CLK ) begin if ( spi_clk_rise ) begin - clk_pin <= 1'b1; + clk_pin_before_inversion <= 1'b1; end if( spi_clk_fall ) begin - clk_pin <= 1'b0; + clk_pin_before_inversion <= 1'b0; end end else begin // FREE_RUNNING_SPI_CLK = 0 - if ( ~ncs_pin && - // fixing extra clock glitch in the end of read transaction - ~((sequence_cntr[7:0] == READ_SEQ_END) && - (WRITE_DATA_EDGE != READ_DATA_EDGE)) ) begin + if ( ~ncs_pin ) begin if ( spi_clk_rise ) begin - clk_pin <= 1'b1; + clk_pin_before_inversion <= 1'b1; end if( spi_clk_fall ) begin - clk_pin <= 1'b0; + clk_pin_before_inversion <= 1'b0; end end else begin // ncs_pin = 1 - clk_pin <= ~WRITE_DATA_EDGE; + clk_pin_before_inversion <= CPOL; end - end + end // if( FREE_RUNNING_SPI_CLK ) // WRITE ======================================================================= // sequence start condition + //*cmd_rise signals are NOT synchronous with spi_clk edges if( sequence_cntr[7:0]==0 && (spi_wr_cmd_rise || spi_rd_cmd_rise) ) begin - // outputs should NOT be updated here if( spi_rd_cmd_rise ) begin rd_nwr <= 1'b1; end else begin rd_nwr <= 1'b0; end - sequence_cntr[7:0] <= 1; // buffering mosi_data to avoid data change after shift_cmd issued - mosi_data_buf[WRITE_WIDTH-1:0] <= mosi_data[WRITE_WIDTH-1:0]; + if( WRITE_MSB_FIRST ) begin + mosi_data_buf[MOSI_DATA_WIDTH-1:0] <= mosi_data_rev[MOSI_DATA_WIDTH-1:0]; + end else begin + mosi_data_buf[MOSI_DATA_WIDTH-1:0] <= mosi_data[MOSI_DATA_WIDTH-1:0]; + end + sequence_cntr[7:0] <= sequence_cntr[7:0] + 1'b1; + end + + // second step of initialization, updating outputs synchronously with spi_clk edge + if( sequence_cntr[7:0]==1 && spi_clk_rise ) begin + ncs_pin <= 1'b0; + oe_pin <= 1'b1; + sequence_cntr[7:0] <= sequence_cntr[7:0] + 1'b1; end // clocking out data if( sequence_cntr[7:0]>=WRITE_SEQ_START && sequence_cntr[7:0]=READ_SEQ_START && sequence_cntr[7:0] 500 megabyte memory footprint). Default is disabled. -; Specify number of megabytes to lock. -; LockedMemory = 1000 - -; Turn on (1) or off (0) WLF file compression. -; The default is 1 (compress WLF file). -; WLFCompress = 0 - -; Specify whether to save all design hierarchy (1) in the WLF file -; or only regions containing logged signals (0). -; The default is 0 (save only regions with logged signals). -; WLFSaveAllRegions = 1 - -; WLF file time limit. Limit WLF file by time, as closely as possible, -; to the specified amount of simulation time. When the limit is exceeded -; the earliest times get truncated from the file. -; If both time and size limits are specified the most restrictive is used. -; UserTimeUnits are used if time units are not specified. -; The default is 0 (no limit). Example: WLFTimeLimit = {100 ms} -; WLFTimeLimit = 0 - -; WLF file size limit. Limit WLF file size, as closely as possible, -; to the specified number of megabytes. If both time and size limits -; are specified then the most restrictive is used. -; The default is 0 (no limit). -; WLFSizeLimit = 1000 - -; Specify whether or not a WLF file should be deleted when the -; simulation ends. A value of 1 will cause the WLF file to be deleted. -; The default is 0 (do not delete WLF file when simulation ends). -; WLFDeleteOnQuit = 1 - -; Automatic SDF compilation -; Disables automatic compilation of SDF files in flows that support it. -; Default is on, uncomment to turn off. -; NoAutoSDFCompile = 1 - -[lmc] - -[msg_system] -; Change a message severity or suppress a message. -; The format is: = [,...] -; Examples: -; note = 3009 -; warning = 3033 -; error = 3010,3016 -; fatal = 3016,3033 -; suppress = 3009,3016,3043 -; The command verror can be used to get the complete -; description of a message. - -; Control transcripting of elaboration/runtime messages. -; The default is to have messages appear in the transcript and -; recorded in the wlf file (messages that are recorded in the -; wlf file can be viewed in the MsgViewer). The other settings -; are to send messages only to the transcript or only to the -; wlf file. The valid values are -; both {default} -; tran {transcript only} -; wlf {wlf file only} -; msgmode = both diff --git a/spi_master_tb/spi_master_tb.sv b/spi_master_tb/spi_master_tb.sv index 153f701..c739d3c 100644 --- a/spi_master_tb/spi_master_tb.sv +++ b/spi_master_tb/spi_master_tb.sv @@ -10,6 +10,13 @@ module spi_master_tb(); +logic clk800; +initial begin + #0 clk800 = 1'b0; + forever + #0.625 clk800 = ~clk800; +end + logic clk200; initial begin #0 clk200 = 1'b0; @@ -88,39 +95,28 @@ end // Module under test ========================================================== -logic oe1_pin, din1_pin, clk1_pin, clk1_pin_rise, clk1_pin_fall; -logic oe2_pin, din2_pin, clk2_pin, clk2_pin_rise, clk2_pin_fall; -logic oe3_pin, din3_pin, clk3_pin, clk3_pin_rise, clk3_pin_fall; -logic oe4_pin, din4_pin, clk4_pin, clk4_pin_rise, clk4_pin_fall; - -edge_detect ed2[3:0] ( - .clk( {4{clk200}} ), - .nrst( {4{1'b1}} ), - .in( {clk1_pin, clk2_pin, clk3_pin, clk4_pin} ), - .rising( {clk1_pin_rise, clk2_pin_rise, clk3_pin_rise, clk4_pin_rise} ), - .falling( {clk1_pin_fall, clk2_pin_fall, clk3_pin_fall, clk4_pin_fall} ), - .both( ) -); +logic oe1_pin, ncs1_pin, din1_pin, clk1_pin, clk1_pin_rise, clk1_pin_fall; +logic oe2_pin, ncs2_pin, din2_pin, clk2_pin, clk2_pin_rise, clk2_pin_fall; +logic oe3_pin, ncs3_pin, din3_pin, clk3_pin, clk3_pin_rise, clk3_pin_fall; +logic oe4_pin, ncs4_pin, din4_pin, clk4_pin, clk4_pin_rise, clk4_pin_fall; reg [7:0] test1_data = 8'b1010_0011; reg [7:0] test2_data = 8'b1010_0011; reg [7:0] test3_data = 8'b1010_0011; reg [7:0] test4_data = 8'b1010_0011; + spi_master #( - .WRITE_WIDTH( 8 ), + .CPOL( 0 ), + .FREE_RUNNING_SPI_CLK( 0 ), + .MOSI_DATA_WIDTH( 8 ), .WRITE_MSB_FIRST( 1 ), - .WRITE_DATA_EDGE( 1 ), - - .READ_WIDTH( 8 ), - .READ_MSB_FIRST( 1 ), - .READ_DATA_EDGE( 1 ), - - .FREE_RUNNING_SPI_CLK( 0 ) + .MISO_DATA_WIDTH( 8 ), + .READ_MSB_FIRST( 1 ) ) SM1 ( .clk( clk200 ), .nrst( nrst_once ), - .spi_clk( DerivedClocks[1] ), + .spi_clk( DerivedClocks[0] ), .spi_wr_cmd( 0 ), .spi_rd_cmd( start ), .spi_busy( ), @@ -129,26 +125,23 @@ spi_master #( .miso_data( ), .clk_pin( clk1_pin ), - .ncs_pin( ), - .d_out_pin( ), - .d_oe( oe1_pin ), - .d_in_pin( din1_pin ) + .ncs_pin( ncs1_pin ), + .mosi_pin( ), + .oe_pin( oe1_pin ), + .miso_pin( din1_pin ) ); spi_master #( - .WRITE_WIDTH( 8 ), + .CPOL( 1 ), + .FREE_RUNNING_SPI_CLK( 0 ), + .MOSI_DATA_WIDTH( 8 ), .WRITE_MSB_FIRST( 1 ), - .WRITE_DATA_EDGE( 0 ), - - .READ_WIDTH( 8 ), - .READ_MSB_FIRST( 1 ), - .READ_DATA_EDGE( 0 ), - - .FREE_RUNNING_SPI_CLK( 0 ) + .MISO_DATA_WIDTH( 8 ), + .READ_MSB_FIRST( 1 ) ) SM2 ( .clk( clk200 ), .nrst( nrst_once ), - .spi_clk( DerivedClocks[1] ), + .spi_clk( DerivedClocks[0] ), .spi_wr_cmd( 0 ), .spi_rd_cmd( start ), .spi_busy( ), @@ -157,26 +150,23 @@ spi_master #( .miso_data( ), .clk_pin( clk2_pin ), - .ncs_pin( ), - .d_out_pin( ), - .d_oe( oe2_pin ), - .d_in_pin( din2_pin ) + .ncs_pin( ncs2_pin ), + .mosi_pin( ), + .oe_pin( oe2_pin ), + .miso_pin( din2_pin ) ); spi_master #( - .WRITE_WIDTH( 8 ), - .WRITE_MSB_FIRST( 1 ), - .WRITE_DATA_EDGE( 1 ), - - .READ_WIDTH( 8 ), - .READ_MSB_FIRST( 1 ), - .READ_DATA_EDGE( 0 ), - - .FREE_RUNNING_SPI_CLK( 0 ) + .CPOL( 0 ), + .FREE_RUNNING_SPI_CLK( 1 ), + .MOSI_DATA_WIDTH( 8 ), + .WRITE_MSB_FIRST( 0 ), + .MISO_DATA_WIDTH( 8 ), + .READ_MSB_FIRST( 0 ) ) SM3 ( .clk( clk200 ), .nrst( nrst_once ), - .spi_clk( DerivedClocks[1] ), + .spi_clk( DerivedClocks[0] ), .spi_wr_cmd( 0 ), .spi_rd_cmd( start ), .spi_busy( ), @@ -185,26 +175,23 @@ spi_master #( .miso_data( ), .clk_pin( clk3_pin ), - .ncs_pin( ), - .d_out_pin( ), - .d_oe( oe3_pin ), - .d_in_pin( din3_pin ) + .ncs_pin( ncs3_pin ), + .mosi_pin( ), + .oe_pin( oe3_pin ), + .miso_pin( din3_pin ) ); spi_master #( - .WRITE_WIDTH( 8 ), - .WRITE_MSB_FIRST( 1 ), - .WRITE_DATA_EDGE( 0 ), - - .READ_WIDTH( 8 ), - .READ_MSB_FIRST( 1 ), - .READ_DATA_EDGE( 1 ), - - .FREE_RUNNING_SPI_CLK( 0 ) + .CPOL( 0 ), + .FREE_RUNNING_SPI_CLK( 1 ), + .MOSI_DATA_WIDTH( 8 ), + .WRITE_MSB_FIRST( 0 ), + .MISO_DATA_WIDTH( 8 ), + .READ_MSB_FIRST( 0 ) ) SM4 ( .clk( clk200 ), .nrst( nrst_once ), - .spi_clk( DerivedClocks[1] ), + .spi_clk( DerivedClocks[0] ), .spi_wr_cmd( 0 ), .spi_rd_cmd( start ), .spi_busy( ), @@ -213,57 +200,68 @@ spi_master #( .miso_data( ), .clk_pin( clk4_pin ), - .ncs_pin( ), - .d_out_pin( ), - .d_oe( oe4_pin ), - .d_in_pin( din4_pin ) + .ncs_pin( ncs4_pin ), + .mosi_pin( ), + .oe_pin( oe4_pin ), + .miso_pin( din4_pin ) ); // emulating external divice ================================================== // that works asynchronously on clk33 clock -always_ff @(posedge clk200) begin +// clk800 emulates some high-speed "ideal" slave + +edge_detect ed2[3:0] ( + .clk( {4{clk800}} ), + .nrst( {4{1'b1}} ), + .in( {clk1_pin, clk2_pin, clk3_pin, clk4_pin} ), + .rising( {clk1_pin_rise, clk2_pin_rise, clk3_pin_rise, clk4_pin_rise} ), + .falling( {clk1_pin_fall, clk2_pin_fall, clk3_pin_fall, clk4_pin_fall} ), + .both( ) +); + +always_ff @(posedge clk800) begin if( ~nrst_once) begin din1_pin <= 0; test1_data[7:0] = 8'b1010_0011; end else begin - if( ~oe1_pin && clk1_pin_rise ) begin + if( ~ncs1_pin && ~oe1_pin && clk1_pin_fall ) begin din1_pin <=test1_data[7]; test1_data[7:0] <= {test1_data[6:0],1'b0}; end end end -always_ff @(posedge clk200) begin +always_ff @(posedge clk800) begin if( ~nrst_once) begin din2_pin <= 0; test2_data[7:0] = 8'b1010_0011; end else begin - if( ~oe2_pin && clk2_pin_fall ) begin + if( ~ncs2_pin && ~oe2_pin && clk2_pin_rise ) begin din2_pin <=test2_data[7]; test2_data[7:0] <= {test2_data[6:0],1'b0}; end end end -always_ff @(posedge clk200) begin +always_ff @(posedge clk800) begin if( ~nrst_once) begin din3_pin <= 0; test3_data[7:0] = 8'b1010_0011; end else begin - if( ~oe3_pin && clk3_pin_fall ) begin + if( ~ncs3_pin && ~oe3_pin && clk3_pin_fall ) begin din3_pin <=test3_data[7]; test3_data[7:0] <= {test3_data[6:0],1'b0}; end end end -always_ff @(posedge clk200) begin +always_ff @(posedge clk800) begin if( ~nrst_once) begin din4_pin <= 0; test4_data[7:0] = 8'b1010_0011; end else begin - if( ~oe4_pin && clk4_pin_fall ) begin + if( ~ncs4_pin && ~oe4_pin && clk4_pin_fall ) begin din4_pin <=test4_data[7]; test4_data[7:0] <= {test4_data[6:0],1'b0}; end diff --git a/spi_master_tb/wave.do b/spi_master_tb/wave.do index 6fd4b53..7120719 100644 --- a/spi_master_tb/wave.do +++ b/spi_master_tb/wave.do @@ -12,35 +12,35 @@ add wave -noupdate /spi_master_tb/SM1/spi_rd_cmd_rise add wave -noupdate /spi_master_tb/SM1/spi_busy add wave -noupdate -radix decimal /spi_master_tb/SM1/sequence_cntr add wave -noupdate /spi_master_tb/SM1/rd_nwr -add wave -noupdate -radix binary /spi_master_tb/SM1/data_out -add wave -noupdate -radix binary /spi_master_tb/SM1/data_in -add wave -noupdate /spi_master_tb/SM1/data_out_buf +add wave -noupdate -radix binary /spi_master_tb/SM1/mosi_data +add wave -noupdate -radix binary /spi_master_tb/SM1/miso_data +add wave -noupdate /spi_master_tb/SM1/mosi_data_buf add wave -noupdate -color Yellow /spi_master_tb/SM1/clk_pin add wave -noupdate -color Yellow /spi_master_tb/SM1/ncs_pin -add wave -noupdate -color Yellow /spi_master_tb/SM1/d_out_pin -add wave -noupdate -color Yellow /spi_master_tb/SM1/d_oe -add wave -noupdate -color Yellow /spi_master_tb/SM1/d_in_pin +add wave -noupdate -color Yellow /spi_master_tb/SM1/mosi_pin +add wave -noupdate -color Yellow /spi_master_tb/SM1/oe_pin +add wave -noupdate -color Yellow /spi_master_tb/SM1/miso_pin add wave -noupdate /spi_master_tb/SM1/spi_clk_rise_d2 add wave -noupdate /spi_master_tb/SM1/spi_clk_fall_d2 -add wave -noupdate /spi_master_tb/SM1/d_in_pin_d2 +add wave -noupdate /spi_master_tb/SM1/miso_pin_d2 add wave -noupdate -color {Medium Violet Red} -radix decimal /spi_master_tb/SM2/sequence_cntr add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/clk_pin add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/ncs_pin -add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/d_out_pin -add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/d_oe -add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/d_in_pin +add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/mosi_pin +add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/oe_pin +add wave -noupdate -color {Medium Violet Red} /spi_master_tb/SM2/miso_pin add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/sequence_cntr add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/clk_pin add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/ncs_pin -add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/d_out_pin -add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/d_oe -add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/d_in_pin +add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/mosi_pin +add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/oe_pin +add wave -noupdate -color {Cornflower Blue} /spi_master_tb/SM3/miso_pin add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/sequence_cntr add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/clk_pin add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/ncs_pin -add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/d_out_pin -add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/d_oe -add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/d_in_pin +add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/mosi_pin +add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/oe_pin +add wave -noupdate -color {Orange Red} /spi_master_tb/SM4/miso_pin TreeUpdate [SetDefaultTree] WaveRestoreCursors {{Cursor 1} {801886 ps} 0} quietly wave cursor active 1