From e828df0807477a4837b0c6258b0ebcda7bc77536 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Fri, 8 Apr 2022 00:50:28 -0500 Subject: [PATCH] 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. --- hw/fpga/crc7.sv | 105 ++++++++++++++++++++++++++++++++++++++++++ hw/fpga/super6502.qsf | 1 + 2 files changed, 106 insertions(+) create mode 100644 hw/fpga/crc7.sv diff --git a/hw/fpga/crc7.sv b/hw/fpga/crc7.sv new file mode 100644 index 0000000..960f22c --- /dev/null +++ b/hw/fpga/crc7.sv @@ -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 diff --git a/hw/fpga/super6502.qsf b/hw/fpga/super6502.qsf index fdb7289..053e5d2 100644 --- a/hw/fpga/super6502.qsf +++ b/hw/fpga/super6502.qsf @@ -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_J21 -to DRAM_UDQM 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 board_io.sv set_global_assignment -name SYSTEMVERILOG_FILE sdram.sv