|
| 1 | +Partially assigned register |
| 2 | +============================ |
| 3 | + |
| 4 | +Introduction |
| 5 | +------------ |
| 6 | + |
| 7 | +SpinalHDL will check that when a register is conditionally assigned, all bits of the register must at least be assigned once. If some bits are left unassigned, it can lead to unintended hardware behavior such as latches or unpredictable values. |
| 8 | + |
| 9 | +This error occurs when: |
| 10 | + |
| 11 | +* A register is assigned within a conditional block (``when``/``switch``) |
| 12 | +* Only some bits of the register are assigned |
| 13 | +* Other bits are left without assignment in that path |
| 14 | + |
| 15 | +Example |
| 16 | +------- |
| 17 | + |
| 18 | +The following code: |
| 19 | + |
| 20 | +.. code-block:: scala |
| 21 | +
|
| 22 | + class TopLevel extends Component{ |
| 23 | +
|
| 24 | + val io = new Bundle { |
| 25 | + val condition = in Bool() |
| 26 | + val result = out UInt( 8 bits ) |
| 27 | + } |
| 28 | +
|
| 29 | + val myReg = Reg(UInt( 8 bits )) |
| 30 | +
|
| 31 | + when(io.condition){ |
| 32 | + myReg(3 downto 0) := 0xF // Only lower 4 bits assigned |
| 33 | + // Upper 4 bits are not assigned! |
| 34 | + } |
| 35 | +
|
| 36 | + io.result := myReg |
| 37 | + } |
| 38 | +
|
| 39 | +will throw: |
| 40 | + |
| 41 | +:: |
| 42 | + |
| 43 | + PARTIALLY ASSIGNED REGISTER (toplevel/myReg : UInt[8 bits]), unassigned bit mask is 11110000, defined at |
| 44 | + *** |
| 45 | + Source file location of the toplevel/myReg definition via the stack trace |
| 46 | + *** |
| 47 | + |
| 48 | +How to fix it |
| 49 | +------------- |
| 50 | + |
| 51 | +There are several ways to fix this error: |
| 52 | + |
| 53 | +**Solution 1: Assign the complete register** |
| 54 | + |
| 55 | +.. code-block:: scala |
| 56 | +
|
| 57 | + class TopLevel extends Component{ |
| 58 | +
|
| 59 | + val io = new Bundle { |
| 60 | + val condition = in Bool() |
| 61 | + val result = out UInt(8 bits) |
| 62 | + } |
| 63 | +
|
| 64 | + val myReg = Reg(UInt( 8 bits )) |
| 65 | +
|
| 66 | + when(io.condition){ |
| 67 | + myReg(7 downto 0) := 0x0F // Assign all 8 bits |
| 68 | +
|
| 69 | + } |
| 70 | +
|
| 71 | + io.result := myReg |
| 72 | + } |
| 73 | +
|
| 74 | +
|
| 75 | +**Solution 2: Explicitly handle all bits** |
| 76 | + |
| 77 | +.. code-block:: scala |
| 78 | +
|
| 79 | + class TopLevel extends Component{ |
| 80 | +
|
| 81 | + val io = new Bundle { |
| 82 | + val condition = in Bool() |
| 83 | + val result = out UInt(8 bits) |
| 84 | + } |
| 85 | +
|
| 86 | + val myReg = Reg(UInt(8 bits)) |
| 87 | +
|
| 88 | + when(io.condition){ |
| 89 | + myReg(3 downto 0) := 0xF // Explicitly keep upper bits |
| 90 | + myReg(7 downto 4) := myReg(7 downto 4) |
| 91 | +
|
| 92 | + } |
| 93 | +
|
| 94 | + io.result := myReg |
| 95 | + } |
| 96 | +
|
| 97 | +**Solution 3: Provide a default value** |
| 98 | + |
| 99 | +.. code-block:: scala |
| 100 | +
|
| 101 | + class TopLevel extends Component{ |
| 102 | +
|
| 103 | + val io = new Bundle { |
| 104 | + val condition = in Bool() |
| 105 | + val result = out UInt(8 bits) |
| 106 | + } |
| 107 | +
|
| 108 | + val myReg = Reg(UInt(8 bits)) |
| 109 | +
|
| 110 | + when(io.condition){ |
| 111 | + myReg(3 downto 0) := 0xF |
| 112 | + // Upper bits will retain their value from previous cycle |
| 113 | + }.otherwise { |
| 114 | + myReg := myReg // Explicitly maintain value |
| 115 | + } |
| 116 | +
|
| 117 | + io.result := myReg |
| 118 | + } |
0 commit comments