mirror of
https://github.com/steve-m/hsdaoh-fpga.git
synced 2025-12-10 07:44:45 +01:00
import hsdaohSDR FPGA design
This commit is contained in:
parent
bd6201e4ac
commit
1ccf7399b8
9 changed files with 1456 additions and 10 deletions
|
|
@ -14,8 +14,9 @@ module hsdaoh_core
|
||||||
input wire clk_pixel,
|
input wire clk_pixel,
|
||||||
input wire fifo_empty,
|
input wire fifo_empty,
|
||||||
input wire fifo_aempty,
|
input wire fifo_aempty,
|
||||||
output reg fifo_read_en,
|
output wire fifo_read_en,
|
||||||
input wire [15:0] data_in
|
input wire [19:0] data_in,
|
||||||
|
input wire tenbit_enable_in
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam [31:0] MAGIC = 32'hda7acab1;
|
localparam [31:0] MAGIC = 32'hda7acab1;
|
||||||
|
|
@ -25,6 +26,11 @@ module hsdaoh_core
|
||||||
reg [15:0] idle_counter = 16'h0000;
|
reg [15:0] idle_counter = 16'h0000;
|
||||||
reg [15:0] line_word_cnt = 16'h00;
|
reg [15:0] line_word_cnt = 16'h00;
|
||||||
reg [3:0] status_nibble = 4'h0;
|
reg [3:0] status_nibble = 4'h0;
|
||||||
|
reg read_en;
|
||||||
|
reg [2:0] pack_state;
|
||||||
|
reg [3:0] pack_sequence_start;
|
||||||
|
reg [15:0] tenbit_data;
|
||||||
|
reg tenbit_enabled = 1'b1;
|
||||||
|
|
||||||
wire [11:0] cx;
|
wire [11:0] cx;
|
||||||
wire [10:0] cy;
|
wire [10:0] cy;
|
||||||
|
|
@ -33,6 +39,9 @@ module hsdaoh_core
|
||||||
wire [11:0] screen_width;
|
wire [11:0] screen_width;
|
||||||
wire [10:0] screen_height;
|
wire [10:0] screen_height;
|
||||||
|
|
||||||
|
// 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 != 3) || !tenbit_enabled);
|
||||||
|
|
||||||
always @(posedge clk_pixel) begin
|
always @(posedge clk_pixel) begin
|
||||||
|
|
||||||
if ((cx == screen_width-1) && (cy < screen_height)) begin
|
if ((cx == screen_width-1) && (cy < screen_height)) begin
|
||||||
|
|
@ -40,9 +49,43 @@ always @(posedge clk_pixel) begin
|
||||||
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 ((cx < screen_width) && (cy < screen_height)) 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};
|
// regular output of FIFO data
|
||||||
|
hdmi_data <= (tenbit_enabled && (pack_state == 4)) ? {tenbit_data[15:0], 8'h00} : {data_in[19:12], data_in[9:2], 8'h00};
|
||||||
|
|
||||||
|
if (tenbit_enabled) begin
|
||||||
|
// for 10 bit IQ samples, we need to pack them
|
||||||
|
case (pack_state)
|
||||||
|
0:
|
||||||
|
begin
|
||||||
|
tenbit_data[3:0] <= {data_in[1:0], data_in[11:10]};
|
||||||
|
pack_state <= 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
begin
|
||||||
|
tenbit_data[7:4] <= {data_in[1:0], data_in[11:10]};
|
||||||
|
pack_state <= 2;
|
||||||
|
end
|
||||||
|
2:
|
||||||
|
begin
|
||||||
|
tenbit_data[11:8] <= {data_in[1:0], data_in[11:10]};
|
||||||
|
pack_state <= 3;
|
||||||
|
end
|
||||||
|
3:
|
||||||
|
begin
|
||||||
|
tenbit_data[15:12] <= {data_in[1:0], data_in[11:10]};
|
||||||
|
pack_state <= 4;
|
||||||
|
end
|
||||||
|
4:
|
||||||
|
begin
|
||||||
|
pack_state <= 0;
|
||||||
|
end
|
||||||
|
default:
|
||||||
|
pack_state <= 0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// increment line payload counter
|
// increment line payload counter
|
||||||
line_word_cnt <= line_word_cnt + 1'b1;
|
line_word_cnt <= line_word_cnt + 1'b1;
|
||||||
|
|
@ -59,29 +102,42 @@ always @(posedge clk_pixel) begin
|
||||||
|
|
||||||
// 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) && !fifo_empty)
|
||||||
fifo_read_en = 1'b1;
|
read_en = 1'b1;
|
||||||
|
|
||||||
// switch read off during blanking
|
// switch read off during blanking
|
||||||
if (cy > screen_height)
|
if (cy > screen_height)
|
||||||
fifo_read_en = 1'b0;
|
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) && (cy < screen_height))
|
||||||
fifo_read_en = 1'b0;
|
read_en = 1'b0;
|
||||||
|
|
||||||
// switch read off when FIFO has only one word remaining
|
// switch read off when FIFO has only one word remaining
|
||||||
if (fifo_aempty)
|
if (fifo_aempty)
|
||||||
fifo_read_en = 1'b0;
|
read_en = 1'b0;
|
||||||
|
|
||||||
|
// 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 (tenbit_enabled && (cy == screen_height-1) && read_en) begin
|
||||||
|
if (pack_state == 4)
|
||||||
|
read_en = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
// increment the frame counter at the end of the frame
|
// increment the frame counter at the end of the frame
|
||||||
if ((cx == frame_width-1) && (cy == frame_height-1)) begin
|
if ((cx == frame_width-1) && (cy == frame_height-1)) begin
|
||||||
frame_cnt <= frame_cnt + 1'b1;
|
frame_cnt <= frame_cnt + 1'b1;
|
||||||
line_word_cnt <= 16'h0000;
|
line_word_cnt <= 16'h0000;
|
||||||
|
// latch the current state of the pack sequence for the beginning of the next frame,
|
||||||
|
// which we transfer in the metadata so the host knows how to unpack the data
|
||||||
|
pack_sequence_start <= pack_state;
|
||||||
|
pack_state <= 0;
|
||||||
|
tenbit_enabled <= tenbit_enable_in;
|
||||||
|
|
||||||
// start FIFO readout
|
// start FIFO readout
|
||||||
if (!fifo_empty)
|
if (!fifo_empty)
|
||||||
fifo_read_en = 1'b1;
|
read_en = 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (cx == 0) begin
|
if (cx == 0) begin
|
||||||
|
|
@ -98,6 +154,8 @@ 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];
|
||||||
|
12 : status_nibble <= pack_sequence_start;
|
||||||
|
13 : status_nibble <= {3'b000, tenbit_enabled};
|
||||||
default : status_nibble <= 4'h0;
|
default : status_nibble <= 4'h0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
|
||||||
567
common/uart_i2c_bridge/i2c_master.v
Normal file
567
common/uart_i2c_bridge/i2c_master.v
Normal file
|
|
@ -0,0 +1,567 @@
|
||||||
|
// Tiny but mighty I2C master
|
||||||
|
// Copyright (c) 2021-2024 Artin Isagholian <artinisagholian@gmail.com>
|
||||||
|
// https://github.com/0xArt/Tiny_But_Mighty_I2C_Master_Verilog
|
||||||
|
// License: GPL V3.0
|
||||||
|
//
|
||||||
|
// converted to Verilog and extended with the 'got_acknowledge' output for hsdaoh
|
||||||
|
|
||||||
|
module i2c_master (
|
||||||
|
clock,
|
||||||
|
reset_n,
|
||||||
|
enable,
|
||||||
|
read_write,
|
||||||
|
mosi_data,
|
||||||
|
register_address,
|
||||||
|
device_address,
|
||||||
|
divider,
|
||||||
|
miso_data,
|
||||||
|
busy,
|
||||||
|
got_acknowledge,
|
||||||
|
external_serial_data,
|
||||||
|
external_serial_clock
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam S_IDLE = 0;
|
||||||
|
localparam S_START = 1;
|
||||||
|
localparam S_WRITE_ADDR_W = 2;
|
||||||
|
localparam S_CHECK_ACK = 3;
|
||||||
|
localparam S_WRITE_REG_ADDR = 4;
|
||||||
|
localparam S_RESTART = 5;
|
||||||
|
localparam S_WRITE_ADDR_R = 6;
|
||||||
|
localparam S_READ_REG = 7;
|
||||||
|
localparam S_SEND_NACK = 8;
|
||||||
|
localparam S_SEND_STOP = 9;
|
||||||
|
localparam S_WRITE_REG_DATA = 10;
|
||||||
|
localparam S_WRITE_REG_ADDR_MSB = 11;
|
||||||
|
localparam S_WRITE_REG_DATA_MSB = 12;
|
||||||
|
localparam S_READ_REG_MSB = 13;
|
||||||
|
localparam S_SEND_ACK = 14;
|
||||||
|
|
||||||
|
parameter DATA_WIDTH = 8;
|
||||||
|
parameter REGISTER_WIDTH = 8;
|
||||||
|
parameter ADDRESS_WIDTH = 7;
|
||||||
|
input wire clock;
|
||||||
|
input wire reset_n;
|
||||||
|
input wire enable;
|
||||||
|
input wire read_write;
|
||||||
|
input wire [DATA_WIDTH - 1:0] mosi_data;
|
||||||
|
input wire [REGISTER_WIDTH - 1:0] register_address;
|
||||||
|
input wire [ADDRESS_WIDTH - 1:0] device_address;
|
||||||
|
input wire [15:0] divider;
|
||||||
|
output reg [DATA_WIDTH - 1:0] miso_data;
|
||||||
|
output reg busy;
|
||||||
|
output reg got_acknowledge;
|
||||||
|
inout external_serial_data;
|
||||||
|
inout external_serial_clock;
|
||||||
|
reg [3:0] state;
|
||||||
|
reg [3:0] _state;
|
||||||
|
reg [3:0] post_state;
|
||||||
|
reg [3:0] _post_state;
|
||||||
|
reg serial_clock;
|
||||||
|
reg _serial_clock;
|
||||||
|
reg [ADDRESS_WIDTH:0] saved_device_address;
|
||||||
|
reg [ADDRESS_WIDTH:0] _saved_device_address;
|
||||||
|
reg [REGISTER_WIDTH - 1:0] saved_register_address;
|
||||||
|
reg [REGISTER_WIDTH - 1:0] _saved_register_address;
|
||||||
|
reg [DATA_WIDTH - 1:0] saved_mosi_data;
|
||||||
|
reg [DATA_WIDTH - 1:0] _saved_mosi_data;
|
||||||
|
reg [1:0] process_counter;
|
||||||
|
reg [1:0] _process_counter;
|
||||||
|
reg [7:0] bit_counter;
|
||||||
|
reg [7:0] _bit_counter;
|
||||||
|
reg serial_data;
|
||||||
|
reg _serial_data;
|
||||||
|
reg post_serial_data;
|
||||||
|
reg _post_serial_data;
|
||||||
|
reg last_acknowledge;
|
||||||
|
reg _last_acknowledge;
|
||||||
|
reg _saved_read_write;
|
||||||
|
reg saved_read_write;
|
||||||
|
reg [15:0] divider_counter;
|
||||||
|
reg [15:0] _divider_counter;
|
||||||
|
reg divider_tick;
|
||||||
|
reg [DATA_WIDTH - 1:0] _miso_data;
|
||||||
|
reg _busy;
|
||||||
|
reg _got_acknowledge;
|
||||||
|
reg serial_data_output_enable;
|
||||||
|
reg serial_clock_output_enable;
|
||||||
|
assign external_serial_clock = (serial_clock_output_enable ? serial_clock : 1'bz);
|
||||||
|
assign external_serial_data = (serial_data_output_enable ? serial_data : 1'bz);
|
||||||
|
always @(*) begin
|
||||||
|
_state = state;
|
||||||
|
_post_state = post_state;
|
||||||
|
_process_counter = process_counter;
|
||||||
|
_bit_counter = bit_counter;
|
||||||
|
_last_acknowledge = last_acknowledge;
|
||||||
|
_miso_data = miso_data;
|
||||||
|
_saved_read_write = saved_read_write;
|
||||||
|
_busy = busy;
|
||||||
|
_got_acknowledge = got_acknowledge;
|
||||||
|
_divider_counter = divider_counter;
|
||||||
|
_saved_register_address = saved_register_address;
|
||||||
|
_saved_device_address = saved_device_address;
|
||||||
|
_saved_mosi_data = saved_mosi_data;
|
||||||
|
_serial_data = serial_data;
|
||||||
|
_serial_clock = serial_clock;
|
||||||
|
_post_serial_data = post_serial_data;
|
||||||
|
if (divider_counter == divider) begin
|
||||||
|
_divider_counter = 0;
|
||||||
|
divider_tick = 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
_divider_counter = divider_counter + 1;
|
||||||
|
divider_tick = 0;
|
||||||
|
end
|
||||||
|
if ((((state != S_IDLE) && (state != S_CHECK_ACK)) && (state != S_READ_REG)) && (state != S_READ_REG_MSB))
|
||||||
|
serial_data_output_enable = 1;
|
||||||
|
else
|
||||||
|
serial_data_output_enable = 0;
|
||||||
|
if (((state != S_IDLE) && (process_counter != 1)) && (process_counter != 2))
|
||||||
|
serial_clock_output_enable = 1;
|
||||||
|
else
|
||||||
|
serial_clock_output_enable = 0;
|
||||||
|
case (state)
|
||||||
|
S_IDLE: begin
|
||||||
|
_process_counter = 0;
|
||||||
|
_bit_counter = 0;
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_busy = 0;
|
||||||
|
_saved_read_write = read_write;
|
||||||
|
_saved_register_address = register_address;
|
||||||
|
_saved_device_address = {device_address, 1'b0};
|
||||||
|
_saved_mosi_data = mosi_data;
|
||||||
|
_serial_data = 1;
|
||||||
|
_serial_clock = 1;
|
||||||
|
if (enable) begin
|
||||||
|
_got_acknowledge = 0;
|
||||||
|
_state = S_START;
|
||||||
|
_post_state = S_WRITE_ADDR_W;
|
||||||
|
_busy = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
S_START:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: _process_counter = 1;
|
||||||
|
1: begin
|
||||||
|
_serial_data = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_bit_counter = 8;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_process_counter = 0;
|
||||||
|
_state = post_state;
|
||||||
|
_serial_data = saved_device_address[ADDRESS_WIDTH];
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_ADDR_W:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1)
|
||||||
|
_process_counter = 2;
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_post_serial_data = saved_register_address[REGISTER_WIDTH - 1];
|
||||||
|
if (REGISTER_WIDTH == 16)
|
||||||
|
_post_state = S_WRITE_REG_ADDR_MSB;
|
||||||
|
else
|
||||||
|
_post_state = S_WRITE_REG_ADDR;
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
_bit_counter = 8;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_device_address[bit_counter - 1];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_CHECK_ACK:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
if (external_serial_data == 0)
|
||||||
|
_last_acknowledge = 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (last_acknowledge == 1) begin
|
||||||
|
_got_acknowledge = 1;
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_serial_data = post_serial_data;
|
||||||
|
_state = post_state;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
_got_acknowledge = 0;
|
||||||
|
_state = S_SEND_STOP;
|
||||||
|
end
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_REG_ADDR_MSB:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_post_state = S_WRITE_REG_ADDR;
|
||||||
|
_post_serial_data = saved_register_address[7];
|
||||||
|
_bit_counter = 8;
|
||||||
|
_serial_data = 0;
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_register_address[bit_counter + 7];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_REG_ADDR:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
if (read_write == 0) begin
|
||||||
|
if (DATA_WIDTH == 16) begin
|
||||||
|
_post_state = S_WRITE_REG_DATA_MSB;
|
||||||
|
_post_serial_data = saved_mosi_data[15];
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
_post_state = S_WRITE_REG_DATA;
|
||||||
|
_post_serial_data = saved_mosi_data[7];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
_post_state = S_RESTART;
|
||||||
|
_post_serial_data = 1;
|
||||||
|
end
|
||||||
|
_bit_counter = 8;
|
||||||
|
_serial_data = 0;
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_register_address[bit_counter - 1];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_REG_DATA_MSB:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
_post_state = S_WRITE_REG_DATA;
|
||||||
|
_post_serial_data = saved_mosi_data[7];
|
||||||
|
_bit_counter = 8;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_mosi_data[bit_counter + 7];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_REG_DATA:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
_post_state = S_SEND_STOP;
|
||||||
|
_post_serial_data = 0;
|
||||||
|
_bit_counter = 8;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_mosi_data[bit_counter - 1];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_RESTART:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1: begin
|
||||||
|
_process_counter = 2;
|
||||||
|
_serial_clock = 1;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
_state = S_START;
|
||||||
|
_post_state = S_WRITE_ADDR_R;
|
||||||
|
_saved_device_address[0] = 1;
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_WRITE_ADDR_R:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
if (DATA_WIDTH == 16) begin
|
||||||
|
_post_state = S_READ_REG_MSB;
|
||||||
|
_post_serial_data = 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
_post_state = S_READ_REG;
|
||||||
|
_post_serial_data = 0;
|
||||||
|
end
|
||||||
|
_state = S_CHECK_ACK;
|
||||||
|
_bit_counter = 8;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_serial_data = saved_device_address[bit_counter - 1];
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_READ_REG_MSB:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_miso_data[bit_counter + 7] = external_serial_data;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_post_state = S_READ_REG;
|
||||||
|
_state = S_SEND_ACK;
|
||||||
|
_bit_counter = 8;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_READ_REG:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_serial_clock = 0;
|
||||||
|
_miso_data[bit_counter - 1] = external_serial_data;
|
||||||
|
_bit_counter = bit_counter - 1;
|
||||||
|
_process_counter = 3;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
if (bit_counter == 0) begin
|
||||||
|
_state = S_SEND_NACK;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_SEND_NACK:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_serial_data = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_process_counter = 3;
|
||||||
|
_serial_clock = 0;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
_state = S_SEND_STOP;
|
||||||
|
_process_counter = 0;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_SEND_ACK:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
_serial_data = 0;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_process_counter = 3;
|
||||||
|
_serial_clock = 0;
|
||||||
|
end
|
||||||
|
3: begin
|
||||||
|
_state = post_state;
|
||||||
|
_process_counter = 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
S_SEND_STOP:
|
||||||
|
if (divider_tick)
|
||||||
|
case (process_counter)
|
||||||
|
0: begin
|
||||||
|
_serial_clock = 1;
|
||||||
|
_process_counter = 1;
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
if (external_serial_clock == 1) begin
|
||||||
|
_last_acknowledge = 0;
|
||||||
|
_process_counter = 2;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
_process_counter = 3;
|
||||||
|
_serial_data = 1;
|
||||||
|
end
|
||||||
|
3: _state = S_IDLE;
|
||||||
|
endcase
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
always @(posedge clock)
|
||||||
|
if (!reset_n) begin
|
||||||
|
state <= S_IDLE;
|
||||||
|
post_state <= S_IDLE;
|
||||||
|
process_counter <= 0;
|
||||||
|
bit_counter <= 0;
|
||||||
|
last_acknowledge <= 0;
|
||||||
|
miso_data <= 0;
|
||||||
|
saved_read_write <= 0;
|
||||||
|
divider_counter <= 0;
|
||||||
|
saved_device_address <= 0;
|
||||||
|
saved_register_address <= 0;
|
||||||
|
saved_mosi_data <= 0;
|
||||||
|
serial_clock <= 0;
|
||||||
|
serial_data <= 0;
|
||||||
|
saved_mosi_data <= 0;
|
||||||
|
post_serial_data <= 0;
|
||||||
|
busy <= 0;
|
||||||
|
got_acknowledge <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
state <= _state;
|
||||||
|
post_state <= _post_state;
|
||||||
|
process_counter <= _process_counter;
|
||||||
|
bit_counter <= _bit_counter;
|
||||||
|
last_acknowledge <= _last_acknowledge;
|
||||||
|
miso_data <= _miso_data;
|
||||||
|
saved_read_write <= _saved_read_write;
|
||||||
|
divider_counter <= _divider_counter;
|
||||||
|
saved_device_address <= _saved_device_address;
|
||||||
|
saved_register_address <= _saved_register_address;
|
||||||
|
saved_mosi_data <= _saved_mosi_data;
|
||||||
|
serial_clock <= _serial_clock;
|
||||||
|
serial_data <= _serial_data;
|
||||||
|
post_serial_data <= _post_serial_data;
|
||||||
|
busy <= _busy;
|
||||||
|
got_acknowledge <= _got_acknowledge;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
233
common/uart_i2c_bridge/uart_i2c_bridge.v
Normal file
233
common/uart_i2c_bridge/uart_i2c_bridge.v
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
// UART to I2C and control bridge for hsdaohSDR
|
||||||
|
// Copyright (C) 2024 by Steve Markgraf <steve@steve-m.de>
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
module uart_i2c_bridge
|
||||||
|
|
||||||
|
#(
|
||||||
|
parameter CLK_FRE = 27
|
||||||
|
)(
|
||||||
|
input wire clk,
|
||||||
|
input wire rst_n,
|
||||||
|
input wire uart_rx,
|
||||||
|
output wire uart_tx,
|
||||||
|
inout wire i2c_sda,
|
||||||
|
inout wire i2c_scl,
|
||||||
|
output reg[31:0] settings = 32'h0003cf76 // default PLL settings: 90 MHz
|
||||||
|
);
|
||||||
|
|
||||||
|
//parameter CLK_FRE = 27;//Mhz
|
||||||
|
parameter UART_FRE = 921600;
|
||||||
|
reg[7:0] tx_data;
|
||||||
|
reg[7:0] tx_str;
|
||||||
|
reg tx_data_valid;
|
||||||
|
wire tx_data_ready;
|
||||||
|
reg[7:0] tx_cnt;
|
||||||
|
wire[7:0] rx_data;
|
||||||
|
wire rx_data_valid;
|
||||||
|
wire rx_data_ready;
|
||||||
|
reg[31:0] wait_cnt;
|
||||||
|
reg[3:0] state;
|
||||||
|
reg[3:0] rx_byte_cnt;
|
||||||
|
reg[23:0] set_tmp;
|
||||||
|
|
||||||
|
localparam IDLE = 0;
|
||||||
|
localparam READ_SLAVE_ADDR = 1;
|
||||||
|
localparam READ_VALUE_TO_WRITE = 2;
|
||||||
|
localparam READ_REG_ADDR = 3;
|
||||||
|
localparam WAIT_I2C_BUSY = 4;
|
||||||
|
localparam SEND_ACKNOWLEDGE = 5;
|
||||||
|
localparam END_SENDING_ACKNOWLEDGE = 6;
|
||||||
|
localparam SEND_READ_RESULT = 7;
|
||||||
|
localparam RECEIVE_SETTINGS = 8;
|
||||||
|
|
||||||
|
// commands
|
||||||
|
localparam CMD_I2C_INIT = "i";
|
||||||
|
localparam CMD_I2C_READ = "r";
|
||||||
|
localparam CMD_I2C_WRITE = "w";
|
||||||
|
localparam CMD_CONFIG = "c";
|
||||||
|
|
||||||
|
assign rx_data_ready = 1'b1;
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
wait_cnt <= 32'd0;
|
||||||
|
tx_data <= 8'd0;
|
||||||
|
state <= IDLE;
|
||||||
|
tx_cnt <= 8'd0;
|
||||||
|
tx_data_valid <= 1'b0;
|
||||||
|
i2c_enable <= 1'b0;
|
||||||
|
settings <= 32'h00000000;
|
||||||
|
rx_byte_cnt <= 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
|
||||||
|
case(state)
|
||||||
|
IDLE:
|
||||||
|
begin
|
||||||
|
tx_data_valid <= 1'b0;
|
||||||
|
if (rx_data_valid == 1'b1)
|
||||||
|
begin
|
||||||
|
// receive command
|
||||||
|
case (rx_data)
|
||||||
|
CMD_I2C_READ:
|
||||||
|
begin
|
||||||
|
i2c_read_write <= 1'b1;
|
||||||
|
state <= READ_SLAVE_ADDR;
|
||||||
|
end
|
||||||
|
CMD_I2C_WRITE:
|
||||||
|
begin
|
||||||
|
i2c_read_write <= 1'b0;
|
||||||
|
state <= READ_SLAVE_ADDR;
|
||||||
|
end
|
||||||
|
CMD_I2C_INIT:
|
||||||
|
state <= IDLE;
|
||||||
|
CMD_CONFIG:
|
||||||
|
state <= RECEIVE_SETTINGS;
|
||||||
|
endcase
|
||||||
|
// default:
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RECEIVE_SETTINGS:
|
||||||
|
if (rx_data_valid == 1'b1) begin
|
||||||
|
if (rx_byte_cnt < 3)
|
||||||
|
rx_byte_cnt <= rx_byte_cnt + 1'b1;
|
||||||
|
|
||||||
|
case (rx_byte_cnt)
|
||||||
|
0:
|
||||||
|
set_tmp[23:16] <= rx_data[7:0];
|
||||||
|
1:
|
||||||
|
set_tmp[15:8] <= rx_data[7:0];
|
||||||
|
2:
|
||||||
|
set_tmp[7:0] <= rx_data[7:0];
|
||||||
|
3:
|
||||||
|
begin
|
||||||
|
settings[31:0] <= {set_tmp[23:0], rx_data[7:0]};
|
||||||
|
rx_byte_cnt <= 0;
|
||||||
|
state <= IDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
rx_byte_cnt <= 0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
READ_SLAVE_ADDR:
|
||||||
|
if(rx_data_valid == 1'b1) begin
|
||||||
|
device_address <= rx_data[6:0];
|
||||||
|
state <= i2c_read_write ? READ_REG_ADDR : READ_VALUE_TO_WRITE;
|
||||||
|
end
|
||||||
|
|
||||||
|
READ_VALUE_TO_WRITE:
|
||||||
|
// only for I2C TX: read value to be written
|
||||||
|
if(rx_data_valid == 1'b1) begin
|
||||||
|
mosi_data <= rx_data;
|
||||||
|
state <= READ_REG_ADDR;
|
||||||
|
end
|
||||||
|
READ_REG_ADDR:
|
||||||
|
if(rx_data_valid == 1'b1) begin
|
||||||
|
reg_addr <= rx_data;
|
||||||
|
|
||||||
|
if (i2c_busy == 0)
|
||||||
|
i2c_enable <= 1'b1;
|
||||||
|
else
|
||||||
|
state <= IDLE;
|
||||||
|
|
||||||
|
state <= WAIT_I2C_BUSY;
|
||||||
|
end
|
||||||
|
|
||||||
|
WAIT_I2C_BUSY:
|
||||||
|
if (i2c_busy == 1) begin
|
||||||
|
i2c_enable <= 1'b0;
|
||||||
|
state <= SEND_ACKNOWLEDGE;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_ACKNOWLEDGE:
|
||||||
|
begin
|
||||||
|
if ((i2c_busy == 0) && tx_data_ready) begin
|
||||||
|
tx_data <= {7'b0000000, i2c_acknowledge};
|
||||||
|
tx_data_valid <= 1'b1;
|
||||||
|
state <= END_SENDING_ACKNOWLEDGE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
END_SENDING_ACKNOWLEDGE:
|
||||||
|
begin
|
||||||
|
tx_data_valid <= 1'b0;
|
||||||
|
state <= i2c_read_write ? SEND_READ_RESULT : IDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_READ_RESULT:
|
||||||
|
begin
|
||||||
|
if ((i2c_busy == 0) && tx_data_ready) begin
|
||||||
|
tx_data <= miso_data;
|
||||||
|
tx_data_valid <= 1'b1;
|
||||||
|
state <= IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
state <= IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
reg i2c_enable;
|
||||||
|
reg i2c_read_write;
|
||||||
|
reg[7:0] mosi_data;
|
||||||
|
reg[7:0] reg_addr;
|
||||||
|
wire[7:0] miso_data;
|
||||||
|
reg[6:0] device_address;
|
||||||
|
wire i2c_busy;
|
||||||
|
wire i2c_acknowledge;
|
||||||
|
|
||||||
|
i2c_master #(.DATA_WIDTH(8),.REGISTER_WIDTH(8),.ADDRESS_WIDTH(7))
|
||||||
|
i2c_master_inst(
|
||||||
|
.clock (clk),
|
||||||
|
.reset_n (rst_n),
|
||||||
|
.enable (i2c_enable),
|
||||||
|
.read_write (i2c_read_write),
|
||||||
|
.mosi_data (mosi_data),
|
||||||
|
.register_address (reg_addr),
|
||||||
|
.device_address (device_address),
|
||||||
|
.divider (16), // ~400 kHz
|
||||||
|
|
||||||
|
.miso_data (miso_data),
|
||||||
|
.busy (i2c_busy),
|
||||||
|
.got_acknowledge (i2c_acknowledge),
|
||||||
|
|
||||||
|
.external_serial_data (i2c_sda),
|
||||||
|
.external_serial_clock (i2c_scl)
|
||||||
|
);
|
||||||
|
|
||||||
|
uart_rx#
|
||||||
|
(
|
||||||
|
.CLK_FRE(CLK_FRE),
|
||||||
|
.BAUD_RATE(UART_FRE)
|
||||||
|
) uart_rx_inst
|
||||||
|
(
|
||||||
|
.clk (clk ),
|
||||||
|
.rst_n (rst_n ),
|
||||||
|
.rx_data (rx_data ),
|
||||||
|
.rx_data_valid (rx_data_valid ),
|
||||||
|
.rx_data_ready (rx_data_ready ),
|
||||||
|
.rx_pin (uart_rx )
|
||||||
|
);
|
||||||
|
|
||||||
|
uart_tx#
|
||||||
|
(
|
||||||
|
.CLK_FRE(CLK_FRE),
|
||||||
|
.BAUD_RATE(UART_FRE)
|
||||||
|
) uart_tx_inst
|
||||||
|
(
|
||||||
|
.clk (clk ),
|
||||||
|
.rst_n (rst_n ),
|
||||||
|
.tx_data (tx_data ),
|
||||||
|
.tx_data_valid (tx_data_valid ),
|
||||||
|
.tx_data_ready (tx_data_ready ),
|
||||||
|
.tx_pin (uart_tx )
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
146
common/uart_i2c_bridge/uart_rx.v
Normal file
146
common/uart_i2c_bridge/uart_rx.v
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
// UART RX implementation
|
||||||
|
// source: https://github.com/sipeed/TangNano-20K-example/blob/main/uart/src/uart_rx.v
|
||||||
|
|
||||||
|
module uart_rx
|
||||||
|
#(
|
||||||
|
parameter CLK_FRE = 50, //clock frequency(Mhz)
|
||||||
|
parameter BAUD_RATE = 115200 //serial baud rate
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input clk, //clock input
|
||||||
|
input rst_n, //asynchronous reset input, low active
|
||||||
|
output reg[7:0] rx_data, //received serial data
|
||||||
|
output reg rx_data_valid, //received serial data is valid
|
||||||
|
input rx_data_ready, //data receiver module ready
|
||||||
|
input rx_pin //serial data input
|
||||||
|
);
|
||||||
|
//calculates the clock cycle for baud rate
|
||||||
|
localparam CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
|
||||||
|
//state machine code
|
||||||
|
localparam S_IDLE = 1;
|
||||||
|
localparam S_START = 2; //start bit
|
||||||
|
localparam S_REC_BYTE = 3; //data bits
|
||||||
|
localparam S_STOP = 4; //stop bit
|
||||||
|
localparam S_DATA = 5;
|
||||||
|
|
||||||
|
reg[2:0] state;
|
||||||
|
reg[2:0] next_state;
|
||||||
|
reg rx_d0; //delay 1 clock for rx_pin
|
||||||
|
reg rx_d1; //delay 1 clock for rx_d0
|
||||||
|
wire rx_negedge; //negedge of rx_pin
|
||||||
|
reg[7:0] rx_bits; //temporary storage of received data
|
||||||
|
reg[15:0] cycle_cnt; //baud counter
|
||||||
|
reg[2:0] bit_cnt; //bit counter
|
||||||
|
|
||||||
|
assign rx_negedge = rx_d1 && ~rx_d0;
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
rx_d0 <= 1'b0;
|
||||||
|
rx_d1 <= 1'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
rx_d0 <= rx_pin;
|
||||||
|
rx_d1 <= rx_d0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
state <= S_IDLE;
|
||||||
|
else
|
||||||
|
state <= next_state;
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(*)
|
||||||
|
begin
|
||||||
|
case(state)
|
||||||
|
S_IDLE:
|
||||||
|
if(rx_negedge)
|
||||||
|
next_state <= S_START;
|
||||||
|
else
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
S_START:
|
||||||
|
if(cycle_cnt == CYCLE - 1)//one data cycle
|
||||||
|
next_state <= S_REC_BYTE;
|
||||||
|
else
|
||||||
|
next_state <= S_START;
|
||||||
|
S_REC_BYTE:
|
||||||
|
if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7) //receive 8bit data
|
||||||
|
next_state <= S_STOP;
|
||||||
|
else
|
||||||
|
next_state <= S_REC_BYTE;
|
||||||
|
S_STOP:
|
||||||
|
if(cycle_cnt == CYCLE/2 - 1)//half bit cycle,to avoid missing the next byte receiver
|
||||||
|
next_state <= S_DATA;
|
||||||
|
else
|
||||||
|
next_state <= S_STOP;
|
||||||
|
S_DATA:
|
||||||
|
if(rx_data_ready) //data receive complete
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
else
|
||||||
|
next_state <= S_DATA;
|
||||||
|
default:
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
rx_data_valid <= 1'b0;
|
||||||
|
else if(state == S_STOP && next_state != state)
|
||||||
|
rx_data_valid <= 1'b1;
|
||||||
|
else if(state == S_DATA && rx_data_ready)
|
||||||
|
rx_data_valid <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
rx_data <= 8'd0;
|
||||||
|
else if(state == S_STOP && next_state != state)
|
||||||
|
rx_data <= rx_bits;//latch received data
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
bit_cnt <= 3'd0;
|
||||||
|
end
|
||||||
|
else if(state == S_REC_BYTE)
|
||||||
|
if(cycle_cnt == CYCLE - 1)
|
||||||
|
bit_cnt <= bit_cnt + 3'd1;
|
||||||
|
else
|
||||||
|
bit_cnt <= bit_cnt;
|
||||||
|
else
|
||||||
|
bit_cnt <= 3'd0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
cycle_cnt <= 16'd0;
|
||||||
|
else if((state == S_REC_BYTE && cycle_cnt == CYCLE - 1) || next_state != state)
|
||||||
|
cycle_cnt <= 16'd0;
|
||||||
|
else
|
||||||
|
cycle_cnt <= cycle_cnt + 16'd1;
|
||||||
|
end
|
||||||
|
//receive serial data bit data
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
rx_bits <= 8'd0;
|
||||||
|
else if(state == S_REC_BYTE && cycle_cnt == CYCLE/2 - 1)
|
||||||
|
rx_bits[bit_cnt] <= rx_pin;
|
||||||
|
else
|
||||||
|
rx_bits <= rx_bits;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
136
common/uart_i2c_bridge/uart_tx.v
Normal file
136
common/uart_i2c_bridge/uart_tx.v
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
// UART RX implementation
|
||||||
|
// source: https://github.com/sipeed/TangNano-20K-example/blob/main/uart/src/uart_tx.v
|
||||||
|
|
||||||
|
module uart_tx
|
||||||
|
#(
|
||||||
|
parameter CLK_FRE = 50, //clock frequency(Mhz)
|
||||||
|
parameter BAUD_RATE = 115200 //serial baud rate
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input clk, //clock input
|
||||||
|
input rst_n, //asynchronous reset input, low active
|
||||||
|
input[7:0] tx_data, //data to send
|
||||||
|
input tx_data_valid, //data to be sent is valid
|
||||||
|
output reg tx_data_ready, //send ready
|
||||||
|
output tx_pin //serial data output
|
||||||
|
);
|
||||||
|
//calculates the clock cycle for baud rate
|
||||||
|
localparam CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
|
||||||
|
//state machine code
|
||||||
|
localparam S_IDLE = 1;
|
||||||
|
localparam S_START = 2;//start bit
|
||||||
|
localparam S_SEND_BYTE = 3;//data bits
|
||||||
|
localparam S_STOP = 4;//stop bit
|
||||||
|
reg[2:0] state;
|
||||||
|
reg[2:0] next_state;
|
||||||
|
reg[15:0] cycle_cnt; //baud counter
|
||||||
|
reg[2:0] bit_cnt;//bit counter
|
||||||
|
reg[7:0] tx_data_latch; //latch data to send
|
||||||
|
reg tx_reg; //serial data output
|
||||||
|
assign tx_pin = tx_reg;
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
state <= S_IDLE;
|
||||||
|
else
|
||||||
|
state <= next_state;
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(*)
|
||||||
|
begin
|
||||||
|
case(state)
|
||||||
|
S_IDLE:
|
||||||
|
if(tx_data_valid == 1'b1)
|
||||||
|
next_state <= S_START;
|
||||||
|
else
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
S_START:
|
||||||
|
if(cycle_cnt == CYCLE - 1)
|
||||||
|
next_state <= S_SEND_BYTE;
|
||||||
|
else
|
||||||
|
next_state <= S_START;
|
||||||
|
S_SEND_BYTE:
|
||||||
|
if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7)
|
||||||
|
next_state <= S_STOP;
|
||||||
|
else
|
||||||
|
next_state <= S_SEND_BYTE;
|
||||||
|
S_STOP:
|
||||||
|
if(cycle_cnt == CYCLE - 1)
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
else
|
||||||
|
next_state <= S_STOP;
|
||||||
|
default:
|
||||||
|
next_state <= S_IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
tx_data_ready <= 1'b0;
|
||||||
|
end
|
||||||
|
else if(state == S_IDLE)
|
||||||
|
if(tx_data_valid == 1'b1)
|
||||||
|
tx_data_ready <= 1'b0;
|
||||||
|
else
|
||||||
|
tx_data_ready <= 1'b1;
|
||||||
|
else if(state == S_STOP && cycle_cnt == CYCLE - 1)
|
||||||
|
tx_data_ready <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
tx_data_latch <= 8'd0;
|
||||||
|
end
|
||||||
|
else if(state == S_IDLE && tx_data_valid == 1'b1)
|
||||||
|
tx_data_latch <= tx_data;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
begin
|
||||||
|
bit_cnt <= 3'd0;
|
||||||
|
end
|
||||||
|
else if(state == S_SEND_BYTE)
|
||||||
|
if(cycle_cnt == CYCLE - 1)
|
||||||
|
bit_cnt <= bit_cnt + 3'd1;
|
||||||
|
else
|
||||||
|
bit_cnt <= bit_cnt;
|
||||||
|
else
|
||||||
|
bit_cnt <= 3'd0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
cycle_cnt <= 16'd0;
|
||||||
|
else if((state == S_SEND_BYTE && cycle_cnt == CYCLE - 1) || next_state != state)
|
||||||
|
cycle_cnt <= 16'd0;
|
||||||
|
else
|
||||||
|
cycle_cnt <= cycle_cnt + 16'd1;
|
||||||
|
end
|
||||||
|
|
||||||
|
always@(posedge clk or negedge rst_n)
|
||||||
|
begin
|
||||||
|
if(rst_n == 1'b0)
|
||||||
|
tx_reg <= 1'b1;
|
||||||
|
else
|
||||||
|
case(state)
|
||||||
|
S_IDLE,S_STOP:
|
||||||
|
tx_reg <= 1'b1;
|
||||||
|
S_START:
|
||||||
|
tx_reg <= 1'b0;
|
||||||
|
S_SEND_BYTE:
|
||||||
|
tx_reg <= tx_data_latch[bit_cnt];
|
||||||
|
default:
|
||||||
|
tx_reg <= 1'b1;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
29
hsdaoh_nano20k_sdr.gprj
Normal file
29
hsdaoh_nano20k_sdr.gprj
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE gowin-fpga-project>
|
||||||
|
<Project>
|
||||||
|
<Template>FPGA</Template>
|
||||||
|
<Version>5</Version>
|
||||||
|
<Device name="GW2AR-18C" pn="GW2AR-LV18QN88C8/I7">gw2ar18c-000</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/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/hsdaoh_core.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/uart_i2c_bridge/i2c_master.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/uart_i2c_bridge/uart_i2c_bridge.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/uart_i2c_bridge/uart_rx.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="common/uart_i2c_bridge/uart_tx.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="hsdaoh_nano20k_sdr/top.v" type="file.verilog" enable="1"/>
|
||||||
|
<File path="hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.cst" type="file.cst" enable="1"/>
|
||||||
|
<File path="hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.sdc" type="file.sdc" enable="1"/>
|
||||||
|
</FileList>
|
||||||
|
</Project>
|
||||||
70
hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.cst
Normal file
70
hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.cst
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
IO_LOC "sys_clk" 4;
|
||||||
|
IO_PORT "sys_clk" PULL_MODE=UP;
|
||||||
|
IO_LOC "uart_tx" 69;
|
||||||
|
IO_PORT "uart_tx" PULL_MODE=UP IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "uart_rx" 70;
|
||||||
|
IO_PORT "uart_rx" PULL_MODE=UP IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "i2c_scl" 15;
|
||||||
|
IO_PORT "i2c_scl" PULL_MODE=UP IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "i2c_sda" 85;
|
||||||
|
IO_PORT "i2c_sda" PULL_MODE=UP IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "lcd_bl" 49;
|
||||||
|
IO_PORT "lcd_bl" IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "pa_en" 51;
|
||||||
|
IO_PORT "pa_en" IO_TYPE=LVCMOS33;
|
||||||
|
IO_LOC "bl616_boot" 75;
|
||||||
|
IO_PORT "bl616_boot" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
|
||||||
|
IO_LOC "tmds_d_p[0]" 35,36;
|
||||||
|
IO_PORT "tmds_d_p[0]" PULL_MODE=NONE DRIVE=8;
|
||||||
|
IO_LOC "tmds_d_p[1]" 37,38;
|
||||||
|
IO_PORT "tmds_d_p[1]" PULL_MODE=NONE DRIVE=8;
|
||||||
|
IO_LOC "tmds_d_p[2]" 39,40;
|
||||||
|
IO_PORT "tmds_d_p[2]" PULL_MODE=NONE DRIVE=8;
|
||||||
|
IO_LOC "tmds_clk_p" 33,34;
|
||||||
|
IO_PORT "tmds_clk_p" PULL_MODE=NONE DRIVE=8;
|
||||||
|
|
||||||
|
IO_LOC "adc0_data[0]" 73;
|
||||||
|
IO_PORT "adc0_data[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[1]" 74;
|
||||||
|
IO_PORT "adc0_data[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[2]" 54;
|
||||||
|
IO_PORT "adc0_data[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[3]" 27;
|
||||||
|
IO_PORT "adc0_data[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[4]" 28;
|
||||||
|
IO_PORT "adc0_data[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[5]" 25;
|
||||||
|
IO_PORT "adc0_data[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[6]" 26;
|
||||||
|
IO_PORT "adc0_data[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[7]" 29;
|
||||||
|
IO_PORT "adc0_data[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[8]" 30;
|
||||||
|
IO_PORT "adc0_data[8]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc0_data[9]" 31;
|
||||||
|
IO_PORT "adc0_data[9]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
|
||||||
|
IO_LOC "adc1_data[0]" 76;
|
||||||
|
IO_PORT "adc1_data[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[1]" 80;
|
||||||
|
IO_PORT "adc1_data[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[2]" 42;
|
||||||
|
IO_PORT "adc1_data[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[3]" 41;
|
||||||
|
IO_PORT "adc1_data[3]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[4]" 56;
|
||||||
|
IO_PORT "adc1_data[4]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[5]" 48;
|
||||||
|
IO_PORT "adc1_data[5]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[6]" 55;
|
||||||
|
IO_PORT "adc1_data[6]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[7]" 86;
|
||||||
|
IO_PORT "adc1_data[7]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[8]" 72;
|
||||||
|
IO_PORT "adc1_data[8]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
IO_LOC "adc1_data[9]" 71;
|
||||||
|
IO_PORT "adc1_data[9]" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
|
|
||||||
|
IO_LOC "adc_clkout" 77;
|
||||||
|
IO_PORT "adc_clkout" IO_TYPE=LVCMOS33 PULL_MODE=UP;
|
||||||
2
hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.sdc
Normal file
2
hsdaoh_nano20k_sdr/hsdaoh_nano20k_sdr.sdc
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
create_clock -name sys_clk -period 37.04 [get_ports {sys_clk}] -add
|
||||||
|
create_clock -name adc_clkout -period 11.11 [get_ports {adc_clkout}] -add
|
||||||
205
hsdaoh_nano20k_sdr/top.v
Normal file
205
hsdaoh_nano20k_sdr/top.v
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
// hsdaoh - High Speed Data Acquisition over HDMI
|
||||||
|
// hsdaohSDR top design for Tang Nano 20K
|
||||||
|
// Copyright (C) 2024 by Steve Markgraf <steve@steve-m.de>
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
module top (
|
||||||
|
sys_clk,
|
||||||
|
tmds_clk_n,
|
||||||
|
tmds_clk_p,
|
||||||
|
tmds_d_n,
|
||||||
|
tmds_d_p,
|
||||||
|
adc0_data,
|
||||||
|
adc1_data,
|
||||||
|
adc_clkout,
|
||||||
|
uart_rx,
|
||||||
|
uart_tx,
|
||||||
|
i2c_scl,
|
||||||
|
i2c_sda,
|
||||||
|
pa_en,
|
||||||
|
lcd_bl,
|
||||||
|
bl616_boot
|
||||||
|
);
|
||||||
|
input sys_clk;
|
||||||
|
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 [9:0] adc0_data;
|
||||||
|
input wire [9:0] adc1_data;
|
||||||
|
output wire adc_clkout;
|
||||||
|
|
||||||
|
input wire uart_rx;
|
||||||
|
output wire uart_tx;
|
||||||
|
|
||||||
|
inout wire i2c_scl;
|
||||||
|
inout wire i2c_sda;
|
||||||
|
|
||||||
|
output wire pa_en;
|
||||||
|
output wire lcd_bl;
|
||||||
|
output wire bl616_boot;
|
||||||
|
|
||||||
|
wire [2:0] tmds;
|
||||||
|
wire clk_pixel;
|
||||||
|
wire clk_pixel_x5;
|
||||||
|
wire hdmi_pll_lock;
|
||||||
|
|
||||||
|
wire clk_data;
|
||||||
|
wire data_pll_lock;
|
||||||
|
|
||||||
|
assign pa_en = 1'b0;
|
||||||
|
assign lcd_bl = 1'b0;
|
||||||
|
assign bl616_boot = 1'b1;
|
||||||
|
|
||||||
|
assign adc_clkout = clk_data;
|
||||||
|
|
||||||
|
// 477 MHz, maximum that works with the nano 20K
|
||||||
|
// 477/5 = 95.4 MHz
|
||||||
|
localparam HDMI_PLL_IDIV = 2;
|
||||||
|
localparam HDMI_PLL_FBDIV = 52;
|
||||||
|
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 ("GW2AR-18C")
|
||||||
|
) 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 91.8 MHz clock for data (ignored, using dynamic settings)
|
||||||
|
localparam DATA_PLL_IDIV = 6;
|
||||||
|
localparam DATA_PLL_FBDIV = 18;
|
||||||
|
localparam DATA_PLL_ODIV = 16;
|
||||||
|
|
||||||
|
wire data_pll_reset;
|
||||||
|
wire tenbit_enable;
|
||||||
|
|
||||||
|
assign data_pll_reset = settings[18];
|
||||||
|
assign tenbit_enable = settings[19];
|
||||||
|
|
||||||
|
// PLL for data clock
|
||||||
|
rPLL #(
|
||||||
|
.FCLKIN (27),
|
||||||
|
.IDIV_SEL (DATA_PLL_IDIV),
|
||||||
|
.FBDIV_SEL (DATA_PLL_FBDIV),
|
||||||
|
.ODIV_SEL (DATA_PLL_ODIV),
|
||||||
|
.DYN_IDIV_SEL("true"),
|
||||||
|
.DYN_FBDIV_SEL("true"),
|
||||||
|
.DYN_ODIV_SEL("true"),
|
||||||
|
.DEVICE ("GW2AR-18C")
|
||||||
|
) data_pll (
|
||||||
|
.CLKIN(sys_clk),
|
||||||
|
.CLKFB(1'b0),
|
||||||
|
.RESET(data_pll_reset),
|
||||||
|
.RESET_P(1'b0),
|
||||||
|
.FBDSEL(settings[5:0]),
|
||||||
|
.IDSEL(settings[11:6]),
|
||||||
|
.ODSEL(settings[17:12]),
|
||||||
|
.DUTYDA(4'b0),
|
||||||
|
.PSDA(4'b0),
|
||||||
|
.FDLY(4'b0),
|
||||||
|
.CLKOUT(clk_data),
|
||||||
|
.LOCK(data_pll_lock),
|
||||||
|
.CLKOUTP(),
|
||||||
|
.CLKOUTD(),
|
||||||
|
.CLKOUTD3()
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [19:0] counter = 16'h0000;
|
||||||
|
|
||||||
|
reg [19:0] fifo_in;
|
||||||
|
|
||||||
|
wire write_enable;
|
||||||
|
|
||||||
|
wire [19:0] fifo_out;
|
||||||
|
wire fifo_empty;
|
||||||
|
wire fifo_aempty;
|
||||||
|
|
||||||
|
wire fifo_full;
|
||||||
|
wire fifo_afull;
|
||||||
|
|
||||||
|
wire fifo_read_en;
|
||||||
|
async_fifo #(
|
||||||
|
.DSIZE(20),
|
||||||
|
.ASIZE($clog2(16384)),
|
||||||
|
.FALLTHROUGH("FALSE")
|
||||||
|
) fifo (
|
||||||
|
.wclk(clk_data),
|
||||||
|
.wrst_n(hdmi_pll_lock),
|
||||||
|
.winc(write_enable),
|
||||||
|
.wdata(fifo_in),
|
||||||
|
.wfull(fifo_full),
|
||||||
|
.awfull(fifo_afull),
|
||||||
|
.rclk(clk_pixel),
|
||||||
|
.rrst_n(hdmi_pll_lock),
|
||||||
|
.rinc(fifo_read_en),
|
||||||
|
.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_read_en),
|
||||||
|
.data_in(fifo_out),
|
||||||
|
.tenbit_enable_in(tenbit_enable)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [31:0] settings;
|
||||||
|
|
||||||
|
uart_i2c_bridge #(
|
||||||
|
) uart_i2c_bridge (
|
||||||
|
.clk(sys_clk),
|
||||||
|
.rst_n(1'b1),//pll_lock),
|
||||||
|
.uart_rx(uart_rx),
|
||||||
|
.uart_tx(uart_tx),
|
||||||
|
.i2c_sda(i2c_sda),
|
||||||
|
.i2c_scl(i2c_scl),
|
||||||
|
.settings(settings)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign write_enable = 1'b1;
|
||||||
|
|
||||||
|
always @(posedge clk_data) begin
|
||||||
|
fifo_in <= {adc0_data[9:0], adc1_data[9:0]};
|
||||||
|
counter <= counter + 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Add table
Reference in a new issue