реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Вычисление arctg(y/x) на verilog c помощью CORDIC-алгоритма
Andy111
сообщение Mar 3 2015, 13:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 3-03-15
Пользователь №: 85 466



Здравствуйте. В общем стоит задача написать модуль на Verilog, который бы рассчитывал arctg(y/x) с помощью CORDIC алгоритма. Я в veriloge не очень силен, поэтому покопался в интернете и нашел вот такую реализацию:
CODE

`define activehigh 1
`define procline posedge clk
`define proclineg posedge clk
`define proclineSlow posedge clkSlow
`define proclineFast posedge clkFast

module CordicRotator (clk, rst, en, xi, yi, zi, xo, yo, zo); // {
parameter smi = 1;
parameter bitWidth = 16;
parameter angBitWidth = 16;
parameter angFracWidth = 16;
parameter rotMode = 1;
input clk;
input rst;
input en;

input signed [bitWidth-1:0] xi;
input signed [bitWidth-1:0] yi;
input signed [angBitWidth-1:0] zi;
output reg signed [bitWidth-1:0] xo;
output reg signed [bitWidth-1:0] yo;
output reg signed [angBitWidth-1:0] zo;

function signed [angFracWidth-1:0] appr;
input signed [53:0] atf;
begin
if (angFracWidth>54)
begin
appr = 0;
appr[angFracWidth-1:angFracWidth-54] = atf;
end
else
appr = atf[53:54-angFracWidth];
end
endfunction // appr

wire signed [bitWidth-1:0] sx,sy;

assign sx = xi >>> smi;
assign sy = yi >>> smi;

reg signed [53:0] atf;
reg signed [angFracWidth-1:0] at;

always @(`procline)
begin
if (rst==`activehigh)
begin
xo <= 0;
yo <= 0;
zo <= 0;
end
else if (en)
begin
case (smi)
0: atf = 54'b010000000000000000000000000000000000000000000000000000; //0.25
1: atf = 54'b001001011100100000001010001110110011101111100110000100;
2: atf = 54'b000100111111011001110000101101101011110111000111001111;
3: atf = 54'b000010100010001000100011101010000011101110111011001101;
4: atf = 54'b000001010001011000011010100001100001110010110001001101;
5: atf = 54'b000000101000101110101111110000101011001000001000110001;
6: atf = 54'b000000010100010111101100001111001011100001010000010011;
7: atf = 54'b000000001010001011111000101010100010001110101000100001;
8: atf = 54'b000000000101000101111100101001101000110110100001100001;
9: atf = 54'b000000000010100010111110010111010111011001100001010101;
10: atf = 54'b000000000001010001011111001100000000000100100011011101;
11: atf = 54'b000000000000101000101111100110000010100101010000000110;
12: atf = 54'b000000000000010100010111110011000001100110111111110110;
13: atf = 54'b000000000000001010001011111001100000110110000010111001;
14: atf = 54'b000000000000000101000101111100110000011011010101110100;
15: atf = 54'b000000000000000010100010111110011000001101101101011101;
16: atf = 54'b000000000000000001010001011111001100000110110111000010;
17: atf = 54'b000000000000000000101000101111100110000011011011100100;
18: atf = 54'b000000000000000000010100010111110011000001101101110010;
19: atf = 54'b000000000000000000001010001011111001100000110110111001;
20: atf = 54'b000000000000000000000101000101111100110000011011011100;
21: atf = 54'b000000000000000000000010100010111110011000001101101110;
22: atf = 54'b000000000000000000000001010001011111001100000110110111;
23: atf = 54'b000000000000000000000000101000101111100110000011011011;
24: atf = 54'b000000000000000000000000010100010111110011000001101101;
25: atf = 54'b000000000000000000000000001010001011111001100000110110;
26: atf = 54'b000000000000000000000000000101000101111100110000011011;
27: atf = 54'b000000000000000000000000000010100010111110011000001101;
28: atf = 54'b000000000000000000000000000001010001011111001100000110;
29: atf = 54'b000000000000000000000000000000101000101111100110000011;
30: atf = 54'b000000000000000000000000000000010100010111110011000001;
31: atf = 54'b000000000000000000000000000000001010001011111001100000;
32: atf = 54'b000000000000000000000000000000000101000101111100110000;
33: atf = 54'b000000000000000000000000000000000010100010111110011000;
34: atf = 54'b000000000000000000000000000000000001010001011111001100;
35: atf = 54'b000000000000000000000000000000000000101000101111100110;
36: atf = 54'b000000000000000000000000000000000000010100010111110011;
37: atf = 54'b000000000000000000000000000000000000001010001011111001;
38: atf = 54'b000000000000000000000000000000000000000101000101111100;
39: atf = 54'b000000000000000000000000000000000000000010100010111110;
40: atf = 54'b000000000000000000000000000000000000000001010001011111;
41: atf = 54'b000000000000000000000000000000000000000000101000101111;
42: atf = 54'b000000000000000000000000000000000000000000010100010111;
43: atf = 54'b000000000000000000000000000000000000000000001010001011;
44: atf = 54'b000000000000000000000000000000000000000000000101000101;
45: atf = 54'b000000000000000000000000000000000000000000000010100010;
46: atf = 54'b000000000000000000000000000000000000000000000001010001;
47: atf = 54'b000000000000000000000000000000000000000000000000101000;
48: atf = 54'b000000000000000000000000000000000000000000000000010100;
49: atf = 54'b000000000000000000000000000000000000000000000000001010;
50: atf = 54'b000000000000000000000000000000000000000000000000000101;
51: atf = 54'b000000000000000000000000000000000000000000000000000010;
52: atf = 54'b000000000000000000000000000000000000000000000000000001;
default: atf = 0;
endcase

at = appr(atf);
if (rotMode==1)
if (zi >= 0)
begin
xo <= xi - sy;
yo <= yi + sx;
zo <= zi - at;
end
else
begin
xo <= xi + sy;
yo <= yi - sx;
zo <= zi + at;
end // if (zi...
else
if (yi >=0)
begin
xo <= xi + sy;
yo <= yi - sx;
zo <= zi + at;
end
else
begin
xo <= xi - sy;
yo <= yi + sx;
zo <= zi - at;
end // if(yi...
end // if(en)
end // always

endmodule // CordicRotator }

/////////////////////////////////////////////////////////////////////

module CordicSeq (clk, rst, en, xi, yi, zi, xo, yo, zo); // {
parameter depth = 15;
parameter bitWidth = 16;
parameter angBitWidth = 16;
parameter angFracWidth = 16;
parameter rotMode = 1;

input clk, rst, en;
input signed [bitWidth-1:0] xi, yi;
input signed [angBitWidth-1:0] zi;
output signed [bitWidth-1:0] xo, yo;
output signed [angBitWidth-1:0] zo;

wire signed [bitWidth-1:0] x [0:depth];
wire signed [bitWidth-1:0] y [0:depth];
wire signed [angBitWidth-1:0] z [0:depth];

assign x[0] = xi;
assign y[0] = yi;
assign z[0] = zi;

generate
genvar i;
for (i = 0; i < depth; i=i+1)
begin : gen_seq
CordicRotator #(
.smi(i),
.bitWidth(bitWidth),
.angBitWidth(angBitWidth),
.angFracWidth(angFracWidth),
.rotMode(rotMode))
cr
(clk, rst, en, x[i], y[i], z[i],
x[i+1], y[i+1], z[i+1]);
end
endgenerate //gen_seq

assign xo = x[depth];
assign yo = y[depth];
assign zo = z[depth];

endmodule // CordicSeq }


module synCordicAtan (clk, rst, en, x, y, atanOut); // {
parameter depth=15;
parameter bitWidth=16;
parameter angBitWidth=16;
input clk, rst, en;
input [bitWidth-1:0] x, y;
output reg [angBitWidth-1:0] atanOut;

reg [1:0] quadrant [0:depth-1];
reg signed [bitWidth+1:0] xi=0, yi=0;
wire signed [bitWidth-1:0] tmpx, tmpy;
reg signed [angBitWidth-1:0] zi=0;

wire signed [bitWidth+1:0] xo, yo;
wire signed [angBitWidth-1:0] zo;
wire signed [angBitWidth-1:0] negzo;

wire [angBitWidth-2:0] tmpzero = 0;
reg [5:0] rcnt;

integer i;

assign negzo = -zo;
assign tmpx = -x;
assign tmpy = -y;


CordicSeq #(
.depth(depth-1),
.bitWidth(bitWidth+2),
.angBitWidth(angBitWidth),
.angFracWidth(angBitWidth-1),
.rotMode(0))
cs
(clk, rst, en, xi, yi, zi, xo, yo, zo);

always @(`procline)
begin
if (rst==`activehigh)
begin
rcnt <= 0;
xi <= 0;
yi <= 0;
atanOut <= 0;
for (i=0;i<depth;i=i+1)
quadrant[i] <= 2'b00;
end
else if (en)
begin
if(rcnt!=depth)
rcnt <= rcnt+1;

if (x[bitWidth-1] == 0)
xi <= {x[bitWidth-1],x[bitWidth-1],x};
else
xi <= {tmpx[bitWidth-1],tmpx[bitWidth-1],tmpx};

if (y[bitWidth-1] == 0)
yi <= {y[bitWidth-1],y[bitWidth-1],y};
else
yi <= {tmpy[bitWidth-1],tmpy[bitWidth-1],tmpy};

quadrant[0][0] <= x[bitWidth-1];
quadrant[0][1] <= y[bitWidth-1];

for (i=0;i<depth-1;i=i+1)
quadrant[i+1] <= quadrant[i];

if(rcnt==depth)
case (quadrant[depth-1])
2'b00 : atanOut <= zo;
2'b01 : atanOut <= {1'b1, tmpzero} - $unsigned(zo);
2'b10 : atanOut <= negzo; // use intermediate to force sizing
default : atanOut <= {1'b1, tmpzero} + $unsigned(zo);
endcase
end // if
end // always

endmodule // }


Промоделировал в Quartus. Вроде работает (через 15 тактов выдает результат). Но не могу разобраться в каком формате задавать входные данные x и y (с фиксированной точкой или целое, знаковое или беззнаковое и т. п.). И как интерпретировать результат (т. е. в каком формате выдается результат, в градусах или радианах, сколько разрядов на дробную часть, сколько на целую и т. д.).
Go to the top of the page
 
+Quote Post
~Elrond~
сообщение Mar 3 2015, 13:58
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 20-04-12
Из: Нижний Новгород
Пользователь №: 71 488



Я тоже где-то с полгода назад разбирался в кордике, в итоге всё написал сам, и разобрался, как оно работает. Если интересно, могу выложить код. Тут реализация похожа на мою, но стиль написания довольно корявый. К тому же, это только ядро CORDIC, а для того чтобы вычислять арктангенс, нужны ещё препроцессор и постпроцессор. На вход должны идти значения синуса и косинуса в формате (s16,15), а на выходе - зависит от реализации постпроцессора. Я сделал выходы в формате u16,16 и для угла, и для фазы.
Go to the top of the page
 
+Quote Post
Andy111
сообщение Mar 3 2015, 14:06
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 3-03-15
Пользователь №: 85 466



Цитата(~Elrond~ @ Mar 3 2015, 14:58) *
Я тоже где-то с полгода назад разбирался в кордике, в итоге всё написал сам, и разобрался, как оно работает. Если интересно, могу выложить код. Тут реализация похожа на мою, но стиль написания довольно корявый. К тому же, это только ядро CORDIC, а для того чтобы вычислять арктангенс, нужны ещё препроцессор и постпроцессор. На вход должны идти значения синуса и косинуса в формате (s16,15), а на выходе - зависит от реализации постпроцессора. Я сделал выходы в формате u16,16 и для угла, и для фазы.

Буду премного благодарен если скинете свою версиюsm.gif
Go to the top of the page
 
+Quote Post
~Elrond~
сообщение Mar 3 2015, 14:16
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 20-04-12
Из: Нижний Новгород
Пользователь №: 71 488



Ядро CORDIC
CODE
// ================================================================================
==========================
// Project : FPGA DSP Library
// File : cordic_core.sv
// Title : CORDIC core module
// Dependencies : -
//
// Description : This module implements iterative CORDIC algorhytm with parameterized precision.
// Calculation started when request detected. 'rdy' flag asserted when result is ready.
// Output data remain valid until the next request.
// ================================================================================
==========================
// REVISION HISTORY
// Version Date Author Change Description
// 1.0 24.11.14 Noskov A.M. Initial creation;
// ================================================================================
==========================
module cordic_core #(
parameter SIG_W = 18,
parameter ACC_W = 20
)(
input logic rst_n,
input logic clk,
input logic req,
input logic ccwr,
input logic signed [SIG_W:0] x_i,
input logic signed [SIG_W:0] y_i,
input logic signed [ACC_W+1:0] a_i,
output logic rdy,
output logic busy,
output logic signed [SIG_W:0] x_o,
output logic signed [SIG_W:0] y_o,
output logic signed [ACC_W+1:0] a_o
);

`define ANG_SCALE(s) (ACC_W < 32) ? \
(ACC_W+2)'(unsigned'(``s`` >>> (32-ACC_W)) + unsigned'(1'(``s`` >> (32-ACC_W-1)))) : \
(ACC_W+2)'(``s``)

localparam logic signed [ACC_W+1:0] ANG_TABLE[31] = '{
`ANG_SCALE(32'sd536870912),
`ANG_SCALE(32'sd316933406),
`ANG_SCALE(32'sd167458907),
`ANG_SCALE(32'sd85004756),
`ANG_SCALE(32'sd42667331),
`ANG_SCALE(32'sd21354465),
`ANG_SCALE(32'sd10679838),
`ANG_SCALE(32'sd5340245),
`ANG_SCALE(32'sd2670163),
`ANG_SCALE(32'sd1335087),
`ANG_SCALE(32'sd667544),
`ANG_SCALE(32'sd333772),
`ANG_SCALE(32'sd166886),
`ANG_SCALE(32'sd83443),
`ANG_SCALE(32'sd41722),
`ANG_SCALE(32'sd20861),
`ANG_SCALE(32'sd10430),
`ANG_SCALE(32'sd5215),
`ANG_SCALE(32'sd2608),
`ANG_SCALE(32'sd1304),
`ANG_SCALE(32'sd652),
`ANG_SCALE(32'sd326),
`ANG_SCALE(32'sd163),
`ANG_SCALE(32'sd81),
`ANG_SCALE(32'sd41),
`ANG_SCALE(32'sd20),
`ANG_SCALE(32'sd10),
`ANG_SCALE(32'sd5),
`ANG_SCALE(32'sd3),
`ANG_SCALE(32'sd1),
`ANG_SCALE(32'sd1)
};
`undef ANG_SCALE

localparam CNT_W = $clog2(ACC_W+1);
localparam [CNT_W-1:0] LAST_CNT = (CNT_W)'(ACC_W) - 1'b1;

logic busy_t1;
logic [CNT_W-1:0] i;
logic signed [SIG_W:0] x_s, y_s;

assign x_s = signed'(x_o >>> i);
assign y_s = signed'(y_o >>> i);
assign busy = (i < LAST_CNT);
assign rdy = (~busy & busy_t1);

always_ff @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
i <= '1;
x_o <= 0;
y_o <= 0;
a_o <= 0;
busy_t1 <= 0;
end
else begin
busy_t1 <= busy;
if(req & ~busy) begin
i <= 0;
x_o <= x_i;
y_o <= y_i;
a_o <= a_i;
end
if(busy) begin
i <= i + 1'b1;
x_o <= (ccwr) ? (x_o - y_s) : (x_o + y_s);
y_o <= (ccwr) ? (y_o + x_s) : (y_o - x_s);
a_o <= (ccwr) ? (a_o + ANG_TABLE[i]) : (a_o - ANG_TABLE[i]);
end
end
end

endmodule

Пре/пост-процессор для арктангенса
CODE
// ================================================================================
==========================
// Project : FPGA DSP Library
// File : cart2pol.sv
// Title : Cartesian-to-Polar Vector Transform
// Dependencies : cordic_core.sv
//
// Description : This module performs transformation of vector from Cartesian to Polar coordinate system.
// Transformation is based on the iterative implementation of the CORDIC algorhytm.
// Vector precision parameterized for both coordinate systems separately;
// Calculation started when request detected. 'rdy' flag asserted when result is ready.
// Output data remain valid until the next request.
// ================================================================================
==========================
// REVISION HISTORY
// Version Date Author Change Description
// 1.0 25.11.14 Noskov A.M. Initial creation;
// ================================================================================
==========================
module cart2pol #(
parameter SIG_W = 16,
parameter ACC_W = 16
)(
input logic rst_n,
input logic clk,
input logic req,
input logic signed [SIG_W-1:0] cos,
input logic signed [SIG_W-1:0] sin,
output logic rdy,
output logic busy,
output logic [ACC_W-1:0] ang,
output logic [SIG_W-1:0] hyp
);

localparam [SIG_W-1:0] X_SCALE = (2**SIG_W-1) * 0.60723;

logic ccwr;
logic signed [SIG_W:0] x_i, y_i;
logic signed [SIG_W:0] x_o, y_o;
logic signed [ACC_W+1:0] a_o, a_i;

cordic_core #(
.SIG_W (SIG_W),
.ACC_W (ACC_W))
dds_core (
.rst_n,
.clk,
.req,
.ccwr,
.x_i,
.y_i,
.a_i,
.rdy,
.busy,
.x_o,
.y_o,
.a_o
);

// Clockwise / Counter-clockwise rotate
assign ccwr = y_o[SIG_W];

// Quadrant selector
always_comb begin : quadrant_sel
x_i = cos;
y_i = -sin;
a_i = '0;
if(cos[SIG_W-1]) begin // X < 0
a_i[ACC_W-:2] = 2'b01; // + 180 deg.
x_i = -cos;
y_i = sin;
end
else if(sin[SIG_W-1]) // Y < 0
a_i[ACC_W-:2] = 2'b10; // + 360 deg.
end : quadrant_sel

function logic [SIG_W-1:0] calc_hyp(logic signed [SIG_W:0] i_x);
logic [SIG_W*2+1:0] mult;
mult = unsigned'(i_x) * X_SCALE;
calc_hyp = mult[SIG_W*2-1:SIG_W];
endfunction

// Output assignments
assign ang = a_o[ACC_W-1:0];
assign hyp = calc_hyp(x_o);

endmodule


Сообщение отредактировал ~Elrond~ - Mar 3 2015, 14:19
Go to the top of the page
 
+Quote Post
serjj
сообщение Mar 4 2015, 15:03
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 527
Регистрация: 4-06-14
Из: Санкт-Петербург
Пользователь №: 81 866



Могу свою реализацию подкинуть (под cyclone), может кому пригодится. Способ применения понятен из тестбенча. Перед сборкой нужно поставить флажок __SYNTHESIS__.
Прикрепленный файл  cordic_light.zip ( 4.94 килобайт ) Кол-во скачиваний: 118
Go to the top of the page
 
+Quote Post
Krys
сообщение Mar 5 2015, 03:05
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 001
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271



Выложите ещё пожалуйста те доки (или ссылки) по которым удалось разобраться, как это работает.


--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
Go to the top of the page
 
+Quote Post
serjj
сообщение Mar 5 2015, 06:57
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 527
Регистрация: 4-06-14
Из: Санкт-Петербург
Пользователь №: 81 866



Тысячи их, вот например:
Прикрепленный файл  cordic____.pdf ( 1.07 мегабайт ) Кол-во скачиваний: 1006

Matlab1
Matlab2
Go to the top of the page
 
+Quote Post
Lerk
сообщение Mar 5 2015, 08:35
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 302
Регистрация: 5-05-11
Пользователь №: 64 797



Цитата(Krys @ Mar 5 2015, 06:05) *
Выложите ещё пожалуйста те доки (или ссылки) по которым удалось разобраться, как это работает.


Если дружить с математикой нет желания, то просто и доступно есть вот такой гайд: CORDIC for dummies

Сообщение отредактировал Lerk - Mar 5 2015, 08:42
Go to the top of the page
 
+Quote Post
~Elrond~
сообщение Mar 5 2015, 10:07
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 20-04-12
Из: Нижний Новгород
Пользователь №: 71 488



Krys
Я разбирался и писал свою версию исключительно по CORDIC for dummies. Крайне полезный и доступный для понимания материал, есть исходники. Оставалось только перевести в HDL и параметризовать. В аттаче моя версия вместе с тестбенчем.
Прикрепленные файлы
Прикрепленный файл  atan2.zip ( 28.31 килобайт ) Кол-во скачиваний: 84
 
Go to the top of the page
 
+Quote Post
Krys
сообщение Mar 10 2015, 04:22
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 001
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271



Большое спасибо всем отозвавшимся!


--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
Go to the top of the page
 
+Quote Post
Abo
сообщение Nov 25 2017, 12:14
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 9-01-06
Пользователь №: 12 967



Цитата(~Elrond~ @ Mar 5 2015, 13:07) *
Krys
Я разбирался и писал свою версию исключительно по CORDIC for dummies. Крайне полезный и доступный для понимания материал, есть исходники. Оставалось только перевести в HDL и параметризовать. В аттаче моя версия вместе с тестбенчем.


Мне тоже потребовалось сделать кордик для расчета арктангенса. Воспользовался этим кодом.
Благодарю автора. Со своей стороны прикладываю немного ускоренный вариант с хранением сдвинутого предыдущего значения в отдельном регистре.
До изменения на 10M50 максимальная тактовая была не более 119МГц, после выросла до 137МГц. Мне нужно было чтобы при 120МГц работало.


Код
module cordic_core #(
    parameter                         SIG_W    = 18,
    parameter                         ACC_W    = 20
)(
    input                  rst,
    input                  clk,
    input                  req,
    input                  ccwr,
    input  signed [SIG_W:0]        x_i,
    input  signed [SIG_W:0]        y_i,
    input  signed [ACC_W+1:0]    a_i,
    output                 rdy,
    output                 busy,
    output reg signed [SIG_W:0]    x_o,
    output reg signed [SIG_W:0]    y_o,
    output reg signed [ACC_W+1:0]    a_o
);

`define ANG_SCALE(s)    (ACC_W < 32) ? \
    (ACC_W+2)'(unsigned'(``s`` >>> (32-ACC_W)) + unsigned'(1'(``s`` >> (32-ACC_W-1)))) : \
    (ACC_W+2)'(``s``)
    
localparam logic signed [ACC_W+1:0]    ANG_TABLE[31] = '{
    `ANG_SCALE(32'sd536870912),
    `ANG_SCALE(32'sd316933406),
    `ANG_SCALE(32'sd167458907),
    `ANG_SCALE(32'sd85004756),
    `ANG_SCALE(32'sd42667331),
    `ANG_SCALE(32'sd21354465),
    `ANG_SCALE(32'sd10679838),
    `ANG_SCALE(32'sd5340245),
    `ANG_SCALE(32'sd2670163),
    `ANG_SCALE(32'sd1335087),
    `ANG_SCALE(32'sd667544),
    `ANG_SCALE(32'sd333772),
    `ANG_SCALE(32'sd166886),
    `ANG_SCALE(32'sd83443),
    `ANG_SCALE(32'sd41722),
    `ANG_SCALE(32'sd20861),
    `ANG_SCALE(32'sd10430),
    `ANG_SCALE(32'sd5215),
    `ANG_SCALE(32'sd2608),
    `ANG_SCALE(32'sd1304),
    `ANG_SCALE(32'sd652),
    `ANG_SCALE(32'sd326),
    `ANG_SCALE(32'sd163),
    `ANG_SCALE(32'sd81),
    `ANG_SCALE(32'sd41),
    `ANG_SCALE(32'sd20),
    `ANG_SCALE(32'sd10),
    `ANG_SCALE(32'sd5),
    `ANG_SCALE(32'sd3),
    `ANG_SCALE(32'sd1),
    `ANG_SCALE(32'sd1)
};
`undef ANG_SCALE

localparam                         CNT_W = $clog2(ACC_W+1);
localparam [CNT_W-1:0]        LAST_CNT = (CNT_W)'(ACC_W) - 1'b1;


logic                                busy_t1;
logic                  [4:0]            i;            // Изначально разрядность была настраиваемой [CNT_W-1:0], изменил чтобы квартус не предупреждал.
logic signed     [SIG_W:0]    x_s, y_s;

assign busy    = (i < LAST_CNT);
assign rdy    = (~busy & busy_t1);

wire signed [SIG_W:0] next_x_o = (ccwr) ? (x_o - y_s) : (x_o + y_s);
wire signed [SIG_W:0] next_y_o = (ccwr) ? (y_o + x_s) : (y_o - x_s);

wire signed [SIG_W:0] next_x_s = signed'(next_x_o >>> (i+1'b1));
wire signed [SIG_W:0] next_y_s = signed'(next_y_o >>> (i+1'b1));
        
always_ff @(posedge clk, posedge rst) begin
    if(rst) begin
        busy_t1    <= 0;
        i    <= '1;
        x_o    <= 0;
        y_o    <= 0;
        x_s     <= 0;
        y_s    <= 0;
        a_o    <= 0;
    end
    else begin
        busy_t1    <= busy;
    
        if(req | busy)
            if(req) begin
                i <= 0;
                x_o    <= x_i;
                y_o    <= y_i;
                x_s     <= x_i;
                y_s     <= y_i;
                a_o    <= a_i;
            end
            else begin
                i        <= i + 1'b1;
                x_o    <= next_x_o; //(ccwr) ? (x_o - y_s) : (x_o + y_s);
                y_o    <= next_y_o; //(ccwr) ? (y_o + x_s) : (y_o - x_s);
                x_s     <= next_x_s;
                y_s     <= next_y_s;
                a_o    <= a_o + (ccwr ? ANG_TABLE[i] : -ANG_TABLE[i]); //(ccwr) ? (a_o + ANG_TABLE[i]) : (a_o - ANG_TABLE[i]);
            end
    end
end
endmodule
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 13th December 2017 - 20:48
Рейтинг@Mail.ru


Страница сгенерированна за 0.01355 секунд с 7
ELECTRONIX ©2004-2016