0
\$\begingroup\$

enter image description here

I am trying to implement the SPI_SLAVE

module SPI_Slave(MOSI,SS_n,clk,rst_n,tx_data,tx_valid,MISO,rx_data,rx_valid) ;

  input MOSI,SS_n,clk,rst_n,tx_valid;
  input [7:0] tx_data;
  output reg MISO,rx_valid;
  output reg [9:0] rx_data;
 
  parameter IDLE      = 3'b000;
  parameter WRITE     = 3'b001;
  parameter READ_DATA = 3'b010;
  parameter READ_ADD  = 3'b011;
  parameter CHK_CMD   = 3'b100;

  reg read_indicator; //1 for read address and 0 for read data
  reg [2:0] cs, ns;
  reg [3:0] counter_internal=10;
  reg [3:0] counter_external=8;
  reg [7:0] temporary_register;

  /*integer i=9;

  always@(posedge clk) begin
     rx_data[i] <= MOSI;
     if(i==0) begin
        i<=10;
      end
      i<=i-1;
  end*/

  //State Memory
  always @(posedge clk or negedge rst_n) begin
     if(~rst_n) begin
   cs = IDLE;
   rx_valid = 0;
   counter_internal = 10 ;
   counter_external = 8 ;
     end
     else
   cs = ns;
  end

// Output Logic 
always @(posedge clk) begin
     case(cs)
        IDLE: 
            rx_data = 0;
        CHK_CMD: 
            if (rx_data[9]==1 && rx_data[8]==0)
                     read_indicator = 1;     //read address
                    else if (rx_data[9]==1 && rx_data[8]==1)
                     read_indicator = 0;    //read data
        
        READ_ADD: 
            if (counter_internal==0)begin
                rx_valid=1;
                rx_data=temporary_register;
                counter_internal=10;
            end
            else begin
            temporary_register[counter_internal]= MOSI;
            counter_internal=counter_internal-1;
            end
        
        READ_DATA: 
            if (tx_valid==1)begin
                if (counter_external==0)begin
                    counter_external=8;
                end
                else begin
                    MISO=tx_data[counter_external];
                    counter_external=counter_external-1;
                end
            end
        
        WRITE: 
            if (counter_internal ==0)begin
                rx_valid=1;
                rx_data=temporary_register;
                counter_internal=10;
            end
            else begin
            temporary_register[counter_internal]= MOSI;
            counter_internal=counter_internal-1;
            end
        endcase
end  

  // Next State Logic
  always@(cs,SS_n) begin
     
     case(cs)
            IDLE:
            if(SS_n==1)
               ns = IDLE ;
            else
               ns = CHK_CMD ;

            CHK_CMD:
            if(SS_n ==0 && MOSI==0)
               ns = WRITE;
            else if (SS_n==1)
               ns = IDLE;
            else if (SS_n == 0 && MOSI==1 && read_indicator==0)
               ns = READ_DATA;
    else if (SS_n == 0 && MOSI==1 && read_indicator==1)
        ns = READ_ADD;

            READ_DATA:
            if(SS_n==1)
               ns = IDLE;
            else if (SS_n==0 && tx_valid==1)
               ns = READ_DATA;

            WRITE:
            if(SS_n==1)
               ns = IDLE;
            else if (SS_n ==0 && rx_valid==1)
               ns = WRITE;

            READ_ADD:
            if(SS_n==1)
               ns = IDLE;
            else if (SS_n==0 && rx_valid==1)
               ns = READ_ADD;

       default : ns = IDLE;
     endcase
           
  end

endmodule

Whenever I do test bench I get zeros in the rx_Data line, I don't know why. Can anyone help with this?

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Cunning place to hide a question... But I doubt it can be answered without the testbench. \$\endgroup\$ – user_1818839 Oct 26 '20 at 20:39
  • 1
    \$\begingroup\$ And if you have a testbench, why don't you debug with a simulation? it is much better than trying to debug your source code by inspection. \$\endgroup\$ – Elliot Alderson Oct 26 '20 at 20:45
  • \$\begingroup\$ I don't have the test bench I have simulated one manually to see if its working or not however it doesn't work \$\endgroup\$ – Dynamic Oct 26 '20 at 20:51
  • 1
    \$\begingroup\$ Be more specific. When you say "doesn't work", what inputs did you give? What outputs did you expect? How were the actual outputs different? A timing diagram will probably help make it more clear. \$\endgroup\$ – The Photon Oct 26 '20 at 21:34
  • 1
    \$\begingroup\$ Quick observations: always@(cs,SS_n) should be always @* otherwise it is not sensitive to all other input sources (ex tx_valid, rx_valid, MOSI, etc.). Signals should only be assigned withing one always block; it will not synthesize otherwise. Sequential logic (e.g. signals assigned in an always block that sensitive to clock edge) should be assigned with non-blocking assignments (ex cs <= ns;). \$\endgroup\$ – Greg Oct 26 '20 at 22:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.