FPGA Central - World's 1st FPGA / CPLD Portal

FPGA Central

World's 1st FPGA Portal

 

Go Back   FPGA Groups > NewsGroup > Verilog

Verilog comp.lang.verilog newsgroup / usenet

Reply
 
LinkBack Thread Tools Display Modes
  #1 (permalink)  
Old 04-15-2007, 02:15 AM
Mahurshi Akilla
Guest
 
Posts: n/a
Default ALU Implementation

Hey Guys,

I am pasting my code for an ALU implementation based on my old
undergrad textbook. I took some suggestions from the folks here from
my older posts, so I am hoping this code should be a bit better than
the first one in style and taste :-)

Anyways, two questions:

1) Do you suggeston using assign statements to registers in always @*
blocks? If not, is there an alternative? I am trying to work this
out just like it is in the textbook and the module diagram doesn't
show a clock input.
2) Are there any suggestions to improvise on this piece of code?

`timescale 1ns / 1ps
module alu(
opcode,
op1,
op2,
alu_result,
zero);

parameter OW = 4; // opcode width
parameter BW = 32; // bus width

parameter op_AND = 4'b0000; //bitwise and
parameter op_OR = 4'b0001; //bitwise or
parameter op_ADD = 4'b0010;
parameter op_SUB = 4'b0110;
parameter op_SLT = 4'b0111;
parameter op_NOR = 4'b1100; //bitwise nor

input [OW-1:0] opcode;
input [BW-1:0] op1;
input [BW-1:0] op2;
output [BW-1:0] alu_result;
output zero;

reg [BW-1:0] alu_result;
reg zero;

always @*
begin
if (opcode == op_AND)
assign alu_result = op1 & op2;
else if (opcode == op_OR)
assign alu_result = op1 | op2;
else if (opcode == op_ADD)
assign alu_result = op1 + op2;
else if (opcode == op_SUB)
begin
assign alu_result = op1 - op2;
assign zero = (op1 == op2) ? 1 : 0;
end
else if (opcode == op_SLT)
assign alu_result = (op1 < op2) ? 1 : 0;
else if (opcode == op_NOR)
assign alu_result = ~(op1 | op2);
end
endmodule


Mahurshi Akilla

Reply With Quote
  #2 (permalink)  
Old 04-15-2007, 09:36 AM
Michael
Guest
 
Posts: n/a
Default Re: ALU Implementation

First of all, the general idea is right. But the implementation is
wrong

always @*
begin
alu_result = 0; // to eliminate latch
zero = 0; // to eliminate latch
if (opcode == op_AND)
alu_result = op1 & op2;
else if (opcode == op_OR)
alu_result = op1 | op2;
else if (opcode == op_ADD)
alu_result = op1 + op2;
else if (opcode == op_SUB)
begin
alu_result = op1 - op2;
zero = (op1 == op2) ? 1 : 0;
end
else if (opcode == op_SLT)
alu_result = (op1 < op2) ? 1 : 0;
else if (opcode == op_NOR)
alu_result = ~(op1 | op2);
end

Or even better:
always @*
begin
alu_result = 0; // to eliminate latch
zero = 0; // to eliminate latch
case(opcode)
op_AND: alu_result = op1 & op2;
op_OR: alu_result = op1 | op2;
op_ADD: alu_result = op1 + op2;
op_SUB: begin
alu_result = op1 - op2;
zero = (op1 == op2) ? 1 : 0;
end
op_SLT: alu_result = (op1 < op2) ? 1 : 0;
op_NOR: alu_result = ~(op1 | op2);
default: begin
$display("Opcode %4h is not valid", opcode);
end
endcase
end

Reply With Quote
  #3 (permalink)  
Old 04-15-2007, 04:29 PM
Mahurshi Akilla
Guest
 
Posts: n/a
Default Re: ALU Implementation

On Apr 15, 1:36 am, "Michael" <[email protected]> wrote:
> First of all, the general idea is right. But the implementation is
> wrong

The implementation is wrong? Were you kidding or were you
serious? :-) Sorry, I couldn't tell.

>
> always @*
> begin
> alu_result = 0; // to eliminate latch
> zero = 0; // to eliminate latch

Could you pl. explain what you mean by this? Was this done just to
eliminate the "red lines" from appearing at the beginning of the
simulation? If so, would it be okay to put these in an always @*
block? I thought you'd want it to initialize to 0 for once at the
beginning and not worry about it in the always @ blocks. I remember
that there's some syntax to have this be done only once at the
beginning of the simulation, but don't remember exactly what it is :-)

<...>

> Or even better:
> always @*
> begin
> alu_result = 0; // to eliminate latch
> zero = 0; // to eliminate latch
> case(opcode)
> op_AND: alu_result = op1 & op2;
> op_OR: alu_result = op1 | op2;
> op_ADD: alu_result = op1 + op2;
> op_SUB: begin
> alu_result = op1 - op2;
> zero = (op1 == op2) ? 1 : 0;
> end
> op_SLT: alu_result = (op1 < op2) ? 1 : 0;
> op_NOR: alu_result = ~(op1 | op2);
> default: begin
> $display("Opcode %4h is not valid", opcode);
> end
> endcase
> end


I really like these case statements. I totally forgot that they exist
in verilog too. I will switch to this style.

Another question: Is there a difference between saying "assign
alu_result = op1 - op2" and saying "alu_result = op1 - op2" ?

Mahurshi Akilla

Reply With Quote
  #4 (permalink)  
Old 04-15-2007, 04:59 PM
Jonathan Bromley
Guest
 
Posts: n/a
Default Re: ALU Implementation

On 15 Apr 2007 08:29:46 -0700, "Mahurshi Akilla"
<m[email protected]> wrote:

>Another question: Is there a difference between saying "assign
>alu_result = op1 - op2" and saying "alu_result = op1 - op2" ?


YES!!!!!

If you write "assign something = expression;" inside a
procedural block (always block) in a design, you are
almost certainly doing the wrong thing. Who allowed
you to get away with this in your original coursework?
If it's from a textbook, tell me the name of the book
so I can tell my students that they should burn it :-)

The assign keyword does two wildly different things in
Verilog. You can use it *inside* an always or initial
block, as in your ALU. This is bad - I'll explain why
later. The common, sensible, OK-for-design use is
to put it at the top level of a module, outside any
always blocks:

module adder ( input [7:0] a,b, output [8:0] sum );
assign sum = a + b;
endmodule

In this case your "assign"...
* is driving a net (wire) - "sum" in this example;
* represents a driver (gate output) permanently
connected to the driven net;
* automatically updates whenever the expresson (a+b)
changes;
* is a completely sensible representation of a piece
of combinational logic.

There is, of course, an alternative. You could
write the same thing in an always block:

module adder ( input [7:0] a,b, output reg [8:0] sum );
always @(a or b) begin
sum = a + b;
end
endmodule

Note, now, that "sum" must be a variable - hence the "reg"
declaration in the port list. Once again, this is a
good and useful synthesisable description of an adder.

But your code contained stuff like this...

always @...
assign sum = a + b;

OUCH! This is a COMPLETELY different form of "assign".
It's a "procedural continuous assignment". It says that
when you execute that line of code, Verilog sets up a
process that monitors a and b, and whenever they change
it will calculate a+b and write that value to "sum".
This procedural continuous assignment will remain active
until you execute a different "assign sum = ...".

Your code, then, was effectively asking Verilog to switch-in
a completely new piece of hardware each time the opcode
changed! Most synthesis tools will not process that code.

Procedural continuous assigns can be useful for modelling
certain kinds of asynchronous load operation, but in my
opinion you should NEVER use them in synthesisable design.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
[email protected]
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Reply With Quote
  #5 (permalink)  
Old 04-16-2007, 02:17 AM
Mahurshi Akilla
Guest
 
Posts: n/a
Default Re: ALU Implementation

Ahh.. thanks for the detailed explanation. Now, I understand it much
better. And no, it wasn't my textbook. It was just me fooling around
with behavioral verilog by myself for giggles. When I was in school,
my prof. made us write "structural" verilog (basically the "netlist"),
which I thought was hopeless. I guess his intention was to make us
aware of the underlying complexity in logic, but the result was that
none of us learned behavioral verilog. Anyways.. but that is school
and the profs. have their own ways. Now that I have graduated ... I
am trying to home school myself. :-)

Also.. could you explain me why we have the below two lines in the
always @ block? If the intention was to initialize to 0, why was it
placed inside the always @ block?

alu_result = 0; // to eliminate latch
zero = 0; // to eliminate latch

Thanks,

Mahurshi Akilla

On Apr 15, 8:59 am, Jonathan Bromley <[email protected]>
wrote:
> On 15 Apr 2007 08:29:46 -0700, "Mahurshi Akilla"
>
> <[email protected]> wrote:
> >Another question: Is there a difference between saying "assign
> >alu_result = op1 - op2" and saying "alu_result = op1 - op2" ?

>
> YES!!!!!
>
> If you write "assign something = expression;" inside a
> procedural block (always block) in a design, you are
> almost certainly doing the wrong thing. Who allowed
> you to get away with this in your original coursework?
> If it's from a textbook, tell me the name of the book
> so I can tell my students that they should burn it :-)
>
> The assign keyword does two wildly different things in
> Verilog. You can use it *inside* an always or initial
> block, as in your ALU. This is bad - I'll explain why
> later. The common, sensible, OK-for-design use is
> to put it at the top level of a module, outside any
> always blocks:
>
> module adder ( input [7:0] a,b, output [8:0] sum );
> assign sum = a + b;
> endmodule
>
> In this case your "assign"...
> * is driving a net (wire) - "sum" in this example;
> * represents a driver (gate output) permanently
> connected to the driven net;
> * automatically updates whenever the expresson (a+b)
> changes;
> * is a completely sensible representation of a piece
> of combinational logic.
>
> There is, of course, an alternative. You could
> write the same thing in an always block:
>
> module adder ( input [7:0] a,b, output reg [8:0] sum );
> always @(a or b) begin
> sum = a + b;
> end
> endmodule
>
> Note, now, that "sum" must be a variable - hence the "reg"
> declaration in the port list. Once again, this is a
> good and useful synthesisable description of an adder.
>
> But your code contained stuff like this...
>
> always @...
> assign sum = a + b;
>
> OUCH! This is a COMPLETELY different form of "assign".
> It's a "procedural continuous assignment". It says that
> when you execute that line of code, Verilog sets up a
> process that monitors a and b, and whenever they change
> it will calculate a+b and write that value to "sum".
> This procedural continuous assignment will remain active
> until you execute a different "assign sum = ...".
>
> Your code, then, was effectively asking Verilog to switch-in
> a completely new piece of hardware each time the opcode
> changed! Most synthesis tools will not process that code.
>
> Procedural continuous assigns can be useful for modelling
> certain kinds of asynchronous load operation, but in my
> opinion you should NEVER use them in synthesisable design.
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> [email protected]://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.



Reply With Quote
  #6 (permalink)  
Old 04-17-2007, 01:15 AM
Jonathan Bromley
Guest
 
Posts: n/a
Default Re: ALU Implementation

On 15 Apr 2007 18:17:30 -0700, "Mahurshi Akilla"
<[email protected]> wrote:

>my prof. made us write "structural" verilog


It happens.

[...]
>Also.. could you explain me why we have the below two lines in the
>always @ block? If the intention was to initialize to 0, why was it
>placed inside the always @ block?
>
> alu_result = 0; // to eliminate latch
> zero = 0; // to eliminate latch


This sort of idiom is not an initialization; it's a default value.

always @* begin
special_case = 0;
if (incredibly_complicated_condition)
special_case = 1;
if (different_incredibly_complicated_condition)
special_case = 1;
end

Every time an input changes, the always block executes again.
If there is no other assignment to "special_case", it takes
its default value of 0; but if there is a second assignment
to it, the later assignment overwrites the earlier default.
Because it would be so very tiresome to determine the "else"
condition, the default assignment is very useful.

Here's another, more realistic example:

always @* begin
overflow = 0;
result = 0;
case (opcode)
op_NOP:
; // do nothing at all
op_ADD:
begin
result = opA + opB;
if ((result[7] != opA[7]) && (opA[7] == opB[7]))
overflow = 1;
end
op_XOR:
result = opA ^ opB;
endcase
end

In this situation we get several benefits from the
default assignments to "overflow" and "result":
- in the case statement, a branch that doesn't need to
act on "overflow" need not write to it
- the case statement is incomplete, but that doesn't matter
because we always have an assignment to every output

If we DON'T assign to every output, then the always block
will create a transparent latch on that output so that it
holds its value when not updated. This is, mostly, bad.

If you don't care about the value of "overflow" in the
cases where it's not specified, you may get better
(more compact) logic by making the default assignment
put "X" in it:

always @* begin
overflow = 1'bx;
result = 8'bx;
...

Synthesis tools will treat the X values as "don't care",
allowing them to create simpler logic. Simulation will
show you red ink on the waveforms if the X condition
occurs, helping you to find possible errors.

Hope this helps
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
[email protected]
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Reply With Quote
  #7 (permalink)  
Old 04-17-2007, 02:28 AM
alan
Guest
 
Posts: n/a
Default Re: ALU Implementation

On Apr 16, 9:17 am, "Mahurshi Akilla" <[email protected]> wrote:
> Ahh.. thanks for the detailed explanation. Now, I understand it much
> better. And no, it wasn't my textbook. It was just me fooling around
> with behavioral verilog by myself for giggles. When I was in school,
> my prof. made us write "structural" verilog (basically the "netlist"),

IMO this is best done in a graphical schematic rather than in text -
what I do is write a little conceptual layout using text graphics in a
comment in my top blocks, then just wire the blocks together.

> which I thought was hopeless. I guess his intention was to make us
> aware of the underlying complexity in logic, but the result was that
> none of us learned behavioral verilog.

Should have taught you barrel shifter implementations instead, which
shows how, yes, logic is complicated, and no, once you *get* it, you
just think "kewl, that was so simple, why didn't I think of that!"

>
> Also.. could you explain me why we have the below two lines in the
> always @ block? If the intention was to initialize to 0, why was it
> placed inside the always @ block?
>
> alu_result = 0; // to eliminate latch
> zero = 0; // to eliminate latch
>

Here's a different attempt at explaining:

Latches are EVIL (unless you know what you're doing, in which case you
should be able to judge when to use latches).
Latches must be eliminated!
To eliminate latches, the previous value of the register should never
be remembered.
....so, to eliminate latches, you have to *erase* the previous value.

An alternative (which I prefer) is to use the default branch:
default: begin
alu_result = 0; zero = 0; end endcase end

Also, as suggested, using x (usually 'bx, if you have a variable-width
design and are too lazy to do something like {width{1'bx}}).

Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
register bank implementation [email protected] Verilog 3 01-09-2007 02:35 PM
Shift register implementation [email protected] Verilog 3 05-26-2006 03:47 AM
Bit Error Rate ..Implementation... Debashish Verilog 0 09-28-2003 06:28 AM
Booth's Algorith Implementation Atif Verilog 2 07-27-2003 10:22 PM
UART Implementation Anand P Paralkar Verilog 2 07-07-2003 06:53 AM


All times are GMT +1. The time now is 02:36 AM.


Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0
Copyright 2008 @ FPGA Central. All rights reserved