<lekernel>
plain integer constants in Verilog are 32 bits and ...signed?!
<wpwrak>
lekernel: like in C ?
<larsc>
i don't know what the standard says, but for a language like verilog it wouldn't make much sense for interger constans to have any size at all
<wpwrak>
larsc: hmm, for general math, it would be useful. languages that require an excessive amount of declarations tend to just invite problems. e.g., think of pascal's ranges.
<wpwrak>
larsc: but i don't know verilog well enough to really criticize the language design.
<larsc>
wpwrak: what i meant was that it would make sense for them to have no upper limit.
<larsc>
since those are consts and known at compile time you know the size they'll require
<larsc>
and can create a signal large enough to hold that const
<larsc>
if your const is only 4 bits wide you wouldn't want to instantiate a 32-bit signal.
<larsc>
and artificially limiting the size to 32-bit would also disallow you from using larger consts which will result in crude hacks when dealing with signals with more then 32 bit wide
<wpwrak>
hmm. that still wouldn't solve the math problem, though. is "3+1" 2 or 3 bits ?
<larsc>
like 'if signal[63:32] == MY_CONST_UPPER and signal[31:0] == MY_CONST_LOWER"
<wpwrak>
dunno how verilog handles "large" integers. hopefully not in an overly ugly way ;-)
<larsc>
wpwrak: consts are known at compile time
<larsc>
so you know that 3+1 is 4
<wpwrak>
how about 2-3 ? :-)
<larsc>
not different
<larsc>
the actual representation of the number will depend on the context
<wpwrak>
so you would have "infinite" integers ? e.g., 2-3 would be "*010" - "*011" = "*1" ? with *0 = an arbitrary number of zeroes, *1 = an arbitrary number of ones ? that might work.
<larsc>
2-3 would be -1
<larsc>
the bit representation then would depend on the context
<larsc>
if you would assgin it to an 4-bit wide signed signal you would get 1111
<larsc>
if you would assign it to a 16-bit signed signal you would get 1111111....
<larsc>
if you would assign it to a unsigned signal you would get an error
<wpwrak>
(24+4) >> 1 assigned to 4 bits would then be an error ?
<larsc>
why?
<wpwrak>
or, better, (14+4) >> 1. would it be a) error, b) 9, c) 1 ?
<wpwrak>
because you cannot represent the result of 14+4 in 4 bits
<larsc>
but (14+4) >> 1
<wpwrak>
(well, assuming the usual conventions)
<wpwrak>
and with how many bits do you calculate the intermediate results ? does the "value size is target size" rule not apply there ?
<larsc>
no
<larsc>
well, at least how i would model it
<wpwrak>
they probably just didn't want to get into arbitrary-precision math.
<larsc>
but you have to
<larsc>
though floating point numbers is a different topic
<wpwrak>
does verilog have floats ? wow. best to replace them just as rational numbers then ;-)Â Â so 0.5 = 1/2, and you can represent 1/10 precisely.
<larsc>
i think they have
<wpwrak>
but you see that the arithmetic "core" gets quite heavy if you make such provisions. just declaring the world to be 32 bits is a lot easier :)
<larsc>
and stupid ;)
<larsc>
if you think about it, it really doesn't make any sense at all
<larsc>
(to limit the number space)
<wpwrak>
i would have to come up with a nice example where you actually depend on truncation of higher digits :)
<wpwrak>
maybe with xor.what's N ^ 3 ? is it N ^ 00...011 or N ^ 11...111 ?
<wpwrak>
examples like  a = b ^ ~c. there you quickly run into ambiguities if not everything has the same size. maybe you could solve them with a two-pass solver, though. first pass would determinate the worst-case size, and then the seocnd pass would perform all calculations with that size.
<wpwrak>
gah, determine
<wpwrak>
three-pass actually. first, your propagate from operands to results. second, yoiu
<wpwrak>
'd propagate (sizes) back from results to operands. third, you'd do the calculation.
<wpwrak>
what was the verilog notation for size again ... size'value ?
<wpwrak>
so (14+4) >> 1 would be (4'14+3'4) >> 1'1 before pass 1, after pass 1 maybe (*) 5'(5'(4'14+3'4) >> 1'1), and after pass 2 something like 5'(5'(5'14+5'4)) >> 1'1).
<wpwrak>
(*) depends on how shift is defined. e.g., does a right-shift reduce the size of the value or does it leave it the same, filling the high bit(s) with zero(es) ?
<wpwrak>
i think it gets quite nasty when you get down to the details. particularly when combining arithmetic with bit-ops.
<larsc>
one think that indeed wouldn't work with that concept is bit-wise negation
<larsc>
or maybe any bit-wise operation at all
<larsc>
because you haven't choosen a bit representation of the number yet
<larsc>
you'd have to cast to a specific representation first
<larsc>
in vhdl for example you have to_unsigned and to_signed constructs
<larsc>
which take a integer and a wide
<larsc>
to_unsigned(3, 4) would be 0011
<wpwrak>
yes, you would either have to treat bit-negation as signed or maybe even introduce a sign-extended unsigned type
<wpwrak>
or maybe just the "infinite prefix" approach would work, i.e., the *0/*1 i mentioned above
<larsc>
nah, disallow bit-wise operations on integers
<wpwrak>
hehe ;-)
<larsc>
we take it for granted nowadays how a number is represented
<larsc>
but with hdls the implementator can choose its own.
<larsc>
you have to differentiate between the abstract concept of a number and the actual implementation
<larsc>
and a number per se has no bits
<larsc>
bits are specific to a binary implementation
<larsc>
anyway, i'll have to go the train. 'll be back in a few hours
<larsc>
wpwrak: consider the following example:
<larsc>
always @(posedge clk) begin; if counter = 15 begin; counter = 0; end else begin counter = counter + 1; end end
<larsc>
switch(counter) begin case 0: doA; case 1 doB; case 2: doC ...
<kristianpaul>
and counter initial value is?
<larsc>
doesn't matter ;)
<kristianpaul>
k
<larsc>
if you choose a binary representation for counter you'd end up with a 4-bit register, an adder and 16 comparers.
<larsc>
you could use a 16-bit shift register though, were each bit represents one state of the counter
<kristianpaul>
is see, the points is dempostrate that you cant take for granted numeric representations as in software..
<wpwrak>
larsc: yes, that's basically an optimization problem, where you replace one construct with a different construct that has the same semantics. similar to the use of calculated jumps to implement "case" in a C compiler.
<kristianpaul>
also when you use a for to parametrice the generation of some logic
<kristianpaul>
right?
<wpwrak>
larsc: also, whether the shifter really makes sense also depends on what happens in the cases. e.g., if case N just stored value N+1 in some output register, then I'd keep the counter ;-)
<wpwrak>
(to make it more interesting and plausible, add one exception)
<larsc>
the example assumes counter is not used elsewise
<larsc>
wpwrak: but even if you'd store the counter to a register in one of the cases it should still be far more efficent to use the shifter
<larsc>
ones and zeros are cheap
<larsc>
a compare unit is not so cheap
<wpwrak>
probably, yes. but it all really depends on what exactly happens in the rest
<kristianpaul>
also in the avaliable resources on fpga, as larsc said, what is cheap and what not
<kristianpaul>
registers are expensive :-)
<larsc>
yes. and i hope that helps my point that for hdl languages you should not expect a certain bit representation of an integer
<kristianpaul>
totally agree
<kristianpaul>
or who knows wpwrak can force llhdl to follow that rule ;-)
<kristianpaul>
not follow*
<kristianpaul>
at the end is a resource problem too, so fpga market can change the rules about that too
<wpwrak>
the bit representation defines the semantics in an easily understood way. perhaps not easily understood per se, but given that this is basic CS knowledge, few engineers will have difficulties with it
<larsc>
in languages like C we can safley assume that a integer is stored as binary number, because the underlying processor will always use that representation
<wpwrak>
if you introduce your own set of rules, people need to wrap their head around them
<kristianpaul>
wpwrak: problem is logic and how you wire it up,
<kristianpaul>
imagine that using fluids :p
<wpwrak>
that you generate in the end does not have to have any resemblance to the model chosen to define the semantics of the definition of the design
<larsc>
wpwrak: i don't introduce my own rules, it's simple plain math ;)
<wpwrak>
larsc: for integers, yes. but already word size can be manipulated. consider an 8 bit microcontroller. a compiler can often tell that this "32 bit" integer is really only used as 8 bit.
<larsc>
it's still a binary number
<wpwrak>
larsc: well, you suggested that you wanted to separate bit ops from arithmetic. that sounds like a new set of rules ;)
<kristianpaul>
wait wait, you said microcontroller, thats a high level talk i think
<larsc>
actualy bit- and arithmetic operations are two differnent sets of operations. in programming languages they just tend to be defined on the same datatype
<wpwrak>
it's still a binary number but already different. there are more complex cases. e.g., loop optimization often removes counters or combines them
<wpwrak>
larsc: ah, so -X = ~X+1 is coincidence ? ;-)
<wpwrak>
(i was waiting for this one ;-))
<larsc>
wpwrak: yes it is
<larsc>
it's not true if you use a ones-complement binary representation
<wpwrak>
correct, yes. so you would leave the representation of numbers completely undefined ? e.g., they wouldn't even have to be binary ?
<larsc>
yes
<wpwrak>
so  reg & 2  would be an error
<larsc>
no
<wpwrak>
reg & (cast-to-binary) 2Â Â then ? :)
<kristianpaul>
what you want to do with: reg & 2 ?
<wpwrak>
test/access/whatever one bit
<kristianpaul>
thats 2 bits i think
<larsc>
wpwrak: you have to differentiate between interger types and binary types
<wpwrak>
binary 00...010 -> one bit is set. and zeroes all the other bits in "reg"
<larsc>
reg would probably be a binary
<larsc>
of a certain size
<larsc>
so using a bitwise operation on a binary and an interger would cause an implicit cast on the interger
<larsc>
and you would only get an error if the interger is too large for the binarys space
<larsc>
and yes, in vhdl your example would be an error. you'd have to use "reg & to_unsigned(2, 4)" or "reg & d'2"
<wpwrak>
can you also to_unsigned(reg, 4) ?
<wpwrak>
or only literals/constant expressions ?
<larsc>
would be possible
<larsc>
you can define integer signals
<wpwrak>
so vhdl tries to be pascal-like while verilog is more c-like
<larsc>
correct
<kristianpaul>
:D
<kristianpaul>
and llhdl.. :-)
<wpwrak>
for code generation, this may not make much of a difference, of course. you'll have to be able to handle these cases in either case
<larsc>
if no bit operations are used on an binary type it is probably converted to an integer by the compiler
<wpwrak>
the concept of a "natural" word size is problematic. also in programming languages. in theory, the only proper way of doing it would be to have no implicit sizes and each variable would have to be declared with a range.
<wpwrak>
but in practive, this would be insane. e.g., you would have to change declarations even if you only change algorithms a bit (for fencepost errors and such)
<wpwrak>
and it gets even nastier if a variable only exceeds its range when the variable is no longer used afterwards.
<wpwrak>
the "natural" word size helps there, because it's usually "more than enough". so while this is sloppy, it also avoids having to spend a lot of attention on micro-managing things.
<kristianpaul>
wrong direction, thats expensive !
<kristianpaul>
now
<wpwrak>
hmm ?
<kristianpaul>
"natural" word size
<wpwrak>
no, it's cheap :-) (in traditional programming languages)
<larsc>
wpwrak: i think you are still thinking too much in 'traditional' terms
<wpwrak>
in a hardware description language, i would expect the synthesis to ignore any sized that aren't nailed down anyway
<wpwrak>
larsc: (ignore sizes) like in your counter+case vs. shifter example
<wpwrak>
larsc: what i'm saying is that one should differentiate from the semantics of the representation and the implementation
<larsc>
yea, thats basicaly what i said
<wpwrak>
larsc: if the representation assumes a "universal" 32 bit word size, that shouldn't prevent the implementation from doing something completely different
<larsc>
at least i think
<wpwrak>
heh, so we agree ? :)
<larsc>
but why assume 32bits in the first place?
<kristianpaul>
here we go again :-)
<wpwrak>
may be one case of "everything is a vax". let's be happy that they didn't follow the "everything is a pdp-11" mantra, or it would be 16 bits ;-)
<kristianpaul>
lets a sume a "universal" n bit word size :-)
<larsc>
wpwrak: and now image you want to implement a 64bit cpu
<wpwrak>
also, for a C programmer, this convention, along with the convention that numbers are arithmetic and binary, would be natural. so there would be fewer bugs caused by wrong "common sense"
<wpwrak>
yeah, that's an interesting question. how do you do >32 bits ?
<larsc>
wpwrak: well you can use arithmetic and binary operations on binaries, but not on integers.
<wpwrak>
a major departure from C, which is not a nice thing to do in a language that aims to be C-like
<kristianpaul>
indeed
<kristianpaul>
But sintax is lookig compared with vhdl, (at least for me)
<kristianpaul>
nice looking*
<kristianpaul>
C-like modeling
<kristianpaul>
not implementation
<kristianpaul>
but yes, you should be aware of the non-comon sense rules :-)
<larsc>
wpwrak: if you wanted c like integers you could easily do something like typdef signed[0:31] int32
<larsc>
but imposing that artificial limit on all numbers doesn't appear as a good idea to me
<larsc>
for 'traditional' programs you have that limit because it is not artificial
<larsc>
as you said it's the natural word size
<roh>
wpwrak: >32bit? use proper amounts of ram (yes, i have seen data sources in use > than 4g address room)
<roh>
or 'store type information' is also nice. one could use 2-4 bits easily there. i'd like 36bit or 72bit computers please. with an io type checking hw on every bus interface
<wpwrak>
larsc: well, did they solve it in verilog ?
<larsc>
wpwrak: what?
<wpwrak>
64 bit values
<larsc>
well you simply define a register of width 64bit
<larsc>
reg foobar[63:0];
<larsc>
actualy it is 'reg [63:0] foobar;'
<wpwrak>
larsc: so there are no technical problems going beyond 32 bits after all ?
<larsc>
no
<wpwrak>
ah, bliss and happiness :-)
<kristianpaul>
.D
<kristianpaul>
more o less, the hapinesss will be a N bit system
<larsc>
you suggested to limit the size to 32bit thats why i ask how would implement a 64bit cpu in such an environment
<wpwrak>
naw, i didn't suggest to limit the size. you said integer constants were 32 bit only. i merely looked for justifications why (a) fixed size(s) would lead to more consistency in an environment where this is the case (as opposed to a dynamic-precision system)
<roh>
why limit at all?
<larsc>
wpwrak: i never said that
<larsc>
wpwrak: i said that imo there shouldn't be a limit on integer size
<wpwrak>
oh, sorry, that was sebastien. too many l* ;)
<lekernel>
wpwrak: in Verilog you can define constants with an optional size specifier
<lekernel>
e.g. 13'd78 defines a 13-bit unsigned constant with value 78 (in decimal)
<lekernel>
3'b101 3-bit with value 101 in binary
<lekernel>
but if you just write, say, 78, it's 32-bit and, I think, unsigned