👉注:更多精彩请看:面试常问的verilog代码汇总 一文
例如,相邻16个点的数据累加:
- 数据采用补码形式相加;
- 在做累加之前要提前给数据位宽扩展
- 构造一个与源时钟的相反的反向时钟,将源时钟和反向时钟做“与逻辑”计算,创建一个采样时钟脉syn_pulse;
- 用计数器计算syn_pulse个数,每当出现syn_pulse,数据就累加一次;
- 计满16次就将数据输出;
时序图如下:
代码如下:
//相邻16点相加
module sigma_16(clk,rst_n,data_in,syn_in,data_out,syn_out);
input clk,rst_n;
input [7:0]data_in;//采样信号
input syn_in;//采样时钟
output [11:0]data_out;//累计结果输出
output syn_out;//累加和同步脉冲
reg syn_in_n1;//syn_in的反向延时
wire sun_pulse;//采样时钟上升沿识别脉冲
assign syn_pulse = syn_in_n1 & syn_in;
reg [3:0]con_syn;//采样时钟循环计数器
wire comp_8;//补码
wire [11:0]d_12;//升位结果,由于是16个8位二进制相加,结果会扩展4位,需要提前升至12位
assign comp_8 = data_in[7] ? {data[7],~data[6:0] + 1} : data_in;//补码运算
assign d_12 = {comp_8[7],comp_8[7],comp_8[7]comp_8[7],comp_8};//把符号位扩展4位
reg [11:0]sigma;//累加计算
reg [11:0]data_out;
reg syn_out;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
syn_in_n1 <= 0;
count_syn <=0;
sigma <= 0;
data_out <= 0;
syn_out <= 0;
end
else begin
syn_in_n1 <= ~syn_in;
if(syn_pulse) begin//出现syn_pulse,就加一次
con_syn <= con_syn + 1; //因为定义的位宽为4,所以其本身就16个点循环,故不用设置它计到16复位
end
if(syn_pulse) begin//在每次syn_pulse出现时,就做相邻点相加
if(con_syn == 15)begin//已经加了15个数时,要做三个步骤
sigma <= d_12;//将累加和至为下一次累加计算的第一个数
data_out <= sigma;//将16个相邻点累加结果输出
syn_out <= 1;//累加和同步脉冲信号拉高
end
else begin
sigma <= sigma + d_12;
end
end
else begin
syn_out <= 0;
end
end
end
endmodule