9 changed files with 3293 additions and 10 deletions
@ -1,27 +1,35 @@
@@ -1,27 +1,35 @@
|
||||
# TangNano-20K-example |
||||
|
||||
- [TangNano-20K-example](#tangnano-20k-example) |
||||
- [Litex](#litex) |
||||
- [ws2812](#ws2812) |
||||
- [hdmi](#hdmi) |
||||
- [litex](#litex) |
||||
- [rgb\_lcd](#rgb_lcd) |
||||
- [uart](#uart) |
||||
- [ws2812](#ws2812) |
||||
|
||||
|
||||
## hdmi |
||||
|
||||
A demo to drive a hdmi screen with resolution 1280\*720 |
||||
|
||||
 |
||||
|
||||
## Litex |
||||
## litex |
||||
|
||||
A [litex](https://github.com/litex-hub) firmware for Tang Nano 20K, thanks [Icenowy](https://github.com/Icenowy) shared this firmware. |
||||
|
||||
 |
||||
|
||||
## ws2812 |
||||
## rgb_lcd |
||||
|
||||
A demo to drive onboard ws2812 rgb led. |
||||
Demos to drive the rgb_lcd screen, 800_480 is for screen with 800\*480 resolution, and 480_272 is for screen with 480\*272 resolution. |
||||
|
||||
## hdmi |
||||
## uart |
||||
|
||||
A demo to drive a hdmi screen with resolution 1280\*720 |
||||
FPGA uart example, containing 2 uart example messages. Burn into FPGA and open onboard serial port to check the message with 115200 baudrate. |
||||
|
||||
 |
||||
FPGA can not be burned when the serial port is opened. |
||||
|
||||
## rgb_lcd |
||||
## ws2812 |
||||
|
||||
Demos to drive the rgb_lcd screen, 800_480 is for screen with 800\*480 resolution, and 480_272 is for screen with 480\*272 resolution. |
||||
A demo to drive onboard ws2812 rgb led. |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
{ |
||||
"Allow_Duplicate_Modules" : false, |
||||
"Annotated_Properties_for_Analyst" : true, |
||||
"BACKGROUND_PROGRAMMING" : "off", |
||||
"COMPRESS" : false, |
||||
"CRC_CHECK" : true, |
||||
"Clock_Conversion" : true, |
||||
"DONE" : false, |
||||
"DOWNLOAD_SPEED" : "default", |
||||
"Default_Enum_Encoding" : "default", |
||||
"Disable_Insert_Pad" : false, |
||||
"ENCRYPTION_KEY" : false, |
||||
"ENCRYPTION_KEY_TEXT" : "00000000000000000000000000000000", |
||||
"FORMAT" : "binary", |
||||
"FSM Compiler" : true, |
||||
"Fanout_Guide" : 10000, |
||||
"Frequency" : "Auto", |
||||
"Generate_Constraint_File_of_Ports" : false, |
||||
"Generate_IBIS_File" : false, |
||||
"Generate_Plain_Text_Timing_Report" : false, |
||||
"Generate_Post_PNR_Simulation_Model_File" : false, |
||||
"Generate_Post_Place_File" : false, |
||||
"Generate_SDF_File" : false, |
||||
"Generate_VHDL_Post_PNR_Simulation_Model_File" : false, |
||||
"GwSyn_Loop_Limit" : 2000, |
||||
"HOTBOOT" : false, |
||||
"I2C" : false, |
||||
"I2C_SLAVE_ADDR" : "00", |
||||
"Implicit_Initial_Value_Support" : false, |
||||
"IncludePath" : [ |
||||
|
||||
], |
||||
"Incremental_Compile" : "", |
||||
"Initialize_Primitives" : false, |
||||
"JTAG" : false, |
||||
"MODE_IO" : false, |
||||
"MSPI" : false, |
||||
"Multiple_File_Compilation_Unit" : true, |
||||
"Number_of_Critical_Paths" : "", |
||||
"Number_of_Start/End_Points" : "", |
||||
"OUTPUT_BASE_NAME" : "uart_Hello", |
||||
"POWER_ON_RESET_MONITOR" : true, |
||||
"PRINT_BSRAM_VALUE" : true, |
||||
"PROGRAM_DONE_BYPASS" : false, |
||||
"Pipelining" : true, |
||||
"PlaceInRegToIob" : true, |
||||
"PlaceIoRegToIob" : true, |
||||
"PlaceOutRegToIob" : true, |
||||
"Place_Option" : "0", |
||||
"Process_Configuration_Verion" : "1.0", |
||||
"Promote_Physical_Constraint_Warning_to_Error" : true, |
||||
"Push_Tristates" : true, |
||||
"READY" : false, |
||||
"RECONFIG_N" : false, |
||||
"Ram_RW_Check" : true, |
||||
"Report_Auto-Placed_Io_Information" : false, |
||||
"Resolve_Mixed_Drivers" : false, |
||||
"Resource_Sharing" : true, |
||||
"Retiming" : false, |
||||
"Route_Maxfan" : "23", |
||||
"Route_Option" : "0", |
||||
"Run_Timing_Driven" : true, |
||||
"SECURE_MODE" : false, |
||||
"SECURITY_BIT" : true, |
||||
"SPI_FLASH_ADDR" : "00000000", |
||||
"SSPI" : false, |
||||
"Show_All_Warnings" : false, |
||||
"Synthesis On/Off Implemented as Translate On/Off" : false, |
||||
"Synthesize_tool" : "GowinSyn", |
||||
"TclPre" : "", |
||||
"TopModule" : "", |
||||
"USERCODE" : "default", |
||||
"Unused_Pin" : "As_input_tri_stated_with_pull_up", |
||||
"Update_Compile_Point_Timing_Data" : false, |
||||
"Use_Clock_Period_for_Unconstrainted IO" : false, |
||||
"Use_SCF" : false, |
||||
"VHDL_Standard" : "VHDL_Std_1993", |
||||
"Verilog_Standard" : "Vlg_Std_2001", |
||||
"WAKE_UP" : "0", |
||||
"Write_Vendor_Constraint_File" : true, |
||||
"dsp_balance" : false, |
||||
"show_all_warnings" : false, |
||||
"turn_off_bg" : false |
||||
} |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
IO_LOC "clk" 4; |
||||
IO_LOC "rst" 88; |
||||
IO_LOC "uart_rx" 70; |
||||
IO_LOC "uart_tx" 69; |
||||
|
||||
IO_PORT "clk" IO_TYPE=LVCMOS33; |
||||
IO_PORT "rst" IO_TYPE=LVCMOS33; |
||||
IO_PORT "uart_rx" IO_TYPE=LVCMOS33; |
||||
IO_PORT "uart_tx" IO_TYPE=LVCMOS33; |
@ -0,0 +1,143 @@
@@ -0,0 +1,143 @@
|
||||
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 |
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
module uart_test( |
||||
input clk, |
||||
input rst, |
||||
input uart_rx, |
||||
output uart_tx |
||||
); |
||||
|
||||
parameter CLK_FRE = 27;//Mhz |
||||
parameter UART_FRE = 115200;//Mhz |
||||
localparam IDLE = 0; |
||||
localparam SEND = 1; //send |
||||
localparam WAIT = 2; //wait 1 second and send uart received data |
||||
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; |
||||
|
||||
wire rst_n = !rst; |
||||
|
||||
assign rx_data_ready = 1'b1;//always can receive data, |
||||
|
||||
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; |
||||
end |
||||
else |
||||
case(state) |
||||
IDLE: |
||||
state <= SEND; |
||||
SEND: |
||||
begin |
||||
wait_cnt <= 32'd0; |
||||
tx_data <= tx_str; |
||||
|
||||
if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < DATA_NUM - 1)//Send 12 bytes data |
||||
begin |
||||
tx_cnt <= tx_cnt + 8'd1; //Send data counter |
||||
end |
||||
else if(tx_data_valid && tx_data_ready)//last byte sent is complete |
||||
begin |
||||
tx_cnt <= 8'd0; |
||||
tx_data_valid <= 1'b0; |
||||
state <= WAIT; |
||||
end |
||||
else if(~tx_data_valid) |
||||
begin |
||||
tx_data_valid <= 1'b1; |
||||
end |
||||
end |
||||
WAIT: |
||||
begin |
||||
wait_cnt <= wait_cnt + 32'd1; |
||||
|
||||
if(rx_data_valid == 1'b1) |
||||
begin |
||||
tx_data_valid <= 1'b1; |
||||
tx_data <= rx_data; // send uart received data |
||||
end |
||||
else if(tx_data_valid && tx_data_ready) |
||||
begin |
||||
tx_data_valid <= 1'b0; |
||||
end |
||||
else if(wait_cnt >= CLK_FRE * 1000_000) // wait for 1 second |
||||
state <= SEND; |
||||
end |
||||
default: |
||||
state <= IDLE; |
||||
endcase |
||||
end |
||||
|
||||
//combinational logic |
||||
|
||||
`define example_1 |
||||
|
||||
`ifdef example_1 |
||||
|
||||
// Example 1 |
||||
|
||||
parameter ENG_NUM = 14;//非中文字符数 |
||||
parameter CHE_NUM = 2 + 1;// 中文字符数 |
||||
parameter DATA_NUM = CHE_NUM * 3 + ENG_NUM; //中文字符使用UTF8,占用3个字节 |
||||
wire [ DATA_NUM * 8 - 1:0] send_data = {"你好 Tang Nano 20K",16'h0d0a}; |
||||
|
||||
`else |
||||
|
||||
// Example 2 |
||||
|
||||
parameter ENG_NUM = 19 + 1;//非中文字符数 |
||||
parameter CHE_NUM = 0;// 中文字符数 |
||||
parameter DATA_NUM = CHE_NUM * 3 + ENG_NUM + 1; //中文字符使用UTF8,占用3个字节 |
||||
wire [ DATA_NUM * 8 - 1:0] send_data = {"Hello Tang Nano 20K",16'h0d0a}; |
||||
|
||||
`endif |
||||
|
||||
always@(*) |
||||
tx_str <= send_data[(DATA_NUM - 1 - tx_cnt) * 8 +: 8]; |
||||
|
||||
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 |
@ -0,0 +1,133 @@
@@ -0,0 +1,133 @@
|
||||
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 |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<?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="src/uart_rx.v" type="file.verilog" enable="1"/> |
||||
<File path="src/uart_top.v" type="file.verilog" enable="1"/> |
||||
<File path="src/uart_tx.v" type="file.verilog" enable="1"/> |
||||
<File path="src/top.cst" type="file.cst" enable="1"/> |
||||
</FileList> |
||||
</Project> |
Loading…
Reference in new issue