Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

my first Verilog program

183 views
Skip to first unread message

Frank Buss

unread,
Jul 18, 2004, 4:35:01 AM7/18/04
to
I'm learning Verilog and have some questions, because I have no
experience with HDL and not much with hardware design. Below is my
first Verilog program, which works with the nice Spartan3 starter
kit from Xilinx. Perhaps you can take a look at it and give me some
hints how I can improve it and where are possible bugs.

Some specific questions:

- how can I latch the vga output signals on falling clock edge without
another reg-set? I assume somthing with "wire", but I don't know

- the state machine for the VGA signal generation looks like it can be
simplified

- how can I do "meta"-programming? For example the handling for
led0Power to led7Power is all the same, so I need something like a loop,
but how do I declare the variables as arrays and access them?


module test(
clk, led, segment, digit,
VGA_Red, VGA_Green, VGA_Blue, VGA_HSYNCH_N, VGA_VSYNCH_N);

input clk;

output [7:0] led;
output [7:0] segment;
output [3:0] digit;

assign segment[0] = 0;
assign segment[1] = 0;
assign segment[2] = 0;
assign segment[3] = 0;
assign segment[4] = 0;
assign segment[5] = 0;
assign segment[6] = 0;
assign segment[7] = 0;
assign digit[0] = 1;
assign digit[1] = 1;
assign digit[2] = 1;
assign digit[3] = 1;

//
// VGA video pattern generator
//

/* VGA timings:
clocks per line:
1. HSync low pulse for 96 clocks
2. back porch for 48 clocks
3. data for 640 clocks
4. front porch for 16 clocks

VSync timing per picture (800 clocks = 1 line):
1. VSync low pulse for 2 lines
2. back porch for 29 lines
3. data for 480 lines
4. front porch for 10 lines
*/

`define LINE_HSYNC_LOW 0
`define LINE_BACK_PORCH 1
`define LINE_DATA 2
`define LINE_FRONT_PORCH 3

`define IMAGE_VSYNC_LOW 0
`define IMAGE_BACK_PORCH 1
`define IMAGE_DATA 2
`define IMAGE_FRONT_PORCH 3

output VGA_Red;
output VGA_Green;
output VGA_Blue;
output VGA_HSYNCH_N;
output VGA_VSYNCH_N;

reg rVGA_Red = 0;
reg rVGA_Green = 0;
reg rVGA_Blue = 0;
reg rVGA_HSYNCH_N = 0;
reg rVGA_VSYNCH_N = 0;

reg latchVGA_Red = 0;
reg latchVGA_Green = 0;
reg latchVGA_Blue = 0;
reg latchVGA_HSYNCH_N = 0;
reg latchVGA_VSYNCH_N = 0;

assign VGA_Red = latchVGA_Red;
assign VGA_Green = latchVGA_Green;
assign VGA_Blue = latchVGA_Blue;
assign VGA_HSYNCH_N = latchVGA_HSYNCH_N;
assign VGA_VSYNCH_N = latchVGA_VSYNCH_N;

reg [2:0] lineState = 0;
reg [2:0] imageState = 0;
reg [10:0] pixelCounter = 0;
reg [10:0] lineCounter = 0;
reg devide2 = 0;

always @(posedge clk) begin
devide2 <= ~devide2;
if (devide2) begin
// check line
case (lineState)
`LINE_HSYNC_LOW: begin
if (pixelCounter == 96) begin
pixelCounter <= 0;
lineState = `LINE_BACK_PORCH;
rVGA_HSYNCH_N <= 1;
end else pixelCounter <= pixelCounter + 1;
end
`LINE_BACK_PORCH: begin
if (pixelCounter == 48) begin
pixelCounter <= 0;
lineState = `LINE_DATA;
end else pixelCounter <= pixelCounter + 1;
end
`LINE_DATA: begin
if (lineCounter < 480 && imageState == `IMAGE_DATA) begin
rVGA_Red <= pixelCounter[4];
rVGA_Green <= pixelCounter[5];
rVGA_Blue <= pixelCounter[6];
end else begin
rVGA_Red <= 0;
rVGA_Green <= 0;
rVGA_Blue <= 0;
end
if (pixelCounter == 640) begin
pixelCounter <= 0;
lineState = `LINE_FRONT_PORCH;
end else pixelCounter <= pixelCounter + 1;
end
`LINE_FRONT_PORCH: begin
if (pixelCounter == 16) begin
pixelCounter <= 0;
lineState = `LINE_HSYNC_LOW;
rVGA_HSYNCH_N <= 0;

// check image
case (imageState)
`IMAGE_VSYNC_LOW: begin
if (lineCounter == 2) begin
lineCounter <= 0;
imageState = `IMAGE_BACK_PORCH;
rVGA_VSYNCH_N <= 1;
end else lineCounter <= lineCounter + 1;
end
`IMAGE_BACK_PORCH: begin
if (lineCounter == 29) begin
lineCounter <= 0;
imageState = `IMAGE_DATA;
end else lineCounter <= lineCounter + 1;
end
`IMAGE_DATA: begin
if (lineCounter == 480) begin
lineCounter <= 0;
imageState = `IMAGE_FRONT_PORCH;
end else lineCounter <= lineCounter + 1;
end
`IMAGE_FRONT_PORCH: begin
if (lineCounter == 16) begin
lineCounter <= 0;
imageState = `IMAGE_VSYNC_LOW;
rVGA_VSYNCH_N <= 0;
end else lineCounter <= lineCounter + 1;
end
default:
imageState = `IMAGE_VSYNC_LOW;
endcase
end else pixelCounter <= pixelCounter + 1;
end
default:
lineState = `LINE_HSYNC_LOW;
endcase
end
end

always @(negedge clk) begin
latchVGA_Red <= rVGA_Red;
latchVGA_Green <= rVGA_Green;
latchVGA_Blue <= rVGA_Blue;
latchVGA_HSYNCH_N <= rVGA_HSYNCH_N;
latchVGA_VSYNCH_N <= rVGA_VSYNCH_N;
end


//
// knight rider like LED scroll
//
reg [16:0] devide2500 = 0; // 50 MHz / 1000 = 50 kHz
reg [16:0] devideLed = 0;
reg [16:0] scrollLedCounter = 0;
reg [4:0] scrollLed = 0;

reg led0 = 0;
assign led[0] = led0;
reg [7:0] led0Power = 0;
reg [7:0] led0Counter = 0;

reg led1 = 0;
assign led[1] = led1;
reg [7:0] led1Power = 0;
reg [7:0] led1Counter = 0;

reg led2 = 0;
assign led[2] = led2;
reg [7:0] led2Power = 0;
reg [7:0] led2Counter = 0;

reg led3 = 0;
assign led[3] = led3;
reg [7:0] led3Power = 0;
reg [7:0] led3Counter = 0;

reg led4 = 0;
assign led[4] = led4;
reg [7:0] led4Power = 0;
reg [7:0] led4Counter = 0;

reg led5 = 0;
assign led[5] = led5;
reg [7:0] led5Power = 0;
reg [7:0] led5Counter = 0;

reg led6 = 0;
assign led[6] = led6;
reg [7:0] led6Power = 0;
reg [7:0] led6Counter = 0;

reg led7 = 0;
assign led[7] = led7;
reg [7:0] led7Power = 0;
reg [7:0] led7Counter = 0;

always @(posedge clk) begin
if (devide2500 == 2500) begin
devide2500 = 0;

if (led0Power > led0Counter) led0 <= 1; else led0 <= 0;
if (led0Counter == 255) led0Counter <= 0; else led0Counter <= led0Counter + 1;

if (led1Power > led1Counter) led1 <= 1; else led1 <= 0;
if (led1Counter == 255) led1Counter <= 0; else led1Counter <= led1Counter + 1;

if (led2Power > led2Counter) led2 <= 1; else led2 <= 0;
if (led2Counter == 255) led2Counter <= 0; else led2Counter <= led2Counter + 1;

if (led3Power > led3Counter) led3 <= 1; else led3 <= 0;
if (led3Counter == 255) led3Counter <= 0; else led3Counter <= led3Counter + 1;

if (led4Power > led4Counter) led4 <= 1; else led4 <= 0;
if (led4Counter == 255) led4Counter <= 0; else led4Counter <= led4Counter + 1;

if (led5Power > led5Counter) led5 <= 1; else led5 <= 0;
if (led5Counter == 255) led5Counter <= 0; else led5Counter <= led5Counter + 1;

if (led6Power > led6Counter) led6 <= 1; else led6 <= 0;
if (led6Counter == 255) led6Counter <= 0; else led6Counter <= led6Counter + 1;

if (led7Power > led7Counter) led7 <= 1; else led7 <= 0;
if (led7Counter == 255) led7Counter <= 0; else led7Counter <= led7Counter + 1;

if (devideLed == 60) begin
devideLed <= 0;
if (led0Power > 0) led0Power <= led0Power * 255 / 256;
if (led1Power > 0) led1Power <= led1Power * 255 / 256;
if (led2Power > 0) led2Power <= led2Power * 255 / 256;
if (led3Power > 0) led3Power <= led3Power * 255 / 256;
if (led4Power > 0) led4Power <= led4Power * 255 / 256;
if (led5Power > 0) led5Power <= led5Power * 255 / 256;
if (led6Power > 0) led6Power <= led6Power * 255 / 256;
if (led7Power > 0) led7Power <= led7Power * 255 / 256;

if (scrollLedCounter == 60) begin
scrollLedCounter <= 0;
scrollLed <= scrollLed + 1;
case (scrollLed)
0: led0Power <= 255;
1: led1Power <= 255;
2: led2Power <= 255;
3: led3Power <= 255;
4: led4Power <= 255;
5: led5Power <= 255;
6: led6Power <= 255;
7: led7Power <= 255;
8: led7Power <= 255;
9: led6Power <= 255;
10: led5Power <= 255;
11: led4Power <= 255;
12: led3Power <= 255;
13: led2Power <= 255;
14: led1Power <= 255;
15: begin led0Power <= 255; scrollLed <= 0; end
endcase
end else begin
scrollLedCounter <= scrollLedCounter + 1;
end

end else begin
devideLed <= devideLed + 1;

end

end else devide2500 = devide2500 + 1;
end

endmodule


--
Frank Buß, f...@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de

Swapnajit Mittra

unread,
Jul 19, 2004, 4:23:16 PM7/19/04
to
Frank Buss <f...@frank-buss.de> wrote in message news:<cddcnk$kk0$1...@newsreader2.netcologne.de>...

> I'm learning Verilog and have some questions, because I have no
> experience with HDL and not much with hardware design. Below is my
> first Verilog program, which works with the nice Spartan3 starter
> kit from Xilinx. Perhaps you can take a look at it and give me some
> hints how I can improve it and where are possible bugs.

Frank,

Welcome to Verilog and hardware design. See below for answers
to your questions.

>
> Some specific questions:
>
> - how can I latch the vga output signals on falling clock edge without

> another reg-set? I assume somthing with "wire", but I don't know.

Probably I do not understand your question but it seems to me you
are already doing that.

always @(negedge clk) begin
latchVGA_Red <= rVGA_Red;
latchVGA_Green <= rVGA_Green;
latchVGA_Blue <= rVGA_Blue;
latchVGA_HSYNCH_N <= rVGA_HSYNCH_N;
latchVGA_VSYNCH_N <= rVGA_VSYNCH_N;
end

>

> - the state machine for the VGA signal generation looks like it can be

> simplified?

This is a holy area that has many sects with various ideas
(and ideologies). Here is mine. In general, I tend to divide
a module in three parts:

1. A current state generator for the state machine:

This is identical in all designs.

always @(posedge clk)
if (reset) // synchronous reset
current_state <= IDLE;
else
current_satet <= next_state;

I would suggest, use a one hot state machine that will
reduce your coding effort (you can use
'if (current_state[STATEn_BIT])', rather than
'if (current_state == STATEn)'), if not help you meet
your timing goal.

2. A *combinatorial* state machine:

This is the logic that will assign the next_state
from current states and the inputs AND NOTHING ELSE.
Typically, a state inside the state machine will look
like:

always @* begin
next_state = current_state;
...
case (1'b1)
current_state[STATEn_BIT]: begin
if (...)
next_state = STATEm;
else
next_state = STATEp;
end
...
endcase

3. All other flops and combinatorial logic:

This is where rest of the logic goes. Organize the logic
according to their functions. Keep the logic that are related
in the same palce. This will help you debug later.

>
> - how can I do "meta"-programming? For example the handling for
> led0Power to led7Power is all the same, so I need something like a loop,
> but how do I declare the variables as arrays and access them?

If the behavior for all ledxPower are identical *all the time*
(I did not explore your logic enough to see if they are), then
you do not need to write 8 of them - just define one and then
fan the output out.

If they are logically identical with different inputs, then
define one module that has the logic for one of the ledxPower
and then instatiates it 8 times.

You might want to take a look at the following site for
some example design:

http://pancham.sourceforge.com

Hope this helps.
- Swapnajit.

--
SystemVerilog, Verilog, PLI and all the good stuffs
Project VeriPage::: http://www.project-veripage.com

Blackie Beard

unread,
Jul 20, 2004, 1:16:05 AM7/20/04
to
It would be a good idea to use an asynchronous reset in
the design. Initial conditions and all that.

always @(posedge clk or negedge rstn)
if(~rstn)
my_reg <= 1'b0;
else
my_reg <= my_nextreg_wire_value;

If you only latch on posedge of clk, your design will
be more portable later. At least that's the way it
was when I was learning. Don't know about nowadays.

BB


"Frank Buss" <f...@frank-buss.de> wrote in message
news:cddcnk$kk0$1...@newsreader2.netcologne.de...

Frank Buss

unread,
Jul 24, 2004, 5:39:42 AM7/24/04
to
mit...@juno.com (Swapnajit Mittra) wrote:

> 2. A *combinatorial* state machine:
>
> This is the logic that will assign the next_state
> from current states and the inputs AND NOTHING ELSE.
> Typically, a state inside the state machine will look
> like:
>
> always @* begin
> next_state = current_state;
> ...
> case (1'b1)
> current_state[STATEn_BIT]: begin
> if (...)
> next_state = STATEm;
> else
> next_state = STATEp;
> end
> ...
> endcase

this looks dangerous to me, because I don't know at which time the state
changes.

>> - how can I do "meta"-programming? For example the handling for
>> led0Power to led7Power is all the same, so I need something like a
>> loop, but how do I declare the variables as arrays and access them?
>
> If the behavior for all ledxPower are identical *all the time*
> (I did not explore your logic enough to see if they are), then
> you do not need to write 8 of them - just define one and then
> fan the output out.
>
> If they are logically identical with different inputs, then
> define one module that has the logic for one of the ledxPower
> and then instatiates it 8 times.

Do you have an example how to do it? I tried something like this:

for (i = 0; i < 8; i = i+1) begin
foo[i*8+7:i*8] <= (foo[i*8+7:i*8] >> (i*8)) + 1;
end

and expected that this is generated:

foo[0*8+7:0*8] <= (foo[0*8+7:0*8] >> (0*8)) + 1;
foo[1*8+7:1*8] <= (foo[1*8+7:1*8] >> (1*8)) + 1;
foo[2*8+7:2*8] <= (foo[2*8+7:2*8] >> (2*8)) + 1;
...

For this module:

module test(clk, led);


input clk;
output [7:0] led;

reg [7:0] rLed = 0;
assign led = rLed;
reg [7:0] i = 0;
always @(posedge clk) begin
for (i = 0; i < 4; i = i + 1) begin
rLed = rLed + i;
end
end
endmodule

it looks like it works like I expect it, because this schematic is
generated:

http://www.frank-buss.de/tmp/for.gif

> You might want to take a look at the following site for
> some example design:
>
> http://pancham.sourceforge.com

I've found another examples at www.opencores.com, but I would like to
have a reference and some tutorials. The FAQ at
http://www.faqs.org/faqs/verilog-faq/ is a bit outdated, I plan to buy
some books. Looks like this is a good one:

http://www.amazon.de/exec/obidos/ASIN/1402070896

And for comparing with VHDL perhaps this one:

http://www.amazon.de/exec/obidos/ASIN/0471899720/

Perhaps someone can comment these books or suggest other books. Some
online resources would be useful, too.

Swapnajit Mittra

unread,
Aug 7, 2004, 1:56:19 PM8/7/04
to
Frank Buss <f...@frank-buss.de> wrote in message news:<cdtaou$fe5$1...@newsreader2.netcologne.de>...

> mit...@juno.com (Swapnajit Mittra) wrote:
>
> > 2. A *combinatorial* state machine:
> >
> > This is the logic that will assign the next_state
> > from current states and the inputs AND NOTHING ELSE.
> > Typically, a state inside the state machine will look
> > like:
> >
> > always @* begin
> > next_state = current_state;
> > ...
> > case (1'b1)
> > current_state[STATEn_BIT]: begin
> > if (...)
> > next_state = STATEm;
> > else
> > next_state = STATEp;
> > end
> > ...
> > endcase
>
> this looks dangerous to me, because I don't know at which time the state
> changes.
>

No, this is not at all dangerous - your state (i.e. current_state)
only changes at the posedge of the clock, as shown in my
previous code:

always @(posedge clk) // decide over synchronous or asynch reset
if (reset)
current_state <=IDLE;
else
current_state <= next_state;

What changes in between clocks is your next_state based on how
the input changes. You do not need to know when it does, as
long as all changes take place before the next posedge of the
clock.

- Swapnajit

--
Project VeriPage: SystemVerilog, Verilog PLI, DPI and all the good stuffs.
http://www.project-veripage.com

0 new messages