Help with Verilog : Cordic Code Posted.

D

dash82

Guest
Hi All,

I needed some help with Verilog Cordic code. The code posted below is
open source and protected by GNU GPL. I do understand the Cordic Logic
(http://my.execpc.com/~geezer/embed/cordic.htm ), but was having some
trouble with the below mentioned code (at the end of this message). My
questions start with Q --.

In cordic.v:
------------------
16 bit vector xi, yi and zi are passed as input. Then cordic
constants are pre-defined.

Q -- Not sure what "wire [bitwidth+1:0] xi_ext =
{{2{xi[bitwidth-1]}},xi};" statement is doing. Is it concatenation and
assignment?

Now, @posedge clock, if reset is set, then x0, y0, z0 is initialized
to '0'. Next, when enable is set, z0 is assigned all bits except the
first two. And the first 2 bits are used for the case statement.

Q -- My understanding is that in this case statements, the first 2
bits are used to determine the quadrants and accordingly adjust the
quadrant (angle) for xi_ext and yi_ext by 90 or 180 or 270 or 360
degree.. But I am not sure. Any comments ?

Then many instances of cordic_stage are defined and they are passed
input values x0, y0, z0 and constants c00 etc.

Q -- I am not sure what "#(bitwidth+2,zwidth-1,0)" in this instance
definition does. My understanding is that # value is used to define
some delay.

In cordic_stage.v
-------------------------
if reset is set then xo, y0 and zo are set to 0. And when enable is
set, value of z is checked. My understanding of cordic logic is that,
if say that current angle is 45, and desired is 20, then subtract from
the current angle, and make corresponding adjustments on x axis and y
axis variables.

Q -- This statement checks if "z_is_pos" and does next operation
respectively. I am not sure what "xi - {{shift
+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]}" is actually doing. My
understanding of cordic is that based on angle adjustments, operations
of multiples of 2 are carried out on x-axis and y-axis variable. And
{} statement are used for concatenation in verilog.

Again, in cordic.v
---------------------------
xo, yo and zo are in continuous assignment mode and are updated
everytime a x12, y12 or z12 value changes respectively.

Q - Not exactly sure how the exact desired angle is obtained in
cordic.v. The algorithm that I read, made continous adjustments on
'current angle' so that it converged to the desired angle. I don't see
that step happening in cordic.v

I am extremely sorry if I might have annoyed you by asking so many
questions. But, any help with the above questions will immensely help
me.

Thanks.

Shah.




// This program is free software; you can redistribute it and/or
modify
// it under the terms of the GNU General Public License as published
by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version. Applies to all codes herein. I
am not posting the complete license details to
// save space.

cordic.v
------------------------

module cordic(clock, reset, enable, xi, yi, zi, xo, yo, zo );
parameter bitwidth = 16;
parameter zwidth = 16;

input clock;
input reset;
input enable;
input [bitwidth-1:0] xi, yi;
output [bitwidth-1:0] xo, yo;
input [zwidth-1:0] zi;
output [zwidth-1:0] zo;

reg [bitwidth+1:0] x0,y0;
reg [zwidth-2:0] z0;
wire [bitwidth+1:0] x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12;
wire [bitwidth+1:0] y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12;
wire [zwidth-2:0] z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12;

wire [bitwidth+1:0] xi_ext = {{2{xi[bitwidth-1]}},xi};
wire [bitwidth+1:0] yi_ext = {{2{yi[bitwidth-1]}},yi};

// Compute consts. Would be easier if vlog had atan...
// see gen_cordic_consts.py

`define c00 16'd8192
`define c01 16'd4836
`define c02 16'd2555
`define c03 16'd1297
`define c04 16'd651
`define c05 16'd326
`define c06 16'd163
`define c07 16'd81
`define c08 16'd41
`define c09 16'd20
`define c10 16'd10
`define c11 16'd5
`define c12 16'd3
`define c13 16'd1
`define c14 16'd1
`define c15 16'd0
`define c16 16'd0

always @(posedge clock)
if(reset)
begin
x0 <= #1 0; y0 <= #1 0; z0 <= #1 0;
end
else if(enable)
begin
z0 <= #1 zi[zwidth-2:0];
case (zi[zwidth-1:zwidth-2])
2'b00, 2'b11 :
begin
x0 <= #1 xi_ext;
y0 <= #1 yi_ext;
end
2'b01, 2'b10 :
begin
x0 <= #1 -xi_ext;
y0 <= #1 -yi_ext;
end
endcase // case(zi[zwidth-1:zwidth-2])
end // else: !if(reset)

// FIXME need to handle variable number of stages
// FIXME should be able to narrow zwidth but quartus makes it
bigger...
// This would be easier if arrays worked better in vlog...
cordic_stage #(bitwidth+2,zwidth-1,0) cordic_stage0
(clock,reset,enable,x0,y0,z0,`c00,x1,y1,z1);
cordic_stage #(bitwidth+2,zwidth-1,1) cordic_stage1
(clock,reset,enable,x1,y1,z1,`c01,x2,y2,z2);
cordic_stage #(bitwidth+2,zwidth-1,2) cordic_stage2
(clock,reset,enable,x2,y2,z2,`c02,x3,y3,z3);
cordic_stage #(bitwidth+2,zwidth-1,3) cordic_stage3
(clock,reset,enable,x3,y3,z3,`c03,x4,y4,z4);
cordic_stage #(bitwidth+2,zwidth-1,4) cordic_stage4
(clock,reset,enable,x4,y4,z4,`c04,x5,y5,z5);
cordic_stage #(bitwidth+2,zwidth-1,5) cordic_stage5
(clock,reset,enable,x5,y5,z5,`c05,x6,y6,z6);
cordic_stage #(bitwidth+2,zwidth-1,6) cordic_stage6
(clock,reset,enable,x6,y6,z6,`c06,x7,y7,z7);
cordic_stage #(bitwidth+2,zwidth-1,7) cordic_stage7
(clock,reset,enable,x7,y7,z7,`c07,x8,y8,z8);
cordic_stage #(bitwidth+2,zwidth-1,8) cordic_stage8
(clock,reset,enable,x8,y8,z8,`c08,x9,y9,z9);
cordic_stage #(bitwidth+2,zwidth-1,9) cordic_stage9
(clock,reset,enable,x9,y9,z9,`c09,x10,y10,z10);
cordic_stage #(bitwidth+2,zwidth-1,10) cordic_stage10
(clock,reset,enable,x10,y10,z10,`c10,x11,y11,z11);
cordic_stage #(bitwidth+2,zwidth-1,11) cordic_stage11
(clock,reset,enable,x11,y11,z11,`c11,x12,y12,z12);

assign xo = x12[bitwidth:1];
assign yo = y12[bitwidth:1];

assign zo = z12;

endmodule // cordic

---------------------------------------------------------------------------------------------------------------------

cordic_stage.v

module cordic_stage( clock, reset, enable,
xi,yi,zi,constant,xo,yo,zo);
parameter bitwidth = 16;
parameter zwidth = 16;
parameter shift = 1;

input clock;
input reset;
input enable;
input [bitwidth-1:0] xi,yi;
input [zwidth-1:0] zi;
input [zwidth-1:0] constant;
output [bitwidth-1:0] xo,yo;
output [zwidth-1:0] zo;

wire z_is_pos = ~zi[zwidth-1];

reg [bitwidth-1:0] xo,yo;
reg [zwidth-1:0] zo;

always @(posedge clock)
if(reset)
begin
xo <= #1 0;
yo <= #1 0;
zo <= #1 0;
end
else if(enable)
begin
xo <= #1 z_is_pos ?
xi - {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]} :
xi + {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]};
yo <= #1 z_is_pos ?
yi + {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]} :
yi - {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]};
zo <= #1 z_is_pos ?
zi - constant :
zi + constant;

----------------------------------------------------------------------------------------------------------------
 
dash82 <dhavalrules@gmail.com> asked:

xi_ext =
{{2{xi[bitwidth-1]}},xi};" statement is doing. Is it concatenation and
assignment?
Yes, it is an assignment and a concantenation (with replication).
This makes a bit vector, 2 bits longer than bitwidth, with the first
two bits of that bit vector being copies of xi[bitwidth-1], the rest
of the bit vector is a copy of xi, e.g. make a value two bits wider
sign extending into those bits.

Q -- I am not sure what "#(bitwidth+2,zwidth-1,0)" in this instance
definition does. My understanding is that # value is used to define
some delay.
Not in this case, it is used to override parameter values. The first
three parameters of the module being instantiated, are changed to have
the values bitwidth-2, zwidth-1, and 0 respectively.

Q -- This statement checks if "z_is_pos" and does next operation
respectively. I am not sure what "xi - {{shift
+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]}" is actually doing. My
understanding of cordic is that based on angle adjustments, operations
of multiples of 2 are carried out on x-axis and y-axis variable. And
{} statement are used for concatenation in verilog.
This concentation looks like a sign extended (arithmetic) shift left
of yi.
 

Welcome to EDABoard.com

Sponsor

Back
Top