Using a Demux to assign a value

I’m trying to implement a Demux module that will allow me to assign a value depending upon the value of a selector (sliceOwner)

module RamMUX #()
( 
  input  logic[ 1:0]              iSliceOwner;
 
  input  wire [20:0]              iSliceDataWrites,
  output wire [20:0]              oSliceDataWrites,

  input  wire [20:0]              iVgaDataWrites,
  output wire [20:0]              oVgaDataWrites

  input  wire [20:0]              iBltDataWrites,
  output wire [20:0]              oBltDataWrites
};

localparam          SLICE_RESET    = 2'b00;
localparam          SLICE_VGA      = 2'b01;
localparam          SLICE_BLT      = 2'b10;
localparam          SLICE_IDLE     = 2'b11;

always @( * )
begin
  case ( iSliceOwner )
    SLICE_VGA : begin
      oVgaDataReads         = iSliceDataReads;
      oVgaDataWrites        = iSliceDataWrites;

      oSliceDataReads       = iVgaDataReads;
      oSliceDataWrites      = iVgaDataWrites;
    end
    
    SLICE_BLT : begin
      oBltDataReads         = iSliceDataReads;
      oBltDataWrites        = iSliceDataWrites;

      oSliceDataReads       = iBltDataReads;
      oSliceDataWrites      = iBltDataWrites;
    end

    SLICE_RESET : begin
      oSliceDataReads       = 0;
      oSliceDataWrites      = 0;

      oVgaDataWrites = 0;
      oBltDataWrites = 0;
     
      oVgaDataReads  = 0;
      oBltDataReads  = 0;
    end
    
    SLICE_IDLE: begin
      // Keep contents as they are..
      oVgaDataReads         = iVgaDataReads;
      oVgaDataWrites        = iVgaDataWrites;
      
      oBltDataReads         = iBltDataReads;
      oBltDataWrites        = iBltDataWrites;
      
    end
    
    default : begin
      oSliceDataReads       = 0;
      oSliceDataWrites      = 0;
    end
  endcase
end
  
endmodule



Parent module:

..
bit [20:0]              vgaDataReads  = 0;
bit [20:0]              vgaDataWrites = 0;
bit [20:0]              bltDataReads  = 0;
bit [20:0]              bltDataWrites = 0;

wire [20:0]             wSliceDataReads;
wire [20:0]             wSliceDataWrites;

bit [20:0]              rSliceDataReads;
bit [20:0]              rSliceDataWrites;

logic       [1 : 0] sliceOwner;

RamMUX #( 
  .ADDR_WIDTH (ADDR_WIDTH), 
  .DATA_WIDTH (DATA_WIDTH) 
)
ramMux
( 
  .iSliceOwner(           sliceOwner ),
 
  //------------------------------------------------------------------------------
  // Assignment inputs
  //------------------------------------------------------------------------------
  .iSliceDataReads(       wSliceDataReads ),
  .iSliceDataWrites(      wSliceDataWrites ),
  //------------------------------------------------------------------------------
  // Read value outputs
  //------------------------------------------------------------------------------
  .oSliceDataReads(       rSliceDataReads ),
  .oSliceDataWrites(      rSliceDataWrites ),
  //------------------------------------------------------------------------------
  .iVgaDataReads(       vgaDataReads ),
  .oVgaDataReads(       vgaDataReads ),
  .iVgaDataWrites(      vgaDataWrites ),
  .oVgaDataWrites(      vgaDataWrites ),
  //------------------------------------------------------------------------------
  .iBltDataReads(       bltDataReads ),
  .oBltDataReads(       bltDataReads ),
  .iBltDataWrites(      bltDataWrites ),
  .oBltDataWrites(      bltDataWrites ),
  //------------------------------------------------------------------------------
);

always_ff @( posedge iClk  )
begin
  ..
  // State machine in here.. I assign sliceOwner to choose whether vgaDataReads or bltDataReads can be read/written..
  sliceOwner <= SLICE_VGA;

  // Here I'm trying to increment either vgaDataReads or bltDataReads, depending upon what sliceOwner is set to
  wSliceDataReads <= rSliceDataReads + 1;
  ..
end

I keep getting the following errors:

Warning (10240): Verilog HDL Always Construct warning at RamMUX.sv(127): inferring latch(es) for variable "oVgaDataReads", which holds its previous value in one or more paths through the always construct

Why do I keep getting these latch warnings, and how can I avoid them? Sorry I couldn’t post an entire module. I really need some help with fundamentals here.

In reply to SparkyNZ:

Within a combinational always block, you must follow a few rules

  • Within the same block, you cannot read a variable before writing to it. Otherwise that variable would have to hold it value from the previous execution of the block.
  • If you write to a variable and it is read outside the block, you must make sure it is written in every conceivable path through conditional statements in the block.

In your code, the SLICE_RESET branch of the case statement writes to 6 variables, but the SLICE_BLT branch only write to 4 of them. What values should oVgaDataReads and oVgaDataReads have when iSliceOwner is SLICE_BLT?

If you do not care, then write 'x to all your variables before the case statement.

BTW, your module outputs should be logic, not wire, and you should use always_comb instead always @(*)

In reply to dave_59:

Thanks Dave. The values of oVgaDataReads and oVgaDataWrites should remain was they were when iSliceOwner is SLICE_BLT.

Would assigning them to 'x achieve this?

In reply to SparkyNZ:

The definition of combinational logic is that the outputs are a complete function of their current inputs. As soon as you say you want an output to remain the way it was when an input changes, that implies you want it to remember the previous inputs. That is the definition of a latch or sequential logic.