我正尝试在ModelSim中模拟一个代码,用于8位数据的16位CRC生成器。生成crc字节的逻辑如下,1.创建16位crc寄存器并将其初始化为全0。2.现在将数据字节的每一位与crc寄存器的位0进行比较,即(数据计数器crc) 3.如果比较为真,则将crc寄存器右移,即crc >> 1,并将其保存到CRC寄存器。4.如果比较为假,则向右移位crc寄存器,并将结果与16'h1021 (多项式生成器)进行异或。
现在,我不确定我在always块中迭代数据字节到FOR循环的实现是否正确;在我的模拟中,for循环迭代时钟第一个正边沿上的数据字节,如模拟块中所示。
我的结果对于CRC生成也是错误的。
即Data = 0xF881正确的CRC = 0x1CED
下面是带有测试平台和仿真结果的Verilog Code (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

发布于 2018-03-26 00:06:00
我猜你在这里误用了非阻塞赋值:
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; 发布于 2018-03-28 00:20:06
我通过有限状态机让它工作,并发布了这个答案是一个学习曲线,挑战仍然存在于CRC寄存器的初始化和引入数据字节的时间上。
模拟结果如下所示。
Crc输出:0000 Crc输出:1021 Crc输出:0810 Crc输出:1429 Crc输出:0a14 Crc输出:152b Crc输出:0a95 Crc输出:156b Crc输出:1a94 Crc输出:0d4a Crc输出:06a5 Crc输出:137CRC输出: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和仿真时序图。


https://stackoverflow.com/questions/49472007
复制相似问题