有时需要先用C语言完成某些设计,通过成熟的仿真软件验证后再转化为Verilog代码
#include <stdio.h>
int main(void){
int n,A,B,C;
A = 0;
C = 7;
scanf("n=%d",&n);
while(C>=0){
B = ((A << 1) + (1 << C)) << C;
if(B <= n){
A += (1 << C);
n -= B;
}
C--;
}
printf("A=%d",A);
return 0;
}
上面是一个将平方数开方的算法,将其转化为verilog代码
module sqrt(clk,rst_n,indata,result);
input clk;
input rst_n;
input [31:0] indata; //输入用32bits
output reg [15:0] result; //结果开方只需16bits
reg [31:0] indata_reg; //算法中需要更改输入,因此需要设置一个寄存
reg [31:0] B;
reg [4:0] C; //indata的最大值为2的30次方,因此根据算法C = 15即可
reg [4:0] C_temp; //在循环中,计算A的值需要上一周期C的值,这里需要注意
reg [15:0] result_reg; //用于检测结果是否发生变化,发生变化
wire flag_f; //用于在循环的计算中使相邻两个循环“互通”
wire flag_r; //用于在循环的计算中使相邻两个循环“互通”
assign flag_f = (B <= indata_reg && C != C_temp)?1'd1:1'd0;
assign flag_r = (result != result_reg);
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
result <= 16'd0;
indata_reg <= indata;
end
else if(B <= indata_reg && flag_r== 1'd0)begin
result <= result + (1 << C_temp);
indata_reg = indata_reg - B;
end
else begin
result <= result;
indata_reg <= indata_reg;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
C = 5'd15;
B <= indata + 1'd1; //刚刚复位后,为了防止误判,将B设置为大于indata,不影响后面
end
else if(C != 31 && flag_f == 0)begin
B <= ((result << 1'd1) + (1'd1 << C)) << C;
C <= C - 1'd1;
end
else begin
C <= C;
B <= B;
end
end
//以下两个always块是重点,分别有不同的作用
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
C_temp <= 5'd0;
end
else begin
C_temp <= C;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
result_reg <= 16'd0;
end
else begin
result_reg <= result;
end
end
endmodule
文章来源:https://www.toymoban.com/news/detail-532904.html
代码中重要的是,在C语言中,代码是顺序执行的,且可以把赋值语句加在循环的任何一个地方,因此本次循环可以使用本次循环或者相邻循环的值,而在Verilog中,不同值之间是并行改变的,相邻周期很容易会导致判断或者赋值语句不能够调用你所期待的,因此需要根据波形图去调整。波形图中的几个flag信号就是一些让循环正确运行的信号。文章来源地址https://www.toymoban.com/news/detail-532904.html
到了这里,关于将一段C语言转化为Verilog的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!