107 lines
2.2 KiB
Systemverilog
107 lines
2.2 KiB
Systemverilog
module crc7 #(parameter POLYNOMIAL = 8'h89)
|
|
(
|
|
input clk,
|
|
input rst,
|
|
|
|
input load,
|
|
input [39:0] data_in,
|
|
|
|
output logic [6:0] crc_out,
|
|
output logic valid
|
|
);
|
|
|
|
logic [46:0] data;
|
|
logic [46:0] next_data;
|
|
logic [46:0] polyshift;
|
|
|
|
typedef enum bit [1:0] {IDLE, WORKING, VALID} macro_t;
|
|
struct packed {
|
|
macro_t macro;
|
|
logic [5:0] count;
|
|
} state, next_state;
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (rst) begin
|
|
polyshift <= {POLYNOMIAL, 39'b0}; //start all the way at the left
|
|
data <= '0;
|
|
state.macro <= IDLE;
|
|
state.count <= '0;
|
|
end else begin
|
|
if (load) begin
|
|
data <= {data_in, 7'b0};
|
|
end else begin
|
|
data <= next_data;
|
|
end
|
|
state <= next_state;
|
|
|
|
if (state.macro == WORKING) begin
|
|
polyshift <= polyshift >> 1;
|
|
end
|
|
|
|
if (state.macro == VALID) begin
|
|
polyshift <= {POLYNOMIAL, 39'b0};
|
|
end
|
|
end
|
|
end
|
|
|
|
always_comb begin
|
|
next_state = state;
|
|
|
|
case (state.macro)
|
|
IDLE: begin
|
|
if (load) begin
|
|
next_state.macro = WORKING;
|
|
next_state.count = '0;
|
|
end
|
|
end
|
|
|
|
WORKING: begin
|
|
if (state.count < 39) begin
|
|
next_state.count = state.count + 6'b1;
|
|
end else begin
|
|
next_state.macro = VALID;
|
|
next_state.count = '0;
|
|
end
|
|
end
|
|
|
|
VALID: begin // Same as IDLE, but IDLE is just for reset.
|
|
if (load) begin
|
|
next_state.macro = WORKING;
|
|
next_state.count = '0;
|
|
end
|
|
end
|
|
|
|
default:;
|
|
endcase
|
|
end
|
|
|
|
always_comb begin
|
|
valid = 0;
|
|
next_data = '0;
|
|
crc_out = '0;
|
|
|
|
case (state.macro)
|
|
IDLE: begin
|
|
valid = 0;
|
|
end
|
|
|
|
WORKING: begin
|
|
if (data[6'd46 - state.count]) begin
|
|
next_data = data ^ polyshift;
|
|
end else begin
|
|
next_data = data;
|
|
end
|
|
end
|
|
|
|
VALID: begin
|
|
valid = ~load;
|
|
next_data = data;
|
|
crc_out = data[6:0];
|
|
end
|
|
|
|
default:;
|
|
endcase
|
|
end
|
|
|
|
endmodule
|