mirror of
https://github.com/steve-m/hsdaoh-fpga.git
synced 2025-12-10 07:44:45 +01:00
add Tang nano 9K dual 12 bit ADC project
This commit is contained in:
parent
a9bc725209
commit
1339c06b11
6 changed files with 336 additions and 10 deletions
29
common/div3.v
Normal file
29
common/div3.v
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
module clk_div3(clk,reset, clk_out);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
output clk_out;
|
||||
|
||||
reg [1:0] pos_count, neg_count;
|
||||
wire [1:0] r_nxt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset)
|
||||
pos_count <= 0;
|
||||
else if (pos_count == 2)
|
||||
pos_count <= 0;
|
||||
else
|
||||
pos_count <= pos_count + 1;
|
||||
end
|
||||
|
||||
always @(negedge clk) begin
|
||||
if (reset)
|
||||
neg_count <=0;
|
||||
else if (neg_count == 2)
|
||||
neg_count <= 0;
|
||||
else
|
||||
neg_count<= neg_count +1;
|
||||
end
|
||||
|
||||
assign clk_out = ~((pos_count == 2) | (neg_count == 2));
|
||||
endmodule
|
||||
|
|
@ -14,8 +14,8 @@ module hsdaoh_core
|
|||
input wire clk_pixel,
|
||||
input wire fifo_empty,
|
||||
input wire fifo_aempty,
|
||||
output reg fifo_read_en,
|
||||
input wire [15:0] data_in
|
||||
output wire fifo_read_en,
|
||||
input wire [23:0] data_in
|
||||
);
|
||||
|
||||
parameter USE_CRC = 1;
|
||||
|
|
@ -48,6 +48,13 @@ module hsdaoh_core
|
|||
wire [11:0] screen_width;
|
||||
wire [10:0] screen_height;
|
||||
|
||||
reg read_en;
|
||||
reg [15:0] tenbit_data;
|
||||
reg [2:0] pack_state;
|
||||
|
||||
// For 10 bit mode, disable FIFO every four 20 bit words so we can pack them to 16 bit
|
||||
assign fifo_read_en = read_en && (pack_state != 1);
|
||||
|
||||
always @(posedge clk_pixel) begin
|
||||
|
||||
if (cy < screen_height) begin
|
||||
|
|
@ -68,9 +75,29 @@ always @(posedge clk_pixel) begin
|
|||
hdmi_data <= {last_line_crc, 8'h00};
|
||||
|
||||
end else if (cx < screen_width) begin
|
||||
if (fifo_read_en && !fifo_empty) begin
|
||||
if (read_en && !fifo_empty) begin
|
||||
// regular output of FIFO data
|
||||
hdmi_data <= {data_in[15:0], 8'h00};
|
||||
hdmi_data <= (pack_state == 2) ? {tenbit_data[15:0], 8'h00} : {data_in[11:4], data_in[23:16], 8'h00};
|
||||
|
||||
// packing of 24 bit to 16 bit
|
||||
case (pack_state)
|
||||
0:
|
||||
begin
|
||||
tenbit_data[7:0] <= {data_in[15:12], data_in[3:0]};
|
||||
pack_state <= 1;
|
||||
end
|
||||
1:
|
||||
begin
|
||||
tenbit_data[15:8] <= {data_in[15:12], data_in[3:0]};
|
||||
pack_state <= 2;
|
||||
end
|
||||
2:
|
||||
begin
|
||||
pack_state <= 0;
|
||||
end
|
||||
default:
|
||||
pack_state <= 0;
|
||||
endcase
|
||||
|
||||
// increment line payload counter
|
||||
line_word_cnt <= line_word_cnt + 1'b1;
|
||||
|
|
@ -79,7 +106,7 @@ always @(posedge clk_pixel) begin
|
|||
hdmi_data <= {idle_counter[15:8], idle_counter[7:0], 8'h00};
|
||||
|
||||
// increment idle counter
|
||||
idle_counter <= idle_counter + 1'b1;
|
||||
// idle_counter <= idle_counter + 1'b1;
|
||||
end
|
||||
end else
|
||||
line_word_cnt <= 16'h0000;
|
||||
|
|
@ -87,22 +114,22 @@ always @(posedge clk_pixel) begin
|
|||
// Enable reading before beginning of next line
|
||||
if ((cx == frame_width-1) && (cy != screen_height-1)) begin
|
||||
if (!fifo_empty)
|
||||
fifo_read_en = 1'b1;
|
||||
read_en = 1'b1;
|
||||
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-USE_CRC)
|
||||
fifo_read_en = 1'b0;
|
||||
read_en = 1'b0;
|
||||
end
|
||||
|
||||
// switch read off during blanking
|
||||
if (cy > screen_height)
|
||||
fifo_read_en = 1'b0;
|
||||
read_en = 1'b0;
|
||||
|
||||
// switch read off when FIFO has only one word remaining
|
||||
if (fifo_aempty)
|
||||
fifo_read_en = 1'b0;
|
||||
read_en = 1'b0;
|
||||
|
||||
// increment the frame counter at the end of the frame
|
||||
if ((cx == frame_width-1) && (cy == frame_height-1)) begin
|
||||
|
|
@ -111,7 +138,15 @@ always @(posedge clk_pixel) begin
|
|||
|
||||
// start FIFO readout
|
||||
if (!fifo_empty)
|
||||
fifo_read_en = 1'b1;
|
||||
read_en = 1'b1;
|
||||
end
|
||||
|
||||
// in order to align the packed data, stop the FIFO readout if we cannot complete a packing cycle
|
||||
// at the end of the frame. This ensures that each frame starts with pack_state 0
|
||||
// FIXME: only done at beginning of last line, should be removed
|
||||
if ((cy == screen_height-1) && read_en) begin
|
||||
if (pack_state == 2)
|
||||
read_en = 1'b0;
|
||||
end
|
||||
|
||||
if (cx == 0) begin
|
||||
|
|
@ -129,6 +164,9 @@ always @(posedge clk_pixel) begin
|
|||
10 : status_nibble <= frame_cnt[11:8];
|
||||
11 : status_nibble <= frame_cnt[15:12];
|
||||
14 : status_nibble <= { 3'b000, USE_CRC };
|
||||
92 : status_nibble <= 4'b0010; // set format ID = FPGA_12BIT_DUAL
|
||||
93 : status_nibble <= 4'b0001;
|
||||
94 : status_nibble <= 4'b0001;
|
||||
default : status_nibble <= 4'h0;
|
||||
endcase
|
||||
end
|
||||
|
|
|
|||
27
hsdaoh_nano9k_dualadc.gprj
Normal file
27
hsdaoh_nano9k_dualadc.gprj
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1" encoding="UTF-8"?>
|
||||
<!DOCTYPE gowin-fpga-project>
|
||||
<Project>
|
||||
<Template>FPGA</Template>
|
||||
<Version>5</Version>
|
||||
<Device name="GW1NR-9C" pn="GW1NR-LV9QN88PC6/I5">gw1nr9c-004</Device>
|
||||
<FileList>
|
||||
<File path="common/async_fifo/async_fifo.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/async_fifo/fifomem.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/async_fifo/rptr_empty.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/async_fifo/sync_r2w.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/async_fifo/sync_w2r.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/async_fifo/wptr_full.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/div3.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/hdmi/auxiliary_video_information_info_frame.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/hdmi/hdmi.v" type="file.verilog" enable="1"/>
|
||||
<File path="common/hdmi/packet_assembler.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/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_dualadc/top.v" type="file.verilog" enable="1"/>
|
||||
<File path="hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.cst" type="file.cst" enable="1"/>
|
||||
<File path="hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.sdc" type="file.sdc" enable="1"/>
|
||||
</FileList>
|
||||
</Project>
|
||||
65
hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.cst
Normal file
65
hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.cst
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
IO_LOC "sys_resetn" 4;
|
||||
IO_PORT "sys_resetn" PULL_MODE=UP;
|
||||
IO_LOC "sys_clk" 52;
|
||||
IO_PORT "sys_clk" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "tmds_d_p[0]" 71,70;
|
||||
IO_PORT "tmds_d_p[0]" PULL_MODE=NONE DRIVE=8;
|
||||
IO_LOC "tmds_d_p[1]" 73,72;
|
||||
IO_PORT "tmds_d_p[1]" PULL_MODE=NONE DRIVE=8;
|
||||
IO_LOC "tmds_d_p[2]" 75,74;
|
||||
IO_PORT "tmds_d_p[2]" PULL_MODE=NONE DRIVE=8;
|
||||
IO_LOC "tmds_clk_p" 69,68;
|
||||
IO_PORT "tmds_clk_p" PULL_MODE=NONE DRIVE=8;
|
||||
|
||||
IO_LOC "adc0_data[0]" 41;
|
||||
IO_PORT "adc0_data[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[1]" 35;
|
||||
IO_PORT "adc0_data[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[2]" 40;
|
||||
IO_PORT "adc0_data[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[3]" 34;
|
||||
IO_PORT "adc0_data[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[4]" 33;
|
||||
IO_PORT "adc0_data[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[5]" 30;
|
||||
IO_PORT "adc0_data[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[6]" 29;
|
||||
IO_PORT "adc0_data[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[7]" 28;
|
||||
IO_PORT "adc0_data[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[8]" 27;
|
||||
IO_PORT "adc0_data[8]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[9]" 26;
|
||||
IO_PORT "adc0_data[9]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[10]" 25;
|
||||
IO_PORT "adc0_data[10]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc0_data[11]" 38;
|
||||
IO_PORT "adc0_data[11]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
|
||||
IO_LOC "adc1_data[0]" 32;
|
||||
IO_PORT "adc1_data[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[1]" 31;
|
||||
IO_PORT "adc1_data[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[2]" 49;
|
||||
IO_PORT "adc1_data[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[3]" 48;
|
||||
IO_PORT "adc1_data[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[4]" 76;
|
||||
IO_PORT "adc1_data[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[5]" 57;
|
||||
IO_PORT "adc1_data[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[6]" 56;
|
||||
IO_PORT "adc1_data[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[7]" 55;
|
||||
IO_PORT "adc1_data[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[8]" 54;
|
||||
IO_PORT "adc1_data[8]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[9]" 53;
|
||||
IO_PORT "adc1_data[9]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[10]" 51;
|
||||
IO_PORT "adc1_data[10]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
IO_LOC "adc1_data[11]" 42;
|
||||
IO_PORT "adc1_data[11]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
|
||||
IO_LOC "adc_clkout" 36;
|
||||
IO_PORT "adc_clkout" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||
1
hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.sdc
Normal file
1
hsdaoh_nano9k_dualadc/hsdaoh_nano9k_dualadc.sdc
Normal file
|
|
@ -0,0 +1 @@
|
|||
create_clock -name sys_clk -period 37.04 [get_ports {sys_clk}] -add
|
||||
166
hsdaoh_nano9k_dualadc/top.v
Normal file
166
hsdaoh_nano9k_dualadc/top.v
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
// hsdaoh - High Speed Data Acquisition over HDMI
|
||||
// Dual 12 bit ADC top design for Tang Nano 9K
|
||||
// Copyright (C) 2024-25 by Steve Markgraf <steve@steve-m.de>
|
||||
// License: MIT
|
||||
|
||||
module top (
|
||||
sys_clk,
|
||||
sys_resetn,
|
||||
tmds_clk_n,
|
||||
tmds_clk_p,
|
||||
tmds_d_n,
|
||||
tmds_d_p,
|
||||
adc0_data,
|
||||
adc1_data,
|
||||
adc_clkout
|
||||
);
|
||||
input sys_clk;
|
||||
input sys_resetn;
|
||||
output wire tmds_clk_n;
|
||||
output wire tmds_clk_p;
|
||||
output wire [2:0] tmds_d_n;
|
||||
output wire [2:0] tmds_d_p;
|
||||
|
||||
input wire [11:0] adc0_data;
|
||||
input wire [11:0] adc1_data;
|
||||
output wire adc_clkout;
|
||||
|
||||
wire [2:0] tmds;
|
||||
wire clk_pixel;
|
||||
wire clk_pixel_x5;
|
||||
wire hdmi_pll_lock;
|
||||
|
||||
wire data_pll_out;
|
||||
wire clk_data;
|
||||
wire data_pll_lock;
|
||||
|
||||
assign adc_clkout = clk_data;
|
||||
|
||||
localparam HDMI_PLL_IDIV = 3;
|
||||
localparam HDMI_PLL_FBDIV = 46;
|
||||
localparam HDMI_PLL_ODIV = 2;
|
||||
|
||||
// PLL for HDMI clock
|
||||
rPLL #(
|
||||
.FCLKIN (27),
|
||||
.IDIV_SEL (HDMI_PLL_IDIV),
|
||||
.FBDIV_SEL (HDMI_PLL_FBDIV),
|
||||
.ODIV_SEL (HDMI_PLL_ODIV),
|
||||
.DEVICE ("GW1NR-9C")
|
||||
) hdmi_pll (
|
||||
.CLKIN(sys_clk),
|
||||
.CLKFB(1'b0),
|
||||
.RESET(1'b0),
|
||||
.RESET_P(1'b0),
|
||||
.FBDSEL(6'b0),
|
||||
.IDSEL(6'b0),
|
||||
.ODSEL(6'b0),
|
||||
.DUTYDA(4'b0),
|
||||
.PSDA(4'b0),
|
||||
.FDLY(4'b0),
|
||||
.CLKOUT(clk_pixel_x5),
|
||||
.LOCK(hdmi_pll_lock),
|
||||
.CLKOUTP(),
|
||||
.CLKOUTD(),
|
||||
.CLKOUTD3()
|
||||
);
|
||||
|
||||
CLKDIV #(
|
||||
.DIV_MODE(5),
|
||||
.GSREN("false")
|
||||
) div_5 (
|
||||
.CLKOUT(clk_pixel),
|
||||
.HCLKIN(clk_pixel_x5),
|
||||
.RESETN(hdmi_pll_lock),
|
||||
.CALIB(1'b0)
|
||||
);
|
||||
|
||||
// 120 MHz
|
||||
localparam DATA_PLL_IDIV = 8;
|
||||
localparam DATA_PLL_FBDIV = 39;
|
||||
localparam DATA_PLL_ODIV = 8;
|
||||
|
||||
// 120 MHz / 3 = 40 MHz
|
||||
clk_div3 clkdiv (.clk(data_pll_out),
|
||||
.reset (!hdmi_pll_lock),
|
||||
.clk_out(clk_data));
|
||||
|
||||
// PLL for data clock
|
||||
rPLL #(
|
||||
.FCLKIN (27),
|
||||
.IDIV_SEL (DATA_PLL_IDIV),
|
||||
.FBDIV_SEL (DATA_PLL_FBDIV),
|
||||
.ODIV_SEL (DATA_PLL_ODIV),
|
||||
.DEVICE ("GW1NR-9C")
|
||||
) data_pll (
|
||||
.CLKIN (sys_clk),
|
||||
.CLKFB (1'b0),
|
||||
.RESET (rst),
|
||||
.RESET_P (1'b0),
|
||||
.FBDSEL (6'b0),
|
||||
.IDSEL (6'b0),
|
||||
.ODSEL (6'b0),
|
||||
.DUTYDA (4'b0),
|
||||
.PSDA (4'b0),
|
||||
.FDLY (4'b0),
|
||||
.CLKOUT (data_pll_out),
|
||||
.LOCK (data_pll_lock),
|
||||
.CLKOUTP (),
|
||||
.CLKOUTD (),
|
||||
.CLKOUTD3 ()
|
||||
);
|
||||
|
||||
reg [23:0] fifo_in;
|
||||
|
||||
wire write_enable;
|
||||
|
||||
wire [23:0] fifo_out;
|
||||
wire fifo_empty;
|
||||
wire fifo_aempty;
|
||||
wire Full_o;
|
||||
|
||||
wire FifoHalfFull;
|
||||
wire FifoFull;
|
||||
|
||||
wire fifo_rd_en_i;
|
||||
|
||||
async_fifo #(
|
||||
.DSIZE(24),
|
||||
.ASIZE($clog2(8192)), // 3 + (1982 * 4) = 7931 => at least 8K entries to buffer 4 lines during VSYNC
|
||||
.FALLTHROUGH("FALSE")
|
||||
) fifo (
|
||||
.wclk(clk_data),
|
||||
.wrst_n(hdmi_pll_lock),
|
||||
.winc(write_enable),
|
||||
.wdata(fifo_in),
|
||||
.wfull(FifoFull),
|
||||
.awfull(FifoHalfFull), //fixme
|
||||
.rclk(clk_pixel),
|
||||
.rrst_n(hdmi_pll_lock),
|
||||
.rinc(fifo_rd_en_i),
|
||||
.rdata(fifo_out),
|
||||
.rempty(fifo_empty),
|
||||
.arempty(fifo_aempty)
|
||||
);
|
||||
|
||||
hsdaoh_core hsdaoh (
|
||||
.rstn(hdmi_pll_lock),
|
||||
.tmds_clk_n(tmds_clk_n),
|
||||
.tmds_clk_p(tmds_clk_p),
|
||||
.tmds_d_n(tmds_d_n),
|
||||
.tmds_d_p(tmds_d_p),
|
||||
.clk_pixel_x5(clk_pixel_x5),
|
||||
.clk_pixel(clk_pixel),
|
||||
.fifo_empty(fifo_empty),
|
||||
.fifo_aempty(fifo_aempty),
|
||||
.fifo_read_en(fifo_rd_en_i),
|
||||
.data_in(fifo_out)
|
||||
);
|
||||
|
||||
assign write_enable = 1'b1;
|
||||
|
||||
always @(posedge clk_data) begin
|
||||
fifo_in <= {adc0_data[11:0], adc1_data[11:0]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Add table
Reference in a new issue