New to all this, have a question

Guest
As part of a personal project I am making a 7 segment decoder, the
following code
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1'd1 ? 6'b100101 :
(bcd == 1'd2 ? 6'b101001 :
(bcd == 1'd3 ? 6'b110001 :
(bcd == 1'd4 ? 6'b000001 :
(bcd == 1'd5 ? 6'b010001 :
(bcd == 1'd6 ? 6'b111001 :
(bcd == 1'd7 ? 6'b111101 :
(bcd == 1'd8 ? 6'b111111 :
(bcd == 1'd9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule
works as predicted, but
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1 ? 6'b100101 :
(bcd == 2 ? 6'b101001 :
(bcd == 3 ? 6'b110001 :
(bcd == 4 ? 6'b000001 :
(bcd == 5 ? 6'b010001 :
(bcd == 6 ? 6'b111001 :
(bcd == 7 ? 6'b111101 :
(bcd == 8 ? 6'b111111 :
(bcd == 9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule

ends up making a ROM for some reason. I was wondering a) why this
occurred, I was under the impression that the default radix in Verilog
was 10, or is something else going on here?
I figured out how to do this but I am trying to understand what is
going on...
do you always have to cast the numbers when you assign? it worked fine
when using case...
 
lewisrjc@gmail.com wrote:
As part of a personal project I am making a 7 segment decoder, the
following code
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1'd1 ? 6'b100101 :
(bcd == 1'd2 ? 6'b101001 :
(bcd == 1'd3 ? 6'b110001 :
(bcd == 1'd4 ? 6'b000001 :
(bcd == 1'd5 ? 6'b010001 :
(bcd == 1'd6 ? 6'b111001 :
(bcd == 1'd7 ? 6'b111101 :
(bcd == 1'd8 ? 6'b111111 :
(bcd == 1'd9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule
works as predicted, but
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1 ? 6'b100101 :
(bcd == 2 ? 6'b101001 :
(bcd == 3 ? 6'b110001 :
(bcd == 4 ? 6'b000001 :
(bcd == 5 ? 6'b010001 :
(bcd == 6 ? 6'b111001 :
(bcd == 7 ? 6'b111101 :
(bcd == 8 ? 6'b111111 :
(bcd == 9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule

ends up making a ROM for some reason. I was wondering a) why this
occurred, I was under the impression that the default radix in Verilog
was 10, or is something else going on here?
I figured out how to do this but I am trying to understand what is
going on...
do you always have to cast the numbers when you assign? it worked fine
when using case...
Does the first really work as expected? "1'd9" is a one-bit number, ie. it
is the same as 1'b1. Therefore I would expect your code (since it is a
priority tree) to reduce to:
assign seg = bcd[0]? 7'b0100101 : 7'b0100011;

On the other hand, in your second example "9" is an unsized number, and
therefore the code becomes something like:
assign seg = ~bcd[0] ? 7'b0100011
:(((bcd == 4'h1)? 7'b0100101
: ((bcd == 4'h3)? 7'b0110001
: ((bcd == 4'h5)? 7'b0010001
: ((bcd == 4'h7)? 7'b0111101
: ((bcd == 4'h9)? 7'b0100001 : 7'b0000000))))));

The 7-segment encodings are not what I'd expect either (consider seg[0]).

John

--
John Penton, posting as an individual unless specifically indicated
otherwise.
 
John Penton wrote:
lewisrjc@gmail.com wrote:
As part of a personal project I am making a 7 segment decoder, the
following code
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1'd1 ? 6'b100101 :
(bcd == 1'd2 ? 6'b101001 :
(bcd == 1'd3 ? 6'b110001 :
(bcd == 1'd4 ? 6'b000001 :
(bcd == 1'd5 ? 6'b010001 :
(bcd == 1'd6 ? 6'b111001 :
(bcd == 1'd7 ? 6'b111101 :
(bcd == 1'd8 ? 6'b111111 :
(bcd == 1'd9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule
works as predicted, but
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1 ? 6'b100101 :
(bcd == 2 ? 6'b101001 :
(bcd == 3 ? 6'b110001 :
(bcd == 4 ? 6'b000001 :
(bcd == 5 ? 6'b010001 :
(bcd == 6 ? 6'b111001 :
(bcd == 7 ? 6'b111101 :
(bcd == 8 ? 6'b111111 :
(bcd == 9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule

ends up making a ROM for some reason. I was wondering a) why this
occurred, I was under the impression that the default radix in Verilog
was 10, or is something else going on here?
I figured out how to do this but I am trying to understand what is
going on...
do you always have to cast the numbers when you assign? it worked fine
when using case...

Does the first really work as expected? "1'd9" is a one-bit number, ie. it
is the same as 1'b1. Therefore I would expect your code (since it is a
priority tree) to reduce to:
assign seg = bcd[0]? 7'b0100101 : 7'b0100011;

On the other hand, in your second example "9" is an unsized number, and
therefore the code becomes something like:
assign seg = ~bcd[0] ? 7'b0100011
:(((bcd == 4'h1)? 7'b0100101
: ((bcd == 4'h3)? 7'b0110001
: ((bcd == 4'h5)? 7'b0010001
: ((bcd == 4'h7)? 7'b0111101
: ((bcd == 4'h9)? 7'b0100001 : 7'b0000000))))));

The 7-segment encodings are not what I'd expect either (consider seg[0]).

John
Beautiful catch on the use of the decimal sizing (1'd9). The second
example, however, won't assign all even values to the decode for zero.
While the 1'd0 is a single bit value, the bcd value is still 4 bits.
The 4-bit bcd value is compared to the width-expanded 1-bit constant in
the first branch.

As for the original post...
ROMs are good! In an FPGA, you can't get a better decode for a
7-segment decoder than a 4-in, 7-out look-up-table (aka a ROM).

My only concerns would be using 7 segments - rather than 6 as in your
code - and generating the correct segments (such as 6 of the 7 bits in
the number 0) to display the numerals you want.

If you like, you can even extend the decoding to provide hex values with
no additional logic if your code implements a distributed ROM in the
4(or more)-input LUT tables that make up the FOGA fabric. If you just
want 0-9, restrict the input value to the 0-9 bcd range; the hex logic
will go unused but can be a generic building block for later use.

- John_H
 
John_H wrote:
John Penton wrote:
lewisrjc@gmail.com wrote:
As part of a personal project I am making a 7 segment decoder, the
following code
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1'd1 ? 6'b100101 :
(bcd == 1'd2 ? 6'b101001 :
(bcd == 1'd3 ? 6'b110001 :
(bcd == 1'd4 ? 6'b000001 :
(bcd == 1'd5 ? 6'b010001 :
(bcd == 1'd6 ? 6'b111001 :
(bcd == 1'd7 ? 6'b111101 :
(bcd == 1'd8 ? 6'b111111 :
(bcd == 1'd9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule
works as predicted, but
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1 ? 6'b100101 :
(bcd == 2 ? 6'b101001 :
(bcd == 3 ? 6'b110001 :
(bcd == 4 ? 6'b000001 :
(bcd == 5 ? 6'b010001 :
(bcd == 6 ? 6'b111001 :
(bcd == 7 ? 6'b111101 :
(bcd == 8 ? 6'b111111 :
(bcd == 9 ? 6'b100001 : 6'b000000)))))))))
;


endmodule

ends up making a ROM for some reason. I was wondering a) why this
occurred, I was under the impression that the default radix in
Verilog was 10, or is something else going on here?
I figured out how to do this but I am trying to understand what is
going on...
do you always have to cast the numbers when you assign? it worked
fine when using case...

Does the first really work as expected? "1'd9" is a one-bit number,
ie. it is the same as 1'b1. Therefore I would expect your code
(since it is a priority tree) to reduce to:
assign seg = bcd[0]? 7'b0100101 : 7'b0100011;

On the other hand, in your second example "9" is an unsized number,
and therefore the code becomes something like:
assign seg = ~bcd[0] ? 7'b0100011
:(((bcd == 4'h1)? 7'b0100101
: ((bcd == 4'h3)? 7'b0110001
: ((bcd == 4'h5)? 7'b0010001
: ((bcd == 4'h7)? 7'b0111101
: ((bcd == 4'h9)? 7'b0100001 :
7'b0000000)))))); The 7-segment encodings are not what I'd expect either
(consider
seg[0]). John

Beautiful catch on the use of the decimal sizing (1'd9). The second
example, however, won't assign all even values to the decode for zero.
While the 1'd0 is a single bit value, the bcd value is still 4 bits.
The 4-bit bcd value is compared to the width-expanded 1-bit constant
in the first branch.
A good point, my bad. Of course that (the fact that verilog expands rather
than truncates to match sizes on comparison) affects the first example too.
It is more like (I think):
assign seg = (bcd == 4'h0)? 7'b0100101
: ((bcd == 4'h1)? 7'b0100011 : 7'b0000000);

John

--
John Penton, posting as an individual unless specifically indicated
otherwise.
 
On Feb 12, 9:23 am, "John Penton" <john.pen...@arm.com> wrote:
John_H wrote:
John Penton wrote:
lewis...@gmail.com wrote:
As part of a personal project I am making a 7 segment decoder, the
following code
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1'd1 ? 6'b100101 :
(bcd == 1'd2 ? 6'b101001 :
(bcd == 1'd3 ? 6'b110001 :
(bcd == 1'd4 ? 6'b000001 :
(bcd == 1'd5 ? 6'b010001 :
(bcd == 1'd6 ? 6'b111001 :
(bcd == 1'd7 ? 6'b111101 :
(bcd == 1'd8 ? 6'b111111 :
(bcd == 1'd9 ? 6'b100001 : 6'b000000)))))))))
;

endmodule
works as predicted, but
module bcdassign(bcd, seg);
input [3:0] bcd;
output [6:0] seg;

assign seg = bcd == 1'd0 ? 6'b100011 :
(bcd == 1 ? 6'b100101 :
(bcd == 2 ? 6'b101001 :
(bcd == 3 ? 6'b110001 :
(bcd == 4 ? 6'b000001 :
(bcd == 5 ? 6'b010001 :
(bcd == 6 ? 6'b111001 :
(bcd == 7 ? 6'b111101 :
(bcd == 8 ? 6'b111111 :
(bcd == 9 ? 6'b100001 : 6'b000000)))))))))
;

endmodule

ends up making a ROM for some reason. I was wondering a) why this
occurred, I was under the impression that the default radix in
Verilog was 10, or is something else going on here?
I figured out how to do this but I am trying to understand what is
going on...
do you always have to cast the numbers when you assign? it worked
fine when using case...

Does the first really work as expected? "1'd9" is a one-bit number,
ie. it is the same as 1'b1. Therefore I would expect your code
(since it is a priority tree) to reduce to:
assign seg = bcd[0]? 7'b0100101 : 7'b0100011;

On the other hand, in your second example "9" is an unsized number,
and therefore the code becomes something like:
assign seg = ~bcd[0] ? 7'b0100011
:(((bcd == 4'h1)? 7'b0100101
: ((bcd == 4'h3)? 7'b0110001
: ((bcd == 4'h5)? 7'b0010001
: ((bcd == 4'h7)? 7'b0111101
: ((bcd == 4'h9)? 7'b0100001 :
7'b0000000)))))); The 7-segment encodings are not what I'd expect either
(consider
seg[0]). John

Beautiful catch on the use of the decimal sizing (1'd9). The second
example, however, won't assign all even values to the decode for zero.
While the 1'd0 is a single bit value, the bcd value is still 4 bits.
The 4-bit bcd value is compared to the width-expanded 1-bit constant
in the first branch.

A good point, my bad. Of course that (the fact that verilog expands rather
than truncates to match sizes on comparison) affects the first example too.
It is more like (I think):
assign seg = (bcd == 4'h0)? 7'b0100101
: ((bcd == 4'h1)? 7'b0100011 : 7'b0000000);

John

--
John Penton, posting as an individual unless specifically indicated
otherwise.
hmm, interesting, the #'rv # is bits? didn't know that
and yes the values are incorrect, I had them written down but not with
me when I posted, the 6 bits was just a mistake

So when I see a ROM in my circuit design, that is the same as a lut?
when I used the following
module bcd7seg(bcd, seg);
input [3:0] bcd;
output [6:0] seg;
reg [6:0]seg;

always@(bcd)
case(bcd)
0: seg = 63;
1: seg = 6;
2: seg = 91;
3: seg = 79;
4: seg = 102;
5: seg = 109;
6: seg = 125;
7: seg = 7;
8: seg = 127;
9: seg = 103;

default: seg = 0;
endcase


endmodule

it displays 4 separate luts in the circuit diagram(which I use to see
if I should bother testing, before I figured out sensitivity lists I
ended up with a latch, is there something else I should look at?)

and if I understand it correctly since I do not stipulate size the
value of seg is assigned to a variable width value, or is an unsized
value defaulted to something?

would this not mean that the value is then expanded when it is
assigned to seg? or more importantly, what would happen if the value
were too big for seg? since it was indicated that verilog truncates, I
would assume this to mean that if seg were assigned to lets say
10101010
it would become
0101010
 
lewisrjc@gmail.com wrote:
On Feb 12, 9:23 am, "John Penton" <john.pen...@arm.com> wrote:
John_H wrote:
hmm, interesting, the #'rv # is bits? didn't know that
and yes the values are incorrect, I had them written down but not with
me when I posted, the 6 bits was just a mistake

So when I see a ROM in my circuit design, that is the same as a lut?
when I used the following
I'm ASIC rather than FPGA, so someone else will need to help there.

and if I understand it correctly since I do not stipulate size the
value of seg is assigned to a variable width value, or is an unsized
value defaulted to something?
iirc:
- The width of a signal is defined in the declaration.
- When assigning, the value assigned is either truncated, or zero-padded (on
the left in both cases) to match the width of the signal being assigned.
- An unsized constant defaults to being at least 32 bits wide. Therefore
'd15 (or just 15) is at least 32'h0000_000f, if not wider.

So in the example:
seg = 7;
The 7 is unsized, and therefore treated as (at least) 32-bits wide
(32'h0000_0007). The assignment is to a 7-bit signal, so this gets
truncated to 7'b000_0111.

I think an unsized constant will almost always do what you expect (except
when the deadline is close). Personally, I always try to ensure that widths
explicitly match so that the behaviour is predictable. That's why I find it
difficult to recall what happens in mismatch cases.

would this not mean that the value is then expanded when it is
assigned to seg? or more importantly, what would happen if the value
were too big for seg? since it was indicated that verilog truncates, I
would assume this to mean that if seg were assigned to lets say
10101010
it would become
0101010
Yup.

--
John Penton, posting as an individual unless specifically indicated
otherwise.
 
On Feb 12, 11:13 pm, lewis...@gmail.com wrote:
hmm, interesting, the #'rv # is bits?
Yes, it is the width of the constant in bits.

I would expect your tools to warn you if you specified a width of 1
bit with a value requiring more than 1 bit.


and if I understand it correctly since I do not stipulate size the
value of seg is assigned to a variable width value, or is an unsized
value defaulted to something?
In practice, an unsized literal defaults to a size of 32 bits.

The language standard actually says it will be a size that is at least
32 bits. If you know where to look, it also says that that size is
the same as the size of an integer, which is also specified as being
at least 32 bits. In the SystemVerilog standard, an integer is
specified to be exactly 32 bits, which then makes unsized literals be
32 bits.

But that is just the starting width of the value. It may be extended
to a greater width depending on the context where it appears. And if
an expression is assigned to a narrower object, such as seg, it will
be truncated in the process.


or more importantly, what would happen if the value
were too big for seg? since it was indicated that verilog truncates, I
would assume this to mean that if seg were assigned to lets say
10101010
it would become
0101010
Yes.
 
On 13-02-2008, John Penton <john.penton@arm.com> wrote:
So when I see a ROM in my circuit design, that is the same as a lut?
when I used the following

I'm ASIC rather than FPGA, so someone else will need to help there.
If you need to design and operator with juste a read only memory. I can
program the rom i realize 'and' and use adress line as input pin to do the
and gate.

So the rom is juste write once... and the LUT (Look Up Table) is the same
on FPGA. Juste you can program it serveral time, when you load the
bitstream.

Thomas
 

Welcome to EDABoard.com

Sponsor

Back
Top