mirror of
https://github.com/steve-m/hsdaoh-fpga.git
synced 2025-12-10 07:44:45 +01:00
hsdaoh_core: add CRC16 checksum support
Output is identical to the implementation in hsdaoh-rp2350.
This commit is contained in:
parent
8b9e1457ea
commit
1b2d011581
7 changed files with 149 additions and 27 deletions
86
common/hsdaoh/crc16_ccitt.v
Normal file
86
common/hsdaoh/crc16_ccitt.v
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* -----------------------------------------------------------------------------------
|
||||||
|
* Module Name : crc16_ccitt
|
||||||
|
* Generated by : https://github.com/PXVI/ip_parallel_custom_crc_gerator_verilog
|
||||||
|
* Author : pxvi
|
||||||
|
* Description : Parallel CRC( 16-bit ) module with 16-bit data input.
|
||||||
|
* Polynomial Degrees [ 16 12 5 0 ]
|
||||||
|
* -----------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 k-sva
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the Software), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------------- */
|
||||||
|
module crc16_ccitt #( parameter RESET_SEED = 'hffff )(
|
||||||
|
input wire CLK,
|
||||||
|
input wire RSTn,
|
||||||
|
|
||||||
|
input wire [15:0] data_in,
|
||||||
|
input wire enable,
|
||||||
|
input wire clear,
|
||||||
|
|
||||||
|
output [15:0] CRC
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
reg [16-1:0] Mout_p, Mout_n;
|
||||||
|
|
||||||
|
always@( posedge CLK )
|
||||||
|
begin
|
||||||
|
Mout_p <= Mout_n;
|
||||||
|
|
||||||
|
if( !RSTn )
|
||||||
|
begin
|
||||||
|
Mout_p <= RESET_SEED;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always@( * )
|
||||||
|
begin
|
||||||
|
Mout_n = Mout_p;
|
||||||
|
|
||||||
|
if( clear )
|
||||||
|
begin
|
||||||
|
Mout_n = RESET_SEED;
|
||||||
|
end
|
||||||
|
else if( enable )
|
||||||
|
begin
|
||||||
|
Mout_n[0] = data_in[0] ^ data_in[4] ^ data_in[8] ^ data_in[11] ^ data_in[12] ^ Mout_p[0] ^ Mout_p[4] ^ Mout_p[8] ^ Mout_p[11] ^ Mout_p[12] ;
|
||||||
|
Mout_n[1] = data_in[1] ^ data_in[5] ^ data_in[9] ^ data_in[12] ^ data_in[13] ^ Mout_p[1] ^ Mout_p[5] ^ Mout_p[9] ^ Mout_p[12] ^ Mout_p[13] ;
|
||||||
|
Mout_n[2] = data_in[2] ^ data_in[6] ^ data_in[10] ^ data_in[13] ^ data_in[14] ^ Mout_p[2] ^ Mout_p[6] ^ Mout_p[10] ^ Mout_p[13] ^ Mout_p[14] ;
|
||||||
|
Mout_n[3] = data_in[3] ^ data_in[7] ^ data_in[11] ^ data_in[14] ^ data_in[15] ^ Mout_p[3] ^ Mout_p[7] ^ Mout_p[11] ^ Mout_p[14] ^ Mout_p[15] ;
|
||||||
|
Mout_n[4] = data_in[4] ^ data_in[8] ^ data_in[12] ^ data_in[15] ^ Mout_p[4] ^ Mout_p[8] ^ Mout_p[12] ^ Mout_p[15] ;
|
||||||
|
Mout_n[5] = data_in[0] ^ data_in[4] ^ data_in[5] ^ data_in[8] ^ data_in[9] ^ data_in[11] ^ data_in[12] ^ data_in[13] ^ Mout_p[0] ^ Mout_p[4] ^ Mout_p[5] ^ Mout_p[8] ^ Mout_p[9] ^ Mout_p[11] ^ Mout_p[12] ^ Mout_p[13] ;
|
||||||
|
Mout_n[6] = data_in[1] ^ data_in[5] ^ data_in[6] ^ data_in[9] ^ data_in[10] ^ data_in[12] ^ data_in[13] ^ data_in[14] ^ Mout_p[1] ^ Mout_p[5] ^ Mout_p[6] ^ Mout_p[9] ^ Mout_p[10] ^ Mout_p[12] ^ Mout_p[13] ^ Mout_p[14] ;
|
||||||
|
Mout_n[7] = data_in[2] ^ data_in[6] ^ data_in[7] ^ data_in[10] ^ data_in[11] ^ data_in[13] ^ data_in[14] ^ data_in[15] ^ Mout_p[2] ^ Mout_p[6] ^ Mout_p[7] ^ Mout_p[10] ^ Mout_p[11] ^ Mout_p[13] ^ Mout_p[14] ^ Mout_p[15] ;
|
||||||
|
Mout_n[8] = data_in[3] ^ data_in[7] ^ data_in[8] ^ data_in[11] ^ data_in[12] ^ data_in[14] ^ data_in[15] ^ Mout_p[3] ^ Mout_p[7] ^ Mout_p[8] ^ Mout_p[11] ^ Mout_p[12] ^ Mout_p[14] ^ Mout_p[15] ;
|
||||||
|
Mout_n[9] = data_in[4] ^ data_in[8] ^ data_in[9] ^ data_in[12] ^ data_in[13] ^ data_in[15] ^ Mout_p[4] ^ Mout_p[8] ^ Mout_p[9] ^ Mout_p[12] ^ Mout_p[13] ^ Mout_p[15] ;
|
||||||
|
Mout_n[10] = data_in[5] ^ data_in[9] ^ data_in[10] ^ data_in[13] ^ data_in[14] ^ Mout_p[5] ^ Mout_p[9] ^ Mout_p[10] ^ Mout_p[13] ^ Mout_p[14] ;
|
||||||
|
Mout_n[11] = data_in[6] ^ data_in[10] ^ data_in[11] ^ data_in[14] ^ data_in[15] ^ Mout_p[6] ^ Mout_p[10] ^ Mout_p[11] ^ Mout_p[14] ^ Mout_p[15] ;
|
||||||
|
Mout_n[12] = data_in[0] ^ data_in[4] ^ data_in[7] ^ data_in[8] ^ data_in[15] ^ Mout_p[0] ^ Mout_p[4] ^ Mout_p[7] ^ Mout_p[8] ^ Mout_p[15] ;
|
||||||
|
Mout_n[13] = data_in[1] ^ data_in[5] ^ data_in[8] ^ data_in[9] ^ Mout_p[1] ^ Mout_p[5] ^ Mout_p[8] ^ Mout_p[9] ;
|
||||||
|
Mout_n[14] = data_in[2] ^ data_in[6] ^ data_in[9] ^ data_in[10] ^ Mout_p[2] ^ Mout_p[6] ^ Mout_p[9] ^ Mout_p[10] ;
|
||||||
|
Mout_n[15] = data_in[3] ^ data_in[7] ^ data_in[10] ^ data_in[11] ^ Mout_p[3] ^ Mout_p[7] ^ Mout_p[10] ^ Mout_p[11] ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign CRC = Mout_p;
|
||||||
|
endmodule
|
||||||
|
|
@ -18,6 +18,21 @@ module hsdaoh_core
|
||||||
input wire [15:0] data_in
|
input wire [15:0] data_in
|
||||||
);
|
);
|
||||||
|
|
||||||
|
parameter USE_CRC = 1;
|
||||||
|
|
||||||
|
reg crc_enable = 1'b0;
|
||||||
|
wire [15:0] crc_out;
|
||||||
|
reg [15:0] last_line_crc;
|
||||||
|
|
||||||
|
crc16_ccitt crc16_ccitt (
|
||||||
|
.CLK(clk_pixel),
|
||||||
|
.RSTn(rstn),
|
||||||
|
.data_in({hdmi_data[15:8], hdmi_data[23:16]}),
|
||||||
|
.enable(crc_enable),
|
||||||
|
.clear(!crc_enable),
|
||||||
|
.CRC(crc_out)
|
||||||
|
);
|
||||||
|
|
||||||
localparam [31:0] MAGIC = 32'hda7acab1;
|
localparam [31:0] MAGIC = 32'hda7acab1;
|
||||||
|
|
||||||
reg [23:0] hdmi_data = 24'h000000;
|
reg [23:0] hdmi_data = 24'h000000;
|
||||||
|
|
@ -35,11 +50,24 @@ module hsdaoh_core
|
||||||
|
|
||||||
always @(posedge clk_pixel) begin
|
always @(posedge clk_pixel) begin
|
||||||
|
|
||||||
if ((cx == screen_width-1) && (cy < screen_height)) begin
|
if (cy < screen_height) begin
|
||||||
|
if (USE_CRC && (cx == 0))
|
||||||
|
crc_enable <= 1'b1;
|
||||||
|
|
||||||
|
if (USE_CRC && (cx == screen_width+1)) begin
|
||||||
|
last_line_crc <= crc_out;
|
||||||
|
crc_enable <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (cx == screen_width-1) begin
|
||||||
// last word of line contains counter of words per line
|
// last word of line contains counter of words per line
|
||||||
hdmi_data <= {status_nibble[3:0], line_word_cnt[11:0], 8'h00};
|
hdmi_data <= {status_nibble[3:0], line_word_cnt[11:0], 8'h00};
|
||||||
|
|
||||||
end else if ((cx < screen_width) && (cy < screen_height)) begin
|
end else if (USE_CRC && (cx == screen_width-2)) begin
|
||||||
|
// second last word contains CRC
|
||||||
|
hdmi_data <= {last_line_crc, 8'h00};
|
||||||
|
|
||||||
|
end else if (cx < screen_width) begin
|
||||||
if (fifo_read_en && !fifo_empty) begin
|
if (fifo_read_en && !fifo_empty) begin
|
||||||
// regular output of FIFO data
|
// regular output of FIFO data
|
||||||
hdmi_data <= {data_in[15:0], 8'h00};
|
hdmi_data <= {data_in[15:0], 8'h00};
|
||||||
|
|
@ -57,16 +85,19 @@ always @(posedge clk_pixel) begin
|
||||||
line_word_cnt <= 16'h0000;
|
line_word_cnt <= 16'h0000;
|
||||||
|
|
||||||
// Enable reading before beginning of next line
|
// Enable reading before beginning of next line
|
||||||
if ((cx == frame_width-1) && (cy < screen_height-1) && !fifo_empty)
|
if ((cx == frame_width-1) && (cy != screen_height-1)) begin
|
||||||
|
if (!fifo_empty)
|
||||||
fifo_read_en = 1'b1;
|
fifo_read_en = 1'b1;
|
||||||
|
end
|
||||||
// switch read off during blanking
|
|
||||||
if (cy > screen_height)
|
|
||||||
fifo_read_en = 1'b0;
|
|
||||||
|
|
||||||
// switch read off at end of line before sending the word counter
|
// switch read off at end of line before sending the word counter
|
||||||
// -2 because the last word is reserved (line_word_cnt and metadata)
|
// -2 because the last word is reserved (line_word_cnt and metadata)
|
||||||
if ((cx == screen_width-2) && (cy < screen_height))
|
if (cx == screen_width-2-USE_CRC)
|
||||||
|
fifo_read_en = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// switch read off during blanking
|
||||||
|
if (cy > screen_height)
|
||||||
fifo_read_en = 1'b0;
|
fifo_read_en = 1'b0;
|
||||||
|
|
||||||
// switch read off when FIFO has only one word remaining
|
// switch read off when FIFO has only one word remaining
|
||||||
|
|
@ -97,10 +128,10 @@ always @(posedge clk_pixel) begin
|
||||||
9 : status_nibble <= frame_cnt[7:4];
|
9 : status_nibble <= frame_cnt[7:4];
|
||||||
10 : status_nibble <= frame_cnt[11:8];
|
10 : status_nibble <= frame_cnt[11:8];
|
||||||
11 : status_nibble <= frame_cnt[15:12];
|
11 : status_nibble <= frame_cnt[15:12];
|
||||||
|
14 : status_nibble <= { 3'b000, USE_CRC };
|
||||||
default : status_nibble <= 4'h0;
|
default : status_nibble <= 4'h0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wire tmds_clock;
|
wire tmds_clock;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/hsdaoh/crc16_ccitt.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano20k_test/top.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_nano20k_test/top.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano20k_test/hsdaoh_nano20k_test.cst" type="file.cst" enable="1"/>
|
<File path="hsdaoh_nano20k_test/hsdaoh_nano20k_test.cst" type="file.cst" enable="1"/>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/hsdaoh/crc16_ccitt.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano4k_test/fifo_hs/fifo_hs.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_nano4k_test/fifo_hs/fifo_hs.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano4k_test/top.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_nano4k_test/top.v" type="file.verilog" enable="1"/>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/hsdaoh/crc16_ccitt.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano9k_test/fifo_hs/fifo_hs.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_nano9k_test/fifo_hs/fifo_hs.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_nano9k_test/top.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_nano9k_test/top.v" type="file.verilog" enable="1"/>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/hsdaoh/crc16_ccitt.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_primer20k_test/top.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_primer20k_test/top.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_primer20k_test/hsdaoh_primer20k_test.cst" type="file.cst" enable="1"/>
|
<File path="hsdaoh_primer20k_test/hsdaoh_primer20k_test.cst" type="file.cst" enable="1"/>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/packet_picker.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/serializer.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
<File path="common/hdmi/tmds_channel.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/hsdaoh/crc16_ccitt.v" type="file.verilog" enable="1"/>
|
||||||
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
<File path="common/hsdaoh/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_primer25k_test/top.v" type="file.verilog" enable="1"/>
|
<File path="hsdaoh_primer25k_test/top.v" type="file.verilog" enable="1"/>
|
||||||
<File path="hsdaoh_primer25k_test/hsdaoh_primer25k_test.cst" type="file.cst" enable="1"/>
|
<File path="hsdaoh_primer25k_test/hsdaoh_primer25k_test.cst" type="file.cst" enable="1"/>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue