要求: 请将下面这段 C 语言描述的串行处理过程,用可综合的 Verilog 来描述。
unsigned char cal_table_high_first(unsigned char value)
{
unsigned char i;
unsigned char checksum = value;
for (i=8; i>0; --i)
{
if (checksum & 0x80)
checksum = (checksum << 1) ^ 0x31;
else
checksum = (checksum << 1);
}
return checksum;
}
//转成多拍的并行处理(占用资源少)
module cal_table_high_first1(
input sys_clk,
input sys_rst,
input [7:0]value,
output [7:0]checksum
);
reg [3:0]cnt;
reg [7:0]checksum_buffer;
always@(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)
cnt <= 3'd0;
else if(cnt == 'd8)
cnt <= 3'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
checksum_buffer <= value;
end
else if(cnt == 3'd0)begin
checksum_buffer<= value;
end
else if(checksum_buffer[7] == 1'b1)begin
checksum_buffer <= (checksum_buffer<<1)^8'h31 ;//{checksum_buffer1[7:6],~checksum_buffer1[5:4],checksum_buffer1[3:1],~checksum_buffer1[0]};
end
else begin
checksum_buffer <= checksum_buffer<<1;//{checksum_buffer1[6:0],1'b0};
end
end
/*
always@(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
checksum <= 8'd0;
end
else if(cnt == 'd0)
checksum <= checksum_buffer;
*/
assign checksum = (cnt == 8'd0)?checksum_buffer:checksum;
endmodule
//转换成单拍的并行处理(占用资源多)
module cal_table_high_first2(
input sys_clk,
input sys_rst,
input [7:0]value,
output reg [7:0]checksum
);
wire [7:0]checksum1;
wire [7:0]checksum2;
wire [7:0]checksum3;
wire [7:0]checksum4;
wire [7:0]checksum5;
wire [7:0]checksum6;
wire [7:0]checksum7;
wire [7:0]checksum8;
assign checksum1 = (value[7] == 1'b1)?((value<<1)^8'h31):(value<<1);
assign checksum2 = (checksum1[7] == 1'b1)?((checksum1<<1)^8'h31):(checksum1<<1);
assign checksum3 = (checksum2[7] == 1'b1)?((checksum2<<1)^8'h31):(checksum2<<1);
assign checksum4 = (checksum3[7] == 1'b1)?((checksum3<<1)^8'h31):(checksum3<<1);
assign checksum5 = (checksum4[7] == 1'b1)?((checksum4<<1)^8'h31):(checksum4<<1);
assign checksum6 = (checksum5[7] == 1'b1)?((checksum5<<1)^8'h31):(checksum5<<1);
assign checksum7 = (checksum6[7] == 1'b1)?((checksum6<<1)^8'h31):(checksum6<<1);
assign checksum8 = (checksum7[7] == 1'b1)?((checksum7<<1)^8'h31):(checksum7<<1);
always@(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)
checksum <= 8'd0;
else
checksum <= checksum8;
end
endmodule
仿真测试文件
`timescale 1ns/1ns
module tb;
reg clk;
reg res;
reg [7:0] value;
wire [7:0] checksum1;
wire [7:0] checksum2;
initial begin
clk <= 1'b0;
res <= 1'b0;
value <= 8'b0000_0000;
#200 res <= 1'b1;
value <= 8'b1000_1100;
#500 value <= 8'b1011_1011;
#1000 value <= 8'b0110_0001;
end
always #10 clk <= ~clk;
cal_table_high_first1 u_cal_table_high_first1(
.sys_clk (clk) ,
.sys_rst (res) ,
.value (value) ,
.checksum (checksum1)
);
cal_table_high_first2 u_cal_table_high_first2(
.sys_clk (clk) ,
.sys_rst (res) ,
.value (value) ,
.checksum (checksum2)
);
endmodule
modelsim仿真图
通过上述仿真结果,可以明显的看出两种转换方式的不同。cal_table_high_first1采用多拍的转换,即进过八个时钟后才输出结果,虽然占用的逻辑资源较少,但效率低;cal_table_high_first2采用流水线的结构,只需单拍就可以输出结果,大大提高了代码运行效率,在FPGA上执行时,更能体现其流水线的特点。