<lekernel>
...what actually happens is that 4 is the sign bit in "3'sd4", which gets extended to -4 when the target is more than 3 bits. and it becomes 1 - (-4) = 5
<lekernel>
thus the rule: in verilog, when you want to represent the most negative integer, you should write its absolute (positive) value instead :)
Mistah_Darcy has joined #m-labs
Mistah_Darcy has quit [Read error: Connection reset by peer]
Mistah_Darcy has joined #m-labs
<GitHub36>
[migen] sbourdeauducq pushed 1 new commit to master: http://git.io/d2s6Dg
<lekernel>
rjo, your test passes now. -1'sd1 was 1 in Verilog :)
<rjo>
lekernel: that's horrible ;)
<rjo>
lekernel: thanks for looking into this. i didn't have the guts to dive that deep into verilog.
mumptai has joined #m-labs
<rjo>
lekernel: that means verilog does sign extend literal constants even when they do not have a "-" that would indicate their negativity?
<lekernel>
it sign-extends operands when the context is signed
<lekernel>
the signedness of the context is defined by the signedness of all operands
<lekernel>
and you can mark literal constants as signed by using 's
<lekernel>
in which case the MSB is the sign bit, and you have to set it manually - using the unary minus before the literal fails for the most negative integer, as we have seen :)
<lekernel>
you can also mark any part of an expression as signed by using $signed (Migen inserts those to provide better sign extension rules)
<rjo>
lekernel: would writing -4'sd4 not work in a 3-bit signed context?
<lekernel>
it would work
<rjo>
lekernel: would it not be more readable?
<lekernel>
but because that literal would make it a 4-bit context
<lekernel>
it would make it more readable, but then, it breaks the rule that literals use their minimum number of bits
<lekernel>
which can cause problems e.g. when putting them in Cat() or Replicate()
<mumptai>
hey, it contains pixelated men and pretty colors ;)
<rjo>
lekernel: ok. understood. but i dont see why verilog is unable to represent the most negative integer using a unary minus. i do understand why 3'sd4 is "wrong" in the sense that it either invalid or -4. But why is -3'sd4 not -4? Just because --3'sd4 != 3'sd4 then?
<lekernel>
because 3'sd4 is -4
<rjo>
that presentation seriously lacks some WordArt and yellow text.
<lekernel>
as the 3rd bit (MSB) is the sign bit, which would have weight 4 if the value wasn't signed
<rjo>
lekernel: wouldn't you want 3'sd4 to be invalid in a better world?
<lekernel>
yes, but then you can't represent -4, as the unary minus won't let you
<lekernel>
(you need an extra bit to represent the absolute value of the most negative integer)
<rjo>
lekernel: hmm
<lekernel>
right now, migen spits out the explicit two's complement representation of the value, and tells Verilog to treat the MSB as sign bit
<lekernel>
it's a straightforward solution, which has the inconvenience of making negative values less readable in the generated code
<lekernel>
and you get things like 1'sd1 for -1, which is horrible, but works ...
<rjo>
lekernel: so this is the only way to represent the most negative signed integer without wrongly increasing the bit-width of the context?
sh4rm4 has quit [Ping timeout: 264 seconds]
Mistah_Darcy_ has joined #m-labs
mumptai has quit [Quit: Verlassend]
<lekernel>
I think so
Mistah_Darcy has quit [Read error: Connection reset by peer]
<lekernel>
ah, no
<lekernel>
-1'd1 works
<lekernel>
:)
sh4rm4 has joined #m-labs
<lekernel>
hmm, actually, I could have simply dropped the "s", since the unary minus also makes the context signed
<lekernel>
ah, no, it does not
<lekernel>
-1'd1*5'sd5 is 155
<lekernel>
1'sd1*5'sd5 is -5 as one would expect
<lekernel>
$signed(-1'd1)*5'sd5 also works
<lekernel>
but is quite heavy
<lekernel>
Verilog is such a terrible language o__O