Add crc7 module
This module takes in a 40 bit word and generates the 7 bit crc7 appropriate for an SD card. It does not use any fancy parallel algorithm, it does it 1 bit at a time.
This commit is contained in:
105
hw/fpga/crc7.sv
Normal file
105
hw/fpga/crc7.sv
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
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;
|
||||||
|
crc_out = data[6:0];
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -350,6 +350,7 @@ set_location_assignment PIN_V22 -to DRAM_LDQM
|
|||||||
set_location_assignment PIN_U22 -to DRAM_RAS_N
|
set_location_assignment PIN_U22 -to DRAM_RAS_N
|
||||||
set_location_assignment PIN_J21 -to DRAM_UDQM
|
set_location_assignment PIN_J21 -to DRAM_UDQM
|
||||||
set_location_assignment PIN_V20 -to DRAM_WE_N
|
set_location_assignment PIN_V20 -to DRAM_WE_N
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE crc7.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE memory_mapper.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE memory_mapper.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE board_io.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE board_io.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE sdram.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE sdram.sv
|
||||||
|
|||||||
Reference in New Issue
Block a user