如何防止verilog中的线值冲突?

How to prevent conflict in wire value in verilog?

我正在设计一个 SPI 设备,它有一个主机和 3 个从机。当我尝试将数据从主机发送到 MOSI 上的一个从机时,它工作正常。但是当我在 MISO 上从一个从站向一个主站发送一个位序列时,我得到了很多 X。我知道这是由于电线中的价值观冲突而发生的,但我无法解决。

代码如下:

module Master(dataIN,dataOUT,slaveno,enable,reset,cpha,cpol,miso,mosi,clk,cs0,cs1,cs2);

  input enable,reset,cpha,cpol,miso,clk;
  output reg mosi,cs0,cs1,cs2;
  input [1:0] slaveno;
  input [7:0] dataIN;
  output [7:0] dataOUT;

  integer mode = 0;

  reg [7:0] data;

  assign dataOUT = data;

  always @ (posedge clk)
    begin
      if (reset)
        begin
          data <= 8'b00000000; 
          cs0 <= 1'b1;
          cs1 <= 1'b1;
          cs2 <= 1'b1;
          mosi <= 1'b0;
        end
        else if (enable === 1) begin
        case(slaveno)    
          2'b00    : cs0 <= 1'b0;
          2'b01    : cs1 <= 1'b0;
          2'b10    : cs2 <= 1'b0; 
          2'b11    : begin
            cs0 <= 1'b1;
            cs1 <= 1'b1;
            cs2 <= 1'b1;  
          end  
          default  : begin
            cs0 <= 1'b1;
            cs1 <= 1'b1;
            cs2 <= 1'b1;  
          end  
        endcase
        if (cpha === 1'b0 && cpol === 1'b0) 
            mode = 1;
          else if (cpha === 1'b0 && cpol === 1'b1)
            mode = 0;
          else if (cpha === 1'b1 && cpol === 1'b0)
            mode = 0;
          else if (cpha === 1'b1 && cpol === 1'b1)
            mode = 1;
        case (mode)
        0 : mosi <= data[7];
        1 : begin
          data [7:1] <= data [6:0];          
          data [0] <= miso;      
        end
        endcase
      end
      else if (enable === 1'b0 && dataIN !== 1'b0) begin
        data <= dataIN;
        cs0 <= 1'b1;
        cs1 <= 1'b1;
        cs2 <= 1'b1;
      end
    end

  always @ (negedge clk)
    begin
      if (reset)
        begin
          data <= 8'b00000000; 
          cs0 <= 1'b1;
          cs1 <= 1'b1;
          cs2 <= 1'b1;
          mosi <= 1'b0;
        end
        else if (enable === 1'b1) begin   
        case(slaveno)
          2'b00    : cs0 <= 1'b0;
          2'b01    : cs1 <= 1'b0;
          2'b10    : cs2 <= 1'b0;
          2'b11    : begin
            cs0 <= 1'b1;
            cs1 <= 1'b1;
            cs2 <= 1'b1;  
          end
          default  : begin
            cs0 <= 1'b1;
            cs1 <= 1'b1;  
            cs2 <= 1'b1;  
          end  
        endcase
        if (cpha === 1'b0 && cpol === 1'b0) 
            mode = 1;
          else if (cpha === 1'b0 && cpol === 1'b1)
            mode = 0;
          else if (cpha === 1'b1 && cpol === 1'b0)
            mode = 0;
          else if (cpha === 1'b1 && cpol === 1'b1)
            mode = 1;
        case (mode)
        0 : begin
          data [7:1] <= data [6:0];
          data [0] <= miso;      
        end
        1 : mosi <= data[7];
        endcase  
      end
      else if (enable === 1'b0 && dataIN !== 1'b0) begin
        data <= dataIN;
        cs0 <= 1'b1;
        cs1 <= 1'b1;
        cs2 <= 1'b1;
      end
    end
endmodule

module Slave(slaveDataIN,slaveDataOUT,reset,cpha,cpol,miso,mosi,clk,cs);

  input reset,cpha,cpol,mosi,clk,cs;
  output reg miso;
  input [7:0] slaveDataIN;
  output [7:0]  slaveDataOUT;

  reg [7:0] data;

  integer mode = 0;

  assign  slaveDataOUT = data;

  always @ (posedge clk)
    begin
      if (reset)
        begin
        data <= 8'b00000000;
        miso <= 1'b0;
      end
      else if (cs === 1'b0) begin
        if (cpha === 1'b0 && cpol === 1'b0)
          mode = 1;
        else if (cpha === 1'b0 && cpol === 1'b1)
          mode = 0;
        else if (cpha === 1'b1 && cpol === 1'b0)
          mode = 0;
        else if (cpha === 1'b1 && cpol === 1'b1)
          mode = 1;
        case (mode)
          1 : miso <= data[7];
          0 : begin
            data [7:1] <= data [6:0];
            data [0] <= mosi;
          end
        endcase
      end
      else if (cs === 1'b1 && slaveDataIN !== 1'b0)
        data <= slaveDataIN;
    end

  always @ (negedge clk)
    begin
      if (reset)
        begin
        data <= 8'b00000000;
        miso <= 1'b0;
      end
      else if (cs === 1'b0) begin
        if (cpha === 1'b0 && cpol === 1'b0)
          mode = 1;
        else if (cpha === 1'b0 && cpol === 1'b1)
          mode = 0;
        else if (cpha === 1'b1 && cpol === 1'b0)
          mode = 0;
        else if (cpha === 1'b1 && cpol === 1'b1)
          mode = 1;
        case (mode)
          1 : begin
            data [7:1] <= data [6:0];
            data [0] <= mosi;
          end
          0 : miso <= data[7];
        endcase
      end
      else if (cs === 1'b1 && slaveDataIN !== 1'b0)
        data <= slaveDataIN;
    end
endmodule

module SPI(masterDataIN,slave0DataIN,slave1DataIN,slave2DataIN,masterDataOUT,slave0DataOUT,
            slave1DataOUT,slave2DataOUT,slaveno,enable,reset,cpha,cpol,clk);

input [7:0] masterDataIN,slave0DataIN,slave1DataIN,slave2DataIN;
output wire [7:0] masterDataOUT,slave0DataOUT,slave1DataOUT,slave2DataOUT;
input [1:0] slaveno;
input enable,reset,cpha,cpol,clk;
wire miso,mosi,cs0,cs1,cs2;

Master m (masterDataIN,masterDataOUT,slaveno,enable,reset,cpha,cpol,miso,mosi,clk,cs0,cs1,cs2);
Slave s1 (slave0DataIN,slave0DataOUT,reset,cpha,cpol,miso,mosi,clk,cs0);
Slave s2 (slave1DataIN,slave1DataOUT,reset,cpha,cpol,miso,mosi,clk,cs1);
Slave s3 (slave2DataIN,slave2DataOUT,reset,cpha,cpol,miso,mosi,clk,cs2);
endmodule

在测试台中,我尝试将数据放入 slaveDataIN 并在 8 个周期后在 masterDataOUT 上接收(我在 Xs 中获得大部分数据)。我该如何解决这个冲突?

PS: x 只代替 1 而不是 0.

您可以为每个从机的 MISO 信号创建一条单独的线路,然后使用 slaveno 到 select 等控制信号,从机将 miso 输入驱动到主机。例如:

wire miso1, miso2, miso3;

assign miso = (slaveno == 0) ? miso1 : (slaveno == 1) ? miso2 : miso3;

Slave s1 (slave0DataIN,slave0DataOUT,reset,cpha,cpol, miso1, mosi,clk,cs0);
Slave s2 (slave1DataIN,slave1DataOUT,reset,cpha,cpol, miso2, mosi,clk,cs1);
Slave s3 (slave2DataIN,slave2DataOUT,reset,cpha,cpol, miso3, mosi,clk,cs2);
                                                         //

PS。在你的代码中,如果所有 3 个从机都驱动 miso=0,那么将不会发生争用,因为它们都是相同的值;这解释了为什么你看到 0,而不是 x。