mirror of
https://github.com/steve-m/hsdaoh-fpga.git
synced 2025-12-09 23:34: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
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
reg [23:0] hdmi_data = 24'h000000;
|
||||
|
|
@ -35,11 +50,24 @@ module hsdaoh_core
|
|||
|
||||
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
|
||||
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
|
||||
// regular output of FIFO data
|
||||
hdmi_data <= {data_in[15:0], 8'h00};
|
||||
|
|
@ -57,16 +85,19 @@ always @(posedge clk_pixel) begin
|
|||
line_word_cnt <= 16'h0000;
|
||||
|
||||
// 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;
|
||||
|
||||
// switch read off during blanking
|
||||
if (cy > screen_height)
|
||||
fifo_read_en = 1'b0;
|
||||
end
|
||||
|
||||
// switch read off at end of line before sending the word counter
|
||||
// -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;
|
||||
|
||||
// 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];
|
||||
10 : status_nibble <= frame_cnt[11:8];
|
||||
11 : status_nibble <= frame_cnt[15:12];
|
||||
14 : status_nibble <= { 3'b000, USE_CRC };
|
||||
default : status_nibble <= 4'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
wire tmds_clock;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<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/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="hsdaoh_nano20k_test/top.v" type="file.verilog" 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/serializer.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="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"/>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<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/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="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"/>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<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/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="hsdaoh_primer20k_test/top.v" type="file.verilog" 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/serializer.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="hsdaoh_primer25k_test/top.v" type="file.verilog" enable="1"/>
|
||||
<File path="hsdaoh_primer25k_test/hsdaoh_primer25k_test.cst" type="file.cst" enable="1"/>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue