# help with code for a newbie...:)

Status
Not open for further replies.

#### toffee_pie

##### Newbie level 6
greetings all,

can anyone with verilog skills help me implement this ALU, I wish to firstly get the basic operations functioning before i move onto the more difficult tasks.

It wont compile, I am getting an error with the endmodule part? also do I need another reg to store the overflow bit and work out signed and unsigned outputs?

// VERILOG CODE

// 'timescale 10ns

module ALU (a,b,Cin,Op,clk,resetb,C[s+15:0],s,ov)

output signed C[s + 15:0] ; // 2's compliment signed 16 bit output word

output ov; // The result of addition or subtraction is
// supposed to fit
// within the significant bits used to represent the numbers.
// If ‘n’ bits are used to represent signed numbers
// in 2’s complement
// scheme, then the result must be in the range
// –2n-1 to 2n-1-1.
// If the result does not fit in this range, then an arithmetic
// overflow has occurred, this used for signed operations.

input clk,resetb; // system clock @ 100Mhz , synchronous
// system reset active low
input [2:0] Op; // assigns ALU one of its 8 operand Instruction
input [15:0] a,b; // unsigned 16 bit input operands to ALU
input Cin,s ; // Carry in, Sum In

// internal nodes

wire [15:0] a,b;
reg signed [15:0] c; // output reg
reg signed s;
reg signed ov;

parameter WIDTH = 'd16;

parameter ADD_AB = 3'b000; // addition -> c = a + b
parameter SUB_AB = 3'b001; // subtraction -> c = a - b
parameter MUL_AB = 3'b010; // multiplication -> c = a * b
parameter AND_AB = 3'b011; // and -> c = a & b
parameter OR_AB = 3'b100; // or -> c = a | b
parameter XOR_AB = 3'b101; // xor -> c = a ^ b
parameter SHIFT_LEFT_A = 3'b110; // shift left -> c = a >> 1
parameter SHIFT_RIGHT_A = 3'b111; // shift right -> c = b >> 1

always @ (a or b or op) begin

// Lets do Arithmetic operations

begin

if (op[2:1] == 2'b00) begin

case (op[2:0])

3'b000:c = a + b ; // addition
3'b001:c = a - b ; // subtraction
//3'b010:c = a * b ; //
default:c = 16'bx;

endcase

//overflow = c[15]^c[14];

end

// Lets do Logical operations

else if (op[2:1] == 2'b01) begin

case (op[2:0])

3'b011:c = a & b ; // logical and
3'b100:c = a | b ; // logical or
3'b111:c = a ^ b; // logical exor
default:c = 16'bx;

endcase

endmodule

#### laserbeak43

##### Member level 1
sorry i didn't look at the FULL code yet, but i did notice a few things in the beginning. I'm a noob too, so I'm not sure how much help i can be, but:
1) output overflow isn't in your list of IO in the module's "sensitivity list"(sorry i forget the name and i want to say parameter list as if it were C).
2)IIRC, a 16-bit SIGNED input would be something like
Code:
input [12:-3] a,b;
3) i also think that you would need some extra room for carry, like
Code:
 input [13:-3] a,b;
so that you can say
Code:
 (a[13]) ? carry_flag_set : carry_flag_clear;
I hope you get what i'm saying. And I hope im not confusing you.
Good luck.

#### toffee_pie

##### Newbie level 6
Hi ya,

thanks for the help, yes I understand. I was wondering about the extra 'bit' for the carry operation...:|

the two inputs a,b are 'unsigned'

the output, c is 'signed'. [s + 15:0]

does that mean the output is 17 bits?

I have included the ov term for overflow in the declarations.

I would like to get the basics going before I worry about the shift operations and the multiply operand, which needs tweaking or 'chopping' as the output answer may exceed 16 bits.

#### laserbeak43

##### Member level 1
toffee_pie said:
the output, c is 'signed'. [s + 15:0]
does that mean the output is 17 bits?
If s represents 1 bit then yes i'm not sure what 's'
means or if it's syntactically correct, verilog-wise.
I've been meaning to learn how to write an ALU myself. I could use this as an
excuse to read up on signed numbers in verilog

hmm check out page 190 section 7.3.3 can it be that easy??

#### toffee_pie

##### Newbie level 6
s is to signify a signed o/p i presume...

in verilog all declarations are unsigned for default, so you need to tell if they are signed,

so i had to say signed for the output to let it know.

how I deal with regs and storage is another thing, and If i can implement this in one always loop....

#### laserbeak43

##### Member level 1
my thing is i don't see any parameter declared named 's' or know of any keyword called 's' in verilog.

#### toffee_pie

##### Newbie level 6
ha,

thats correct...!

c[s + 15:0] is the output

where s is the 2 signed compliment output word

so that can be amended to my code.

I am not sure what I do with this S, and how I declare it ?

its a > 'reg signed s' I would think ?

1 bit word? is this declared just as in output reg..?

#### laserbeak43

##### Member level 1
i'm sorry i'm not sure i understand your question.
are you saying you want a sign bit?

#### toffee_pie

##### Newbie level 6
I have attached a block diag of my design.

I have also used a updated block of the final product as the original misses out on carry inputs etc.

I changed my code also, slightly regarding the port declarations.

#### laserbeak43

##### Member level 1
hello, haven't had a chance to look at your code yet(you might have noticed that i'm steadily working on something posted in these forums for myself.)
what I DID do though, was look for some info for my project and stumble upon this:
a tuto for a signed ALU
good luck

#### toffee_pie

##### Newbie level 6
well,

I have been over complicating my code way too much. I dont need any carry, sum flags or regs.

Making it too complicated for my own sake. The output is a 16 bit word, plus 1 bit for the 2s compliment bit.

[msb].................[lsb]

#### dcreddy1980

##### Full Member level 5
did u solve your problem, if not let me know.

#### toffee_pie

##### Newbie level 6
hello

Yes, I got my code working. well i got it synthised on xilinx ise

I need to create a test bench for it now and having problems.

an someone help me with the test bench for this please? I ran it on multi sim and got an error to do with the c bit being the incorrect size and a few other things mentioning incorrect sizes also.

I have two 'c' variables in my code, one is c_nx= the output of the alu, which is sent to the ff to be timed, the output of this is the actual port output 'c'

so c_nx is not declared as an output.

anyone?

module ALU(a,b,op,clk,resetb,c);

parameter s = 'd1;
output signed[s+15:0]c;
reg signed[s+15:0]c;

input [15:0]a,b;
input [2:0]op;
input resetb;
input clk;

reg signed [s+15:0]c_nx;
//output signed [s+15:0]c_nx;

// port declarations

parameter WIDTH = 'd16;

parameter ADD_AB = 3'b000; // addition -> c = a + b
parameter SUB_AB = 3'b001; // subtraction -> c = a - b
parameter MUL_AB = 3'b010; // multiplication -> c = a * b
parameter AND_AB = 3'b011; // and -> c = a & b
parameter OR_AB = 3'b100; // or -> c = a | b
parameter XOR_AB = 3'b101; // xor -> c = a ^ b
parameter SHIFT_LEFT_A = 3'b110; // shift left -> c = a >> 1
parameter SHIFT_RIGHT_B = 3'b111; // shift right -> c = b >> 1

always @(a or b or op)

case (op)

ADD_AB: c_nx = a + b;
SUB_AB: c_nx = a - b;
MUL_AB: c_nx = a * b;
AND_AB: c_nx = a & b;
OR_AB: c_nx = a | b;
XOR_AB: c_nx = a ^ b;
SHIFT_LEFT_A: c_nx = a >> 1;
SHIFT_RIGHT_B: c_nx = b >> 1;

endcase

always @ (posedge clk)

if (~resetb)

c <= 0;

else

c <= c_nx;

endmodule

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

module ALU_tb ( // no ports; this is a testbench
);

parameter PRD = 10; // ns - according to left-hand argument to the timescale directive
parameter SIMLEN = 100; // clks - number of clks for which to run the simulation

parameter s = 'd1;
parameter WIDTH = 'd16;

// inputs to the DUT are reg types

reg clk,resetb;
reg [15:0]tb_a,tb_b,true_output;
reg [2:0]tb_op;

// outputs from the DUT are wire type

wire signed[15:0]tb_c;

integer i,j,outfile,pat_error;

// instantiate the device under test

ALU my_alu_testbench(.c(tb_c),.a(tb_a),.b(tb_b),.op(tb_op),.resetb(resetb),.clk(clk));

always #5 clk = ~clk; // every 5 nano seconds invert, create period 10ns

initial

begin

$monitor (tb_a,tb_b,tb_c); outfile =$fopen("tb_c.txt");

if(!outfile) begin

$display("can not write file!");$finish;

end

pat_error= 0;

resetb= 1'b1;clk=1'b1;a=0;b=0;op=0;

#2 resetb = 1'b0;

#2 resetb = 1'b1;

op = 3'b000;

for (i=0;i<65536;i=i+1)

begin

for (j=0;j<65536;j=j+1)

begin

a = i[15:0];b=j[15:0];

#10 true_output = a + b;

if(c!==true_output[15:0])

begin

\$fdisplay (outfile, "%b + %b should be %b. but your output is %b." , a,b,true_output,c);

pat_error= pat_error+1;

end
end
end

end

endmodule

Status
Not open for further replies.