1. 概述
在获取到 Cordic 算法生成的正余弦数值后,即可进入旋转公式的计算阶段。图像旋转的核心本质并不复杂,主要涉及两个坐标变换公式。为了便于理解,这里按照实际工程编写的逻辑记录一下关键步骤。

2. 图像旋转代码设计思路
2.1 旋转后的图像尺寸
图像旋转后,像素位置发生变化,虽然总面积不变,但显示范围会改变。例如 100x100 的图像旋转后,其外接矩形可能变大。为了确保完整显示,通常以原图对角线长度作为新图像的边界依据。
利用勾股定理计算旋转后的行列尺寸(Pixel_X, Pixel_Y),其中 ROW 和 COL 为原始尺寸。注意这里使用了定点数运算,右移 14 位相当于除以 2^14。
reg [12:0] row_size; reg [12:0] col_size;
assign Pixel_X = row_size; assign Pixel_Y = col_size;
wire [31:0] cosout_abs = (cosout[31]) ? -cosout : cosout;
wire [31:0] sinout_abs = (sinout[31]) ? -sinout : sinout;
always @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) begin
row_size <= 'd0; col_size <= 'd0;
end else begin
// h --> row, w --> col
row_size <= (ROW * cosout_abs + COL * sinout_abs) >> 14;
col_size <= (COL * cosout_abs + ROW * sinout_abs) >> 14;
end
end
2.2 旋转后图像的有效位置
有效显示区域可自由设定,这里以屏幕中心为基准。假设使用 480x272 的 LCD 屏幕,需根据具体的时序参数调整同步信号。
data_req 信号用于判断当前扫描位置是否在旋转后的有效区域内。以屏幕中点为旋转中心,减去流水线级数带来的延迟,确保时序对齐。
// 行场时序参数定义
localparam H_SYNC = 11'd41, H_BACK = 11'd2, H_LEFT = 11'd0,
H_VALID = 11'd480, H_RIGHT = 11'd0, H_FRONT = 11'd2, H_TOTAL = 11'd525;
localparam V_SYNC = 11'd10, V_BACK = 11'd2, V_TOP = 11'd0,
V_VALID = 11'd272, V_BOTTOM = 11'd0, V_FRONT = 11'd2, V_TOTAL = 11'd286;
// cnt_h: 行计数器,cnt_v: 场计数器
// data_req: 数据请求信号,表示当前像素点在有效显示区内
wire data_req = (((cnt_h >= (((H_VALID - Pixel_X) >> 1) + H_SYNC + H_BACK - 'd5)) &&
(cnt_h < (((H_VALID - Pixel_X) >> 1) + Pixel_X + H_SYNC + H_BACK - 'd5))) &&
((cnt_v >= ((V_VALID - Pixel_Y) >> 1) + V_SYNC + V_BACK - 'd5) &&
(cnt_v < (((V_VALID - Pixel_Y) >> 1) + Pixel_Y + V_SYNC + V_BACK - 'd5))));
2.3 第一级流水线
基础操作:在图像有效信号有效时进行行场计数,生成有效的旋转控制信号。
always @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) r_rotate_valid <= 1'b0;
else r_rotate_valid <= data_req;
end
always @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) r_rotate_end <= 'd0;
else if (r_rotate_valid && (vcnt == row_abs - 1) && (hcnt == col_abs - 2))
r_rotate_end <= 1'b1;
else r_rotate_end <= 'd0;
end
always @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) hcnt <= 'd0;
else if (r_rotate_valid && (r_rotate_end || (hcnt == col_abs - 1)))
hcnt <= 'd0;
else if (r_rotate_valid) hcnt <= hcnt + 'd1;
end
always @(posedge clk_i, negedge rstn_i) begin
if (!rstn_i) vcnt <= 'd0;
else if (r_rotate_valid && r_rotate_end) vcnt <= 'd0;
else if (r_rotate_valid && (hcnt == col_abs - 1)) vcnt <= vcnt + 'd1;
end


