我正在尝试在ModelSim中模拟8位数据的16位CRC生成器中的代码。生成CRC字节的逻辑如下, 1.创建一个16位crc寄存器并将其初始化为全零。 2.现在将数据字节的每个位与crc寄存器的位0进行比较,即(data [counter] == crc [0]) 3.如果比较为真,则右移crc寄存器,即crc>> 1并将其保存到crc寄存器。 4.如果比较为假,则右移crc寄存器并用16'h1021(多项式发生器)xor结果。
现在我不确定我在always块内通过FOR循环遍历数据字节的实现是否正确;在我的模拟中,for循环遍历时钟的第一个正边沿上的数据字节,如模拟块中所示。
我的结果对于CRC生成也是错误的。
即。数据= 0xF881正确CRC = 0x1CED
下面是带有测试平台的Verilog代码(Serial_CRC)和仿真结果。
//http://www.asic-world.com/examples/verilog/serial_crc.html#Serial_CRC
`timescale 1ns/1ns
`define WIDTH 16
//**************************************************************************
module Serial_CRC_wTB();
//**************************************************************************
reg in_enable;
reg in_clk;
reg in_rst_n;
reg [`WIDTH-9:0] in_data;
wire [`WIDTH-1:0] out_crcOutput;
Serial_CRC TS (.i_data(in_data), .o_crcOutput(out_crcOutput), .i_clk(in_clk), .i_rst_n(in_rst_n), .i_enable(in_enable));
initial
begin
in_clk = 1'b0 ;in_enable = 1'b0; in_rst_n = 1'b1;
#1 in_rst_n = 1'b0;
#2 in_rst_n = 1'b1; in_enable = 1'b1;
@(negedge in_clk) in_data = 8'hF8;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(negedge in_clk) in_data = 8'h81;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
#20 $finish;
end
always
#1 in_clk = ~in_clk;
endmodule // Serial_CRC_wTB
//**************************************************************************
module Serial_CRC (input [`WIDTH-9:0] i_data,input i_clk,input i_rst_n,input i_enable, output [`WIDTH-1:0] o_crcOutput);
//**************************************************************************
reg [`WIDTH-1:0] crc;
reg [`WIDTH-9:0] d;
integer counter;
always @ (posedge i_clk) begin
if (~i_rst_n) begin
crc <= {16{1'b0}};
d <= {8{1'b0}};
end
else if (i_rst_n && i_enable) begin
d <= i_data;
for (counter = 0 ; counter <= `WIDTH-9 ; counter = counter + 1) begin
if (d[counter] == crc[0])
crc <= crc >> 1;
else if (d[counter] != crc[0]) begin
crc <= crc >> 1;
crc <= crc ^ 16'h1021;
end // else if block
end // for loop block
end // else if block
end // always block
assign o_crcOutput = crc;
endmodule // Serial_CRC
答案 0 :(得分:0)
我猜你在这里误用了非阻塞作业:
crc <= crc >> 1;
crc <= crc ^ 16'h1021;
第一行不会立即更改为crc,第二行将对旧值crc进行操作
您需要以下内容:
reg [`WIDTH-1:0]tmp ;
...
else if (d[counter] != crc[0]) begin
tmp = crc >> 1;
crc <= tmp ^ 16'h1021;
end // else if block
或将其分成一行:
crc <= (crc >> 1) ^ 16'h1021;
答案 1 :(得分:0)
我通过FSM工作并发布这个答案是一个学习曲线,CRC寄存器初始化和引入数据字节的时间仍然存在挑战。
模拟的答案在这里显示。
Crc输出:0000 Crc输出:0000 Crc输出:0000 Crc输出:0000 Crc输出:1021 Crc输出:0810 Crc输出:1429 Crc输出:0a14 Crc输出:152b Crc输出:0a95 Crc输出:156b Crc输出:1a94 Crc输出:0d4a Crc输出:06a5 Crc输出:1373 Crc产量:1998年 Crc输出:1ced
//http://www.asic-world.com/examples/verilog/serial_crc.html#Serial_CRC
`timescale 1ns/1ns
`define WIDTH 16
//**************************************************************************
module Serial_CRC_wTB();
//**************************************************************************
//reg in_enable;
reg in_clk;
reg in_rst_n;
reg [`WIDTH-9:0] in_data;
wire [`WIDTH-1:0] out_crcOutput;
Serial_CRC TS (.i_data(in_data), .o_crcOutput(out_crcOutput), .i_clk(in_clk), .i_rst_n(in_rst_n));
initial
begin
in_clk = 1'b0 ; in_rst_n = 1'b0; in_data = 8'hF8;
#1 in_rst_n = 1'b0;
#2 in_rst_n = 1'b1;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 0
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 1
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 2
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 3
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 4
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 5
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 6
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 7
@(negedge in_clk) in_data = 8'h81;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 8
//@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
//@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
// @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
#1 $finish;
end
always
#1 in_clk = ~in_clk;
endmodule // Serial_CRC_wTB
//**************************************************************************
module Serial_CRC (input [`WIDTH-9:0] i_data,input i_clk,input i_rst_n, output [`WIDTH-1:0] o_crcOutput);
//**************************************************************************
parameter S0 = 3'b000; //BIT[0]
parameter S1 = 3'b001; //BIT[1]
parameter S2 = 3'b010; //BIT[2]
parameter S3 = 3'b011; //BIT[3]
parameter S4 = 3'b100; //BIT[4]
parameter S5 = 3'b101; //BIT[5]
parameter S6 = 3'b110; //BIT[6]
parameter S7 = 3'b111; //BIT[7]
reg [2:0] curr_state;
reg [2:0] next_state;
reg [7:0] d;
reg [15:0] crc;
// Sequential logic for storing current state
always @ (posedge i_clk, negedge i_rst_n) begin
if (~i_rst_n) begin
curr_state <= S0;
crc <= {16{1'b0}}; end
else
curr_state <= next_state;
end
always @ (curr_state, d) begin
case (curr_state)
S0: next_state <= S1;
S1: next_state <= S2;
S2: next_state <= S3;
S3: next_state <= S4;
S4: next_state <= S5;
S5: next_state <= S6;
S6: next_state <= S7;
S7: next_state <= S0;
endcase // curr_state
end
// need to fix the blocking versus the non-blocking case on the state variables
// Output Logic
always @ (posedge i_clk) begin
case(curr_state)
S0: begin
d = i_data;
if (d[0] == crc[0])
crc = crc >> 1'b1;
else if (d[0] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S0
S1: begin
if (d[1] == crc[0])
crc = crc >> 1'b1;
else if (d[1] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S1
S2: begin
if (d[2] == crc[0])
crc = crc >> 1'b1;
else if (d[2] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S2
S3: begin
if (d[3] == crc[0])
crc = crc >> 1'b1;
else if (d[3] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S3
S4: begin
if (d[4] == crc[0])
crc = crc >> 1'b1;
else if (d[4] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S4
S5: begin
if (d[5] == crc[0])
crc = crc >> 1'b1;
else if (d[5] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S5
S6: begin
if (d[6] == crc[0])
crc = crc >> 1'b1;
else if (d[6] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S6
S7: begin
if (d[7] == crc[0])
crc = crc >> 1'b1;
else if (d[7] != crc[0]) begin
crc = crc >> 1'b1;
crc = crc ^ 16'h1021; end
end // S7
endcase // curr_state
end //always
assign o_crcOutput = crc;
endmodule // Serial_CRC