diff --git a/hw/efinix_fpga/addr_decode.sv b/hw/efinix_fpga/addr_decode.sv index c304198..fd1c1dd 100644 --- a/hw/efinix_fpga/addr_decode.sv +++ b/hw/efinix_fpga/addr_decode.sv @@ -7,6 +7,7 @@ module addr_decode output o_timer_cs, output o_multiplier_cs, output o_divider_cs, + output o_uart_cs, output o_sdram_cs ); @@ -14,6 +15,7 @@ assign o_rom_cs = i_addr >= 16'hf000 && i_addr <= 16'hffff; assign o_timer_cs = i_addr >= 16'heff8 && i_addr <= 16'heffb; assign o_multiplier_cs = i_addr >= 16'heff0 && i_addr <= 16'heff7; assign o_divider_cs = i_addr >= 16'hefe7 && i_addr <= 16'hefef; +assign o_uart_cs = i_addr >= 16'hefe5 && i_addr <= 16'hefe6; assign o_leds_cs = i_addr == 16'hefff; assign o_sdram_cs = i_addr < 16'h8000; diff --git a/hw/efinix_fpga/debug_profile.wizard.json b/hw/efinix_fpga/debug_profile.wizard.json index 617a65e..6d90309 100644 --- a/hw/efinix_fpga/debug_profile.wizard.json +++ b/hw/efinix_fpga/debug_profile.wizard.json @@ -3,62 +3,137 @@ { "name": "la0", "type": "la", - "uuid": "4089d047ca614f1d8b1fe200bb713f1e", + "uuid": "bf7f2937618246c9b4a5564ab6e8e6af", "trigin_en": false, "trigout_en": false, "auto_inserted": true, "capture_control": false, - "data_depth": 2048, + "data_depth": 1024, "input_pipeline": 1, "probes": [ { - "name": "u_divider/rfd", + "name": "u_uart/tx_o", "width": 1, "probe_type": 1 }, { - "name": "u_divider/reset", + "name": "u_uart/tx_en", "width": 1, "probe_type": 1 }, { - "name": "u_divider/o_data", + "name": "u_uart/tx_data", "width": 8, "probe_type": 1 }, { - "name": "u_divider/numer", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_divider/quotient", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_divider/remain", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_divider/denom", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_divider/cs", + "name": "u_uart/tx_busy", "width": 1, "probe_type": 1 }, { - "name": "u_divider/r_remain", - "width": 16, + "name": "u_uart/status", + "width": 1, "probe_type": 1 }, { - "name": "u_divider/r_quotient", - "width": 16, + "name": "u_uart/state", + "width": 2, + "probe_type": 1 + }, + { + "name": "u_uart/rx_parity_error", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/rx_i", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/rx_error", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/rx_data_valid", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/rx_data", + "width": 8, + "probe_type": 1 + }, + { + "name": "u_uart/rx_busy", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/rwb", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/reset", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/o_data", + "width": 8, + "probe_type": 1 + }, + { + "name": "u_uart/next_state", + "width": 2, + "probe_type": 1 + }, + { + "name": "u_uart/i_data", + "width": 8, + "probe_type": 1 + }, + { + "name": "u_uart/irqb", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/cs", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/control", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/clk_50", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/clk", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/baud_x16_ce", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/baud_rate", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_uart/addr", + "width": 1, "probe_type": 1 } ] @@ -192,751 +267,387 @@ }, { "name": "la0_probe0", - "net": "rfd", + "net": "tx_o", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe1", - "net": "reset", + "net": "tx_en", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[0]", - "net": "o_data[0]", + "net": "tx_data[0]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[1]", - "net": "o_data[1]", + "net": "tx_data[1]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[2]", - "net": "o_data[2]", + "net": "tx_data[2]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[3]", - "net": "o_data[3]", + "net": "tx_data[3]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[4]", - "net": "o_data[4]", + "net": "tx_data[4]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[5]", - "net": "o_data[5]", + "net": "tx_data[5]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[6]", - "net": "o_data[6]", + "net": "tx_data[6]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe2[7]", - "net": "o_data[7]", + "net": "tx_data[7]", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe3[0]", - "net": "numer[0]", + "name": "la0_probe3", + "net": "tx_busy", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe3[1]", - "net": "numer[1]", + "name": "la0_probe4", + "net": "status", "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[2]", - "net": "numer[2]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[3]", - "net": "numer[3]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[4]", - "net": "numer[4]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[5]", - "net": "numer[5]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[6]", - "net": "numer[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[7]", - "net": "numer[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[8]", - "net": "numer[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[9]", - "net": "numer[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[10]", - "net": "numer[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[11]", - "net": "numer[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[12]", - "net": "numer[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[13]", - "net": "numer[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[14]", - "net": "numer[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe3[15]", - "net": "numer[15]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[0]", - "net": "quotient[0]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[1]", - "net": "quotient[1]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[2]", - "net": "quotient[2]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[3]", - "net": "quotient[3]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[4]", - "net": "quotient[4]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[5]", - "net": "quotient[5]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[6]", - "net": "quotient[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[7]", - "net": "quotient[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[8]", - "net": "quotient[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[9]", - "net": "quotient[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[10]", - "net": "quotient[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[11]", - "net": "quotient[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[12]", - "net": "quotient[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[13]", - "net": "quotient[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[14]", - "net": "quotient[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe4[15]", - "net": "quotient[15]", - "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe5[0]", - "net": "remain[0]", + "net": "state[0]", "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe5[1]", - "net": "remain[1]", + "net": "state[1]", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe5[2]", - "net": "remain[2]", + "name": "la0_probe6", + "net": "rx_parity_error", "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[3]", - "net": "remain[3]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[4]", - "net": "remain[4]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[5]", - "net": "remain[5]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[6]", - "net": "remain[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[7]", - "net": "remain[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[8]", - "net": "remain[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[9]", - "net": "remain[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[10]", - "net": "remain[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[11]", - "net": "remain[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[12]", - "net": "remain[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[13]", - "net": "remain[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[14]", - "net": "remain[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe5[15]", - "net": "remain[15]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[0]", - "net": "denom[0]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[1]", - "net": "denom[1]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[2]", - "net": "denom[2]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[3]", - "net": "denom[3]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[4]", - "net": "denom[4]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[5]", - "net": "denom[5]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[6]", - "net": "denom[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[7]", - "net": "denom[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[8]", - "net": "denom[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[9]", - "net": "denom[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[10]", - "net": "denom[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[11]", - "net": "denom[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[12]", - "net": "denom[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[13]", - "net": "denom[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[14]", - "net": "denom[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe6[15]", - "net": "denom[15]", - "path": [ - "u_divider" + "u_uart" ] }, { "name": "la0_probe7", + "net": "rx_i", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe8", + "net": "rx_error", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe9", + "net": "rx_data_valid", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[0]", + "net": "rx_data[0]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[1]", + "net": "rx_data[1]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[2]", + "net": "rx_data[2]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[3]", + "net": "rx_data[3]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[4]", + "net": "rx_data[4]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[5]", + "net": "rx_data[5]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[6]", + "net": "rx_data[6]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe10[7]", + "net": "rx_data[7]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe11", + "net": "rx_busy", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe12", + "net": "rwb", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe13", + "net": "reset", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[0]", + "net": "o_data[0]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[1]", + "net": "o_data[1]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[2]", + "net": "o_data[2]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[3]", + "net": "o_data[3]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[4]", + "net": "o_data[4]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[5]", + "net": "o_data[5]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[6]", + "net": "o_data[6]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe14[7]", + "net": "o_data[7]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe15[0]", + "net": "next_state[0]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe15[1]", + "net": "next_state[1]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[0]", + "net": "i_data[0]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[1]", + "net": "i_data[1]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[2]", + "net": "i_data[2]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[3]", + "net": "i_data[3]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[4]", + "net": "i_data[4]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[5]", + "net": "i_data[5]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[6]", + "net": "i_data[6]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe16[7]", + "net": "i_data[7]", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe17", + "net": "irqb", + "path": [ + "u_uart" + ] + }, + { + "name": "la0_probe18", "net": "cs", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[0]", - "net": "r_remain[0]", + "name": "la0_probe19", + "net": "control", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[1]", - "net": "r_remain[1]", + "name": "la0_probe20", + "net": "clk_50", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[2]", - "net": "r_remain[2]", + "name": "la0_probe21", + "net": "clk", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[3]", - "net": "r_remain[3]", + "name": "la0_probe22", + "net": "baud_x16_ce", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[4]", - "net": "r_remain[4]", + "name": "la0_probe23", + "net": "baud_rate", "path": [ - "u_divider" + "u_uart" ] }, { - "name": "la0_probe8[5]", - "net": "r_remain[5]", + "name": "la0_probe24", + "net": "addr", "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[6]", - "net": "r_remain[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[7]", - "net": "r_remain[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[8]", - "net": "r_remain[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[9]", - "net": "r_remain[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[10]", - "net": "r_remain[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[11]", - "net": "r_remain[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[12]", - "net": "r_remain[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[13]", - "net": "r_remain[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[14]", - "net": "r_remain[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe8[15]", - "net": "r_remain[15]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[0]", - "net": "r_quotient[0]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[1]", - "net": "r_quotient[1]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[2]", - "net": "r_quotient[2]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[3]", - "net": "r_quotient[3]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[4]", - "net": "r_quotient[4]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[5]", - "net": "r_quotient[5]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[6]", - "net": "r_quotient[6]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[7]", - "net": "r_quotient[7]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[8]", - "net": "r_quotient[8]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[9]", - "net": "r_quotient[9]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[10]", - "net": "r_quotient[10]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[11]", - "net": "r_quotient[11]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[12]", - "net": "r_quotient[12]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[13]", - "net": "r_quotient[13]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[14]", - "net": "r_quotient[14]", - "path": [ - "u_divider" - ] - }, - { - "name": "la0_probe9[15]", - "net": "r_quotient[15]", - "path": [ - "u_divider" + "u_uart" ] } ] @@ -951,17 +662,143 @@ ], "session": { "wizard": { - "data_depth": 2048, + "data_depth": 1024, "capture_control": false, "selected_nets": [ { - "name": "rfd", + "name": "tx_o", "width": 1, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" + ] + }, + { + "name": "tx_en", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "tx_data", + "width": 8, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ], + "net_idx_left": 7, + "net_idx_right": 0 + }, + { + "name": "tx_busy", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "status", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "state", + "width": 2, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ], + "net_idx_left": 1, + "net_idx_right": 0 + }, + { + "name": "rx_parity_error", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "rx_i", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "rx_error", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "rx_data_valid", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "rx_data", + "width": 8, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ], + "net_idx_left": 7, + "net_idx_right": 0 + }, + { + "name": "rx_busy", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "rwb", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" ] }, { @@ -971,7 +808,7 @@ "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" ] }, { @@ -981,58 +818,44 @@ "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" ], "net_idx_left": 7, "net_idx_right": 0 }, { - "name": "numer", - "width": 16, + "name": "next_state", + "width": 2, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" ], - "net_idx_left": 15, + "net_idx_left": 1, "net_idx_right": 0 }, { - "name": "quotient", - "width": 16, + "name": "i_data", + "width": 8, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" ], - "net_idx_left": 15, + "net_idx_left": 7, "net_idx_right": 0 }, { - "name": "remain", - "width": 16, + "name": "irqb", + "width": 1, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" - ], - "net_idx_left": 15, - "net_idx_right": 0 - }, - { - "name": "denom", - "width": 16, - "clk_domain": "clk_2", - "selected_probe_type": "DATA AND TRIGGER", - "child": [], - "path": [ - "u_divider" - ], - "net_idx_left": 15, - "net_idx_right": 0 + "u_uart" + ] }, { "name": "cs", @@ -1041,32 +864,68 @@ "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" + "u_uart" ] }, { - "name": "r_remain", - "width": 16, + "name": "control", + "width": 1, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" - ], - "net_idx_left": 15, - "net_idx_right": 0 + "u_uart" + ] }, { - "name": "r_quotient", - "width": 16, + "name": "clk_50", + "width": 1, "clk_domain": "clk_2", "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [ - "u_divider" - ], - "net_idx_left": 15, - "net_idx_right": 0 + "u_uart" + ] + }, + { + "name": "clk", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "baud_x16_ce", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "baud_rate", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] + }, + { + "name": "addr", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_uart" + ] } ], "top_module": "super6502", diff --git a/hw/efinix_fpga/ip/uart/settings.json b/hw/efinix_fpga/ip/uart/settings.json new file mode 100644 index 0000000..c1e284a --- /dev/null +++ b/hw/efinix_fpga/ip/uart/settings.json @@ -0,0 +1,34 @@ +{ + "args": [ + "-o", + "uart", + "--base_path", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip", + "--vlnv", + { + "vendor": "efinixinc.com", + "library": "serial_interface", + "name": "efx_uart", + "version": "2.0" + } + ], + "conf": { + "BYTE": "1", + "CLOCK_FREQ": "50000000", + "BAUD": "115200", + "ENABLE_PARITY": "0", + "FIX_BAUDRATE": "1", + "PARITY_MODE": "0", + "BOOTUP_CHECK": "0" + }, + "output": { + "external_source_source": [ + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart.v", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_define.vh", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_tmpl.vhd", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_tmpl.v" + ] + }, + "sw_version": "2022.2.322", + "generated_date": "2023-01-12T01:01:22.177819" +} \ No newline at end of file diff --git a/hw/efinix_fpga/ip/uart/uart.v b/hw/efinix_fpga/ip/uart/uart.v new file mode 100644 index 0000000..df28590 --- /dev/null +++ b/hw/efinix_fpga/ip/uart/uart.v @@ -0,0 +1,1168 @@ +// ============================================================================= +// Generated by efx_ipmgr +// Version: 2022.2.322 +// IP Version: 2.0 +// ============================================================================= + +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2022 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// + +`define IP_UUID _5423258f8d324e3e81f7da25952c84a2 +`define IP_NAME_CONCAT(a,b) a``b +`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID) +module uart ( +output tx_o, +input rx_i, +output tx_busy, +output [7:0] rx_data, +output rx_data_valid, +output rx_error, +output rx_parity_error, +output rx_busy, +output baud_x16_ce, +input clk, +input reset, +input [7:0] tx_data, +input [2:0] baud_rate, +input tx_en +); +`IP_MODULE_NAME(top_uart) #( +.BYTE (1), +.CLOCK_FREQ (50000000), +.BAUD (115200), +.ENABLE_PARITY (0), +.FIX_BAUDRATE (1), +.PARITY_MODE (0), +.BOOTUP_CHECK (0) +) u_top_uart( +.tx_o ( tx_o ), +.rx_i ( rx_i ), +.tx_busy ( tx_busy ), +.rx_data ( rx_data ), +.rx_data_valid ( rx_data_valid ), +.rx_error ( rx_error ), +.rx_parity_error ( rx_parity_error ), +.rx_busy ( rx_busy ), +.baud_x16_ce ( baud_x16_ce ), +.clk ( clk ), +.reset ( reset ), +.tx_data ( tx_data ), +.baud_rate ( baud_rate ), +.tx_en ( tx_en ) +); + +endmodule + +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// baud_generator.v +// +// Description: +// Baud Generator generates up to 115.2KHz baud rate. +// common Baud Rate - 4800/9600/19200/57600/115200Hz +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// +// ******************************* +///////////////////////////////////////////////////////////////////////////// + + +`resetall +`timescale 1ns/10ps + + module `IP_MODULE_NAME(baud_generator) + #(parameter CLOCK_FREQ = 50000000, + FIX_BAUDRATE = 1, + BAUD = 115200) + + ( + output wire baud_ce, + output wire baud_x16_ce, + + //inputs + input clk, + input [2:0] baud_rate, + input reset + ); + + //Baud Rate Calculation + parameter BAUD_GEN_ACC_WIDTH = 16; + + localparam [BAUD_GEN_ACC_WIDTH-1:0] BAUD_GEN_INC = CLOCK_FREQ/BAUD; + localparam [BAUD_GEN_ACC_WIDTH-1:0] BAUD_GEN_INC_X16 = (CLOCK_FREQ/BAUD) >> 4; + + localparam BAUD_GEN_INC_0 = CLOCK_FREQ/115200; + localparam BAUD_GEN_INC_1 = CLOCK_FREQ/57600; + localparam BAUD_GEN_INC_2 = CLOCK_FREQ/38400; + localparam BAUD_GEN_INC_3 = CLOCK_FREQ/19200; + localparam BAUD_GEN_INC_4 = CLOCK_FREQ/9600; + localparam BAUD_GEN_INC_5 = CLOCK_FREQ/4800; + localparam BAUD_GEN_INC_6 = CLOCK_FREQ/2400; + localparam BAUD_GEN_INC_7 = CLOCK_FREQ/1200; + + //internal registers + reg [BAUD_GEN_ACC_WIDTH:0] baud_cnt ; + reg [BAUD_GEN_ACC_WIDTH:0] baud_cnt_x16 ; + //Baud Rate <1%. + + always @(posedge clk) begin + if (reset) begin + baud_cnt <= 'h0; + end + else begin + if(baud_ce) begin + baud_cnt <= 'h0; + end + else begin + baud_cnt <= baud_cnt[BAUD_GEN_ACC_WIDTH-1:0] + 1'b1; + end + end + end + + always @(posedge clk) begin + if (reset) begin + baud_cnt_x16 <= 'h0; + end + else begin + if(baud_ce || baud_x16_ce) begin + baud_cnt_x16 <= 'h0; + end + else begin + baud_cnt_x16 <= baud_cnt_x16[BAUD_GEN_ACC_WIDTH-1:0] + 1'b1; + end + end + end + + + generate if (FIX_BAUDRATE) begin + assign baud_ce = (baud_cnt == BAUD_GEN_INC-1'b1); + assign baud_x16_ce = (baud_cnt_x16 == BAUD_GEN_INC_X16 - 1'b1); + end + else begin + assign baud_ce = (baud_rate == 1) ? (baud_cnt == BAUD_GEN_INC_1-1'b1) : + (baud_rate == 2) ? (baud_cnt == BAUD_GEN_INC_2-1'b1) : + (baud_rate == 3) ? (baud_cnt == BAUD_GEN_INC_3-1'b1) : + (baud_rate == 4) ? (baud_cnt == BAUD_GEN_INC_4-1'b1) : + (baud_rate == 5) ? (baud_cnt == BAUD_GEN_INC_5-1'b1) : + (baud_rate == 6) ? (baud_cnt == BAUD_GEN_INC_6-1'b1) : + (baud_rate == 7) ? (baud_cnt == BAUD_GEN_INC_7-1'b1) : + (baud_cnt == BAUD_GEN_INC_0-1'b1); + assign baud_x16_ce = (baud_rate == 1) ? (baud_cnt_x16 == (BAUD_GEN_INC_1 >> 4)-1'b1) : + (baud_rate == 2) ? (baud_cnt_x16 == (BAUD_GEN_INC_2 >> 4)-1'b1) : + (baud_rate == 3) ? (baud_cnt_x16 == (BAUD_GEN_INC_3 >> 4)-1'b1) : + (baud_rate == 4) ? (baud_cnt_x16 == (BAUD_GEN_INC_4 >> 4)-1'b1) : + (baud_rate == 5) ? (baud_cnt_x16 == (BAUD_GEN_INC_5 >> 4)-1'b1) : + (baud_rate == 6) ? (baud_cnt_x16 == (BAUD_GEN_INC_6 >> 4)-1'b1) : + (baud_rate == 7) ? (baud_cnt_x16 == (BAUD_GEN_INC_7 >> 4)-1'b1) : + (baud_cnt_x16 == (BAUD_GEN_INC_0 >> 4)-1'b1); + end + endgenerate + + +endmodule + +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// receiver.v +// +// Description: +// process the RX data from UART Peripherals +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// +// ******************************* +///////////////////////////////////////////////////////////////////////////// + + +`resetall +`timescale 1ns/10ps + + module `IP_MODULE_NAME(receiver) + #( parameter PARITY_MODE = 0) + ( + //outputs + output wire [7:0] data_1_byte, //One bye of data. + output reg valid, //Valid for data_1_byte. + output reg error, //Framing Error. + output reg parity_error, //Parity Error. + output reg rx_busy, //rx busy + //inputs + input clk, //System Clock. + input reset, //system reset. + input baud_x16_ce, //BaudX16 Enable Signal + input rx_i, //RX data from PC. + input en_parity //Enable Parity + ); + + //Parameters + localparam IDLE = 0, + START = 1, + DATA = 2, + STOP = 3, + ERROR = 4, + PARITY = 5; + + localparam IDLE_ST = 6'b00_0001, + START_ST = 6'b00_0010, + DATA_ST = 6'b00_0100, + STOP_ST = 6'b00_1000, + ERROR_ST = 6'b01_0000, + PARITY_ST = 6'b10_0000; + + + + //internal signals + reg rx_data0,rx_data1,rx_data2; + reg [5:0] present_state,next_state; + reg [3:0] count_x16; + wire start; + reg shift_en; + reg [15:0] shift_rx_data [7:0]; + reg load_data; + reg [7:0] parallel_data; + reg count_en; + reg valid_en; + reg [7:0] count_8bit; + integer i; + reg [2:0] rx_data_sync; + reg parity_en; + reg [15:0] parity_data; + wire parity_bit; + + wire expected_parity_bit; + + //synchronize the rx_i. + always @(posedge clk) + if (reset) + rx_data_sync <= 3'b111; + else + rx_data_sync <= {rx_data_sync[1:0],rx_i}; + + + //synchronize the incoming rx_i... + always @(posedge clk) + if (reset) + begin + rx_data0 <= 1'b1; + rx_data1 <= 1'b1; + rx_data2 <= 1'b1; + end + else if (baud_x16_ce) + begin + rx_data0 <= rx_data_sync[2]; + rx_data1 <= rx_data0; + rx_data2 <= rx_data1; + end + + assign start = !rx_data1 & rx_data2; + + + always @(posedge clk) + if (reset) + present_state <= 6'h1; + else if (baud_x16_ce) + present_state <= next_state; + + //State Machine for Receiver to process the RXDATA and generate the parallel data... + always @(*) + begin + load_data = 0; + shift_en= 0; + valid_en = 0; + count_en = 0; + parity_en = 0; + + case (present_state) + IDLE_ST: begin + if (start) + next_state = START_ST; + else + next_state = IDLE_ST; + end + + START_ST: begin + count_en = 1'b1; + + if (&count_x16) + next_state = DATA_ST; + else if (rx_data2) + next_state = ERROR_ST; + else + next_state = START_ST; + end + + DATA_ST : begin + shift_en = 1'b1; + if (count_8bit[7] && &count_x16) + begin + load_data = 1'b1; + if (en_parity) + next_state = PARITY_ST; + else + next_state= STOP_ST; + + end + else + begin + + next_state = DATA_ST; + end + end + + PARITY_ST : begin + count_en = 1'b1; + parity_en = 1'b1; + if (&count_x16) + begin + next_state = STOP_ST; + end + + else + begin + next_state = PARITY_ST; + end + end + + + STOP_ST : begin + count_en=1'b1; + + if (!rx_data1) + next_state = ERROR_ST; + else if (count_8bit[0] & &count_x16) + begin + valid_en = 1'b1; + if (start) + next_state = START_ST; + else + next_state = IDLE_ST; + end + + else + begin + next_state = STOP_ST; + + end + end // case: present_state[STOP] + + ERROR_ST : begin + next_state = IDLE_ST; + end + + + default: next_state = IDLE_ST; + + endcase // case(current_state) + + + end // always @ (*) + + + always @(posedge clk) + if (reset) + count_x16 <= 4'b0; + else if (baud_x16_ce) + begin + if (count_en | shift_en) + count_x16 <= count_x16 + 1; + else if (present_state[IDLE]) + count_x16 <= 4'h0; + end + + always @(posedge clk) + begin + if (reset) + count_8bit <= 8'h01; + else if (baud_x16_ce) + begin + if ( present_state[DATA] && &count_x16 ) + count_8bit <= {count_8bit[6:0],count_8bit[7]}; + else if (present_state[IDLE]) + count_8bit <= 8'h01; + end + + + end // always @ (posedge clk) + + + + + always @(posedge clk) + if (reset | present_state[IDLE]) + begin + for (i=0; i<8;i=i+1) + shift_rx_data[i] <= 16'h0; + end + + else if (baud_x16_ce & shift_en) + case (1'b1) + count_8bit[0]: + shift_rx_data[0] <= shift_rx_data[0]<<1 | rx_data2; + count_8bit[1]: + shift_rx_data[1] <= shift_rx_data[1]<<1 | rx_data2; + count_8bit[2]: + shift_rx_data[2] <= shift_rx_data[2]<<1 | rx_data2; + count_8bit[3]: + shift_rx_data[3] <= shift_rx_data[3]<<1 | rx_data2; + count_8bit[4]: + shift_rx_data[4] <= shift_rx_data[4]<<1 | rx_data2; + count_8bit[5]: + shift_rx_data[5] <= shift_rx_data[5]<<1 | rx_data2; + count_8bit[6]: + shift_rx_data[6] <= shift_rx_data[6]<<1 | rx_data2; + count_8bit[7]: + shift_rx_data[7] <= shift_rx_data[7]<<1 | rx_data2; + endcase + + + + always @(posedge clk) + if (reset) + begin + parallel_data <= 8'h0; + + end + else if (load_data & baud_x16_ce) + parallel_data <= { &shift_rx_data[7][8:7], &shift_rx_data[6][8:7], + &shift_rx_data[5][8:7], &shift_rx_data[4][8:7], + &shift_rx_data[3][8:7], &shift_rx_data[2][8:7], + &shift_rx_data[1][8:7], &shift_rx_data[0][8:7] + }; + + assign data_1_byte = parallel_data; + + always @(posedge clk) + if (reset ) + valid <= 1'b0; + else if (baud_x16_ce) begin + if (valid_en) + valid <= 1'b1; + else + valid <= 1'b0; + end + + + + + + always @(posedge clk) + if (reset | present_state[IDLE]) + parity_data <= 16'h0; + else if (baud_x16_ce & parity_en) + parity_data <= parity_data<<1 | rx_data2; + + + assign parity_bit = &parity_data[8:7]; + generate + if (PARITY_MODE==1) + assign expected_parity_bit = ~(^parallel_data); + else + assign expected_parity_bit = ^parallel_data; + endgenerate + + //Update the parity status bit. + always @(posedge clk) + if (reset) + parity_error <= 1'b0; + else if (present_state[STOP]) + parity_error <= (expected_parity_bit != parity_bit); + + + + + //Error in transmission... + //This is unused register in this design. I only need to use it + //during verification. + //TO-DO: You may add this feature to let firmware read the error. + always @(posedge clk) + if (reset) + error <= 1'b0; + else if (present_state[ERROR]) + error <= 1'b1; + else if (present_state[STOP]) + error <= 1'b0; + + + + always @(posedge clk) + if (reset) + rx_busy <= 1'b0; + else if (present_state[IDLE]) + rx_busy <= 1'b0; + else + rx_busy <= 1'b1; + +endmodule // receiver + +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +///////////////////////////////////////////////////////////////////////////// + + + + +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// top_uart.v +// +// Description: +// UART Controller +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// +// ******************************* +///////////////////////////////////////////////////////////////////////////// + +`resetall +`timescale 1ns/10ps +//`include "uart_defines.v" + + module `IP_MODULE_NAME(top_uart)( + tx_o, + rx_i, + tx_busy, + rx_data, + rx_data_valid, + rx_error, + rx_parity_error, + rx_busy, + baud_x16_ce, + clk, + reset, + tx_data, + baud_rate, + tx_en + ); + + parameter BYTE = 4; + parameter DATA_WIDTH = BYTE*8; + parameter CLOCK_FREQ = 50000000; + parameter FIX_BAUDRATE = 0; + parameter BAUD = 115200; + parameter ENABLE_PARITY = 0; + parameter PARITY_MODE = 0; + parameter BOOTUP_CHECK = 0; + //////////////////// + //UART interface + output tx_o; //UART TX + input rx_i; //UART RX + + //////////////////// + //User Interface + //outputs + output tx_busy; //transmitting the tx data. + output [7:0] rx_data; //rx_data to user logic + output rx_data_valid; //valid flag for rx_data. + output rx_error; //a start bit, parity bit, or stop bit error was detected during the last received data. + output rx_parity_error; //Indicate receive data contain parity error. + output rx_busy; //Receiving the rx data. + output baud_x16_ce; + //inputs + input clk; //system clock + input reset; //active high reset + input [BYTE*8-1:0] tx_data; //Data to transmit. + input tx_en; //Latches tx_data and initiate transmit + input [2:0] baud_rate; //0-115200, 1-57600, 2-38400, 3-19200, 4-9600, 5-4800, 6-2400, 7-1200 +//Internal Signals + wire baud_ce; + wire en_parity; + + //UART Format + /* _______ ______ _______________ + * IDLE \_Start_/ Bit0 -----Bit1 -> Bit 7(MSB)/PARITY \/STOP IDLE + * Refer to waveform above, the start is start bit (1'b0). + * Meanwhile, the stop is stop bit (1'b1) + */ + + + `IP_MODULE_NAME(baud_generator) #(.CLOCK_FREQ(CLOCK_FREQ), + .FIX_BAUDRATE(FIX_BAUDRATE), + .BAUD(BAUD) + ) + u_baud_generator + ( + // Outputs + .baud_ce (baud_ce), + .baud_x16_ce (baud_x16_ce), + // Inputs + .clk (clk), + .baud_rate (baud_rate), + .reset (reset)); + + + `IP_MODULE_NAME(transmitter) #( + .ENABLE_PARITY(ENABLE_PARITY), + .PARITY_MODE(PARITY_MODE), + .DATA_WIDTH(DATA_WIDTH), + .BOOTUP_CHECK(BOOTUP_CHECK) + ) + u_transmitter + ( + // Outputs + .tx_o (tx_o), + .tx_busy (tx_busy), + // Inputs + .clk (clk), + .reset (reset), + .baud_ce (baud_ce), + .tx_data (tx_data[DATA_WIDTH-1:0]), + .tx_en (tx_en)); + + + `IP_MODULE_NAME(receiver) #( + .PARITY_MODE(PARITY_MODE) + ) + u_receiver + ( + // Outputs + .data_1_byte (rx_data), + .valid (rx_data_valid), + .error (rx_error), + .parity_error (rx_parity_error), + .rx_busy (rx_busy), + // Inputs + .clk (clk), + .reset (reset), + .baud_x16_ce (baud_x16_ce), + .en_parity (en_parity), + .rx_i (rx_i)); + + assign en_parity = ENABLE_PARITY; + + +endmodule // top_uart + +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +///////////////////////////////////////////////////////////////////////////// + + + +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// transmitter.v +// +// Description: +// Transmit the TX data to UART Peripheral +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// +// ******************************* +///////////////////////////////////////////////////////////////////////////// + +`resetall +`timescale 1ns/10ps + + module `IP_MODULE_NAME(transmitter) + #(parameter ENABLE_PARITY = 0, + PARITY_MODE = 0, + DATA_WIDTH = 32, + BOOTUP_CHECK = 0) + ( + //outputs + output wire tx_o, //TX data to UART peripheral. + output reg tx_busy, //tx busy flag. + //input + input clk, //system clock + input reset, //system reset. + input baud_ce, //baud tick + input [DATA_WIDTH-1:0] tx_data, //8-bit read data... + input tx_en //Valid read data...Ready to send it... + ); + +//ASCII +`define ASCII_0 8'h30 +`define ASCII_1 8'h31 +`define ASCII_2 8'h32 +`define ASCII_3 8'h33 +`define ASCII_4 8'h34 +`define ASCII_5 8'h35 +`define ASCII_6 8'h36 +`define ASCII_7 8'h37 +`define ASCII_8 8'h38 +`define ASCII_9 8'h39 + +`define ASCII_a 8'h61 +`define ASCII_b 8'h62 +`define ASCII_c 8'h63 +`define ASCII_d 8'h64 +`define ASCII_e 8'h65 +`define ASCII_f 8'h66 + + +`define ASCII_A 8'h41 +`define ASCII_B 8'h42 +`define ASCII_C 8'h43 +`define ASCII_D 8'h44 +`define ASCII_E 8'h45 +`define ASCII_F 8'h46 + +`define ASCII_O 8'h4F +`define ASCII_K 8'h4B +`define ASCII_LF 8'h0A + +//START & STOP BIT +`define STOP_BIT 1'b1 +`define START_BIT 1'b0 + + //internal signals. + reg [46:0] shift_tx_data; + wire [46:0] xmit_data_p, xmit_data; + reg tx_en0,tx_en1,tx_en2; + reg [5:0] tx_count; + wire ascii_k_parity; + wire ascii_o_parity; + + + always @(posedge clk) + if (reset) + begin + tx_en0 <= 1'b0; + tx_en1 <= 1'b0; + tx_en2 <= 1'b0; + end + else if (baud_ce) + begin + tx_en0 <= tx_en; + tx_en1 <= tx_en0; + tx_en2 <= tx_en1; + end + + generate + if (PARITY_MODE==1) begin //odd + assign ascii_k_parity = ~(^(`ASCII_K)); + assign ascii_o_parity = ~(^(`ASCII_O)); + end + else begin //even + assign ascii_k_parity = ^(`ASCII_K); + assign ascii_o_parity = ^(`ASCII_O); + end + endgenerate + + generate + if (DATA_WIDTH == 32) + if (PARITY_MODE==1) begin + assign xmit_data_p = {`STOP_BIT, ~(^tx_data[7:0]) , tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[15:8]) , tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[23:16]), tx_data[23:16] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[31:24]), tx_data[31:24] , `START_BIT + }; + + end + + else begin + assign xmit_data_p = {`STOP_BIT, ^tx_data[7:0] , tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[15:8] , tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[23:16], tx_data[23:16] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[31:24], tx_data[31:24] , `START_BIT + }; + + end + + + + else if (DATA_WIDTH == 24) + if (PARITY_MODE==1) begin + assign xmit_data_p = {11'h7ff, + `STOP_BIT, ~(^tx_data[7:0]), tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[15:8]), tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[23:16]), tx_data[23:16] , `START_BIT, 1'b1 + }; + end + else begin + assign xmit_data_p = {11'h7ff, + `STOP_BIT, ^tx_data[7:0] , tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[15:8] , tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[23:16], tx_data[23:16] , `START_BIT, 1'b1 + }; + end + + else if (DATA_WIDTH == 16) + if (PARITY_MODE==1) begin + assign xmit_data_p = {23'h7f_ffff, + `STOP_BIT, ~(^tx_data[7:0]) , tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ~(^tx_data[15:8]) , tx_data[15:8] , `START_BIT, 1'b1 + }; + end + else begin + assign xmit_data_p = {23'h7f_ffff, + `STOP_BIT, ^tx_data[7:0] , tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, ^tx_data[15:8] , tx_data[15:8] , `START_BIT, 1'b1 + }; + end + + + else if (DATA_WIDTH == 8) + if (PARITY_MODE==1) begin + assign xmit_data_p = {35'h7_ffff_ffff, + `STOP_BIT, ~(^tx_data[7:0]) , tx_data[7:0] , `START_BIT, 1'b1 + }; + + end + else begin + assign xmit_data_p = {35'h7_ffff_ffff, + `STOP_BIT, ^tx_data[7:0] , tx_data[7:0] , `START_BIT, 1'b1 + }; + end + + + else + if (PARITY_MODE==1) begin + assign xmit_data_p = {35'h7_ffff_ffff, + `STOP_BIT, ~(^tx_data[7:0]) , tx_data[7:0] , `START_BIT, 1'b1 + }; + end + else begin + assign xmit_data_p = {35'h7_ffff_ffff, + `STOP_BIT, ^tx_data[7:0] , tx_data[7:0] , `START_BIT, 1'b1 + }; + end + + endgenerate + + + generate + if (DATA_WIDTH == 32) + assign xmit_data = { 4'hf, + `STOP_BIT, tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[23:16] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[31:24] , `START_BIT + }; + + else if (DATA_WIDTH == 24) + assign xmit_data = { 14'h3fff, + `STOP_BIT, tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[15:8] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[23:16] , `START_BIT, 1'b1 + }; + else if (DATA_WIDTH == 16) + assign xmit_data = { 25'h1ff_ffff, + `STOP_BIT, tx_data[7:0] , `START_BIT, 1'b1, + `STOP_BIT, tx_data[15:8] , `START_BIT, 1'b1 + }; + + else if (DATA_WIDTH == 8) + assign xmit_data = { 36'hf_ffff_ffff, + `STOP_BIT, tx_data[7:0] , `START_BIT, 1'b1 + }; + + else + assign xmit_data = { 36'hf_ffff_ffff, + `STOP_BIT, tx_data[7:0] , `START_BIT, 1'b1 + }; + endgenerate + + + generate + if (BOOTUP_CHECK) begin + if (ENABLE_PARITY) begin + //Generates OK flag after reset. + always @(posedge clk) + if (reset) + shift_tx_data <= { 12'hfff, + `STOP_BIT, ascii_k_parity, `ASCII_K, `START_BIT, + 4'hf, + `STOP_BIT, ascii_o_parity, `ASCII_O, `START_BIT, + 8'hff, 1'b1 + }; + + else if (baud_ce) + begin + if (tx_en1 & !tx_en2) + shift_tx_data <= xmit_data_p; + else + shift_tx_data <= {1'b1, shift_tx_data[DATA_WIDTH-1+15:1] } ; + end + + end // if (ENABLE_PARITY) + + else begin + //Generates OK flag after reset. + always @(posedge clk) + if (reset) + shift_tx_data <= { 1'b1, 8'hff, 1'b1, + `STOP_BIT, `ASCII_K, `START_BIT, + 8'hff, + `STOP_BIT, `ASCII_O, `START_BIT, + 8'hff, 1'b1 + }; + + else if (baud_ce) + begin + if (tx_en1 & !tx_en2) + shift_tx_data <= xmit_data; + else + shift_tx_data <= {1'b1, shift_tx_data[DATA_WIDTH-1+15:1] } ; + end + end // else: !if(ENABLE_PARITY) + + end // if (BOOTUP_CHECK) + else begin + if (ENABLE_PARITY) begin + //Generates OK flag after reset. + always @(posedge clk) + if (reset) + shift_tx_data <= {47{1'b1}}; + + + else if (baud_ce) + begin + if (tx_en1 & !tx_en2) + shift_tx_data <= xmit_data_p; + else + shift_tx_data <= {1'b1, shift_tx_data[DATA_WIDTH-1+15:1] } ; + end + + end // if (ENABLE_PARITY) + + else begin + //Generates OK flag after reset. + always @(posedge clk) + if (reset) + shift_tx_data <= {47{1'b1}}; + + else if (baud_ce) + begin + if (tx_en1 & !tx_en2) + shift_tx_data <= xmit_data; + else + shift_tx_data <= {1'b1, shift_tx_data[DATA_WIDTH-1+15:1] } ; + end + end // else: !if(ENABLE_PARITY) + + end // else: !if(BOOTUP_CHECK) + + endgenerate + + + + + always @(posedge clk) + if (reset) + tx_count <= 6'd0; + else if (baud_ce) + if (tx_en1 & !tx_en2) + tx_count <= 6'd0; + else if (tx_count < (DATA_WIDTH+11 + 1) ) + tx_count <= tx_count + 1; + + always @(posedge clk) + if (reset) + tx_busy <= 1'b0; + else if (baud_ce) + if (tx_en1 & !tx_en2) + tx_busy <= 1'b1; + else if (tx_count == (DATA_WIDTH+11 ) ) + tx_busy <= 1'b0; + + assign tx_o = shift_tx_data[0]; + + +endmodule // transmitter + + +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +///////////////////////////////////////////////////////////////////////////// + +`undef IP_UUID +`undef IP_NAME_CONCAT +`undef IP_MODULE_NAME diff --git a/hw/efinix_fpga/ip/uart/uart_define.vh b/hw/efinix_fpga/ip/uart/uart_define.vh new file mode 100644 index 0000000..4f0f893 --- /dev/null +++ b/hw/efinix_fpga/ip/uart/uart_define.vh @@ -0,0 +1,52 @@ +// ============================================================================= +// Generated by efx_ipmgr +// Version: 2022.2.322 +// IP Version: 2.0 +// ============================================================================= + +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2022 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// + +localparam BYTE = 1; +localparam CLOCK_FREQ = 50000000; +localparam BAUD = 115200; +localparam ENABLE_PARITY = 0; +localparam FIX_BAUDRATE = 1; +localparam PARITY_MODE = 0; +localparam BOOTUP_CHECK = 0; diff --git a/hw/efinix_fpga/ip/uart/uart_tmpl.v b/hw/efinix_fpga/ip/uart/uart_tmpl.v new file mode 100644 index 0000000..45a2939 --- /dev/null +++ b/hw/efinix_fpga/ip/uart/uart_tmpl.v @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2022 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// + +uart u_uart( +.tx_o ( tx_o ), +.rx_i ( rx_i ), +.tx_busy ( tx_busy ), +.rx_data ( rx_data ), +.rx_data_valid ( rx_data_valid ), +.rx_error ( rx_error ), +.rx_parity_error ( rx_parity_error ), +.rx_busy ( rx_busy ), +.baud_x16_ce ( baud_x16_ce ), +.clk ( clk ), +.reset ( reset ), +.tx_data ( tx_data ), +.baud_rate ( baud_rate ), +.tx_en ( tx_en ) +); diff --git a/hw/efinix_fpga/ip/uart/uart_tmpl.vhd b/hw/efinix_fpga/ip/uart/uart_tmpl.vhd new file mode 100644 index 0000000..422f662 --- /dev/null +++ b/hw/efinix_fpga/ip/uart/uart_tmpl.vhd @@ -0,0 +1,76 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2022 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// +------------- Begin Cut here for COMPONENT Declaration ------ +COMPONENT uart is +PORT ( +tx_o : out std_logic; +rx_i : in std_logic; +tx_busy : out std_logic; +rx_data : out std_logic_vector(7 downto 0); +rx_data_valid : out std_logic; +rx_error : out std_logic; +rx_parity_error : out std_logic; +rx_busy : out std_logic; +baud_x16_ce : out std_logic; +clk : in std_logic; +reset : in std_logic; +tx_data : in std_logic_vector(7 downto 0); +baud_rate : in std_logic_vector(2 downto 0); +tx_en : in std_logic); +END COMPONENT; +---------------------- End COMPONENT Declaration ------------ + +------------- Begin Cut here for INSTANTIATION Template ----- +u_uart : uart +PORT MAP ( +tx_o => tx_o, +rx_i => rx_i, +tx_busy => tx_busy, +rx_data => rx_data, +rx_data_valid => rx_data_valid, +rx_error => rx_error, +rx_parity_error => rx_parity_error, +rx_busy => rx_busy, +baud_x16_ce => baud_x16_ce, +clk => clk, +reset => reset, +tx_data => tx_data, +baud_rate => baud_rate, +tx_en => tx_en); +------------------------ End INSTANTIATION Template --------- diff --git a/hw/efinix_fpga/super6502.peri.xml b/hw/efinix_fpga/super6502.peri.xml index 1cb5a6f..cdcd9bb 100644 --- a/hw/efinix_fpga/super6502.peri.xml +++ b/hw/efinix_fpga/super6502.peri.xml @@ -1,5 +1,5 @@ - + @@ -306,6 +306,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/efinix_fpga/super6502.sv b/hw/efinix_fpga/super6502.sv index 8508e10..6609142 100644 --- a/hw/efinix_fpga/super6502.sv +++ b/hw/efinix_fpga/super6502.sv @@ -35,7 +35,10 @@ module super6502 input logic [15:0] i_sdr_DATA, output logic [15:0] o_sdr_DATA, output logic [15:0] o_sdr_DATA_oe, - output logic [1:0] o_sdr_DQM + output logic [1:0] o_sdr_DQM, + + input uart_rx, + output uart_tx ); @@ -68,6 +71,7 @@ logic w_sdram_cs; logic w_timer_cs; logic w_multiplier_cs; logic w_divider_cs; +logic w_uart_cs; addr_decode u_addr_decode( .i_addr(cpu_addr), @@ -76,6 +80,7 @@ addr_decode u_addr_decode( .o_timer_cs(w_timer_cs), .o_multiplier_cs(w_multiplier_cs), .o_divider_cs(w_divider_cs), + .o_uart_cs(w_uart_cs), .o_sdram_cs(w_sdram_cs) ); @@ -84,6 +89,7 @@ logic [7:0] w_leds_data_out; logic [7:0] w_timer_data_out; logic [7:0] w_multiplier_data_out; logic [7:0] w_divider_data_out; +logic [7:0] w_uart_data_out; logic [7:0] w_sdram_data_out; always_comb begin @@ -97,6 +103,8 @@ always_comb begin cpu_data_out = w_multiplier_data_out; else if (w_divider_cs) cpu_data_out = w_divider_data_out; + else if (w_uart_cs) + cpu_data_out = w_uart_data_out; else if (w_sdram_cs) cpu_data_out = w_sdram_data_out; else @@ -158,6 +166,22 @@ divider_wrapper u_divider( .addr(cpu_addr[2:0]) ); +logic w_uart_irqb; + +uart_wrapper u_uart( + .clk(clk_2), + .clk_50(clk_50), + .reset(~cpu_resb), + .i_data(cpu_data_in), + .o_data(w_uart_data_out), + .cs(w_uart_cs), + .rwb(cpu_rwb), + .addr(cpu_addr[0]), + .rx_i(uart_rx), + .tx_o(uart_tx), + .irqb(w_uart_irqb) +); + sdram_adapter u_sdram_adapter( .i_cpuclk(clk_2), .i_arst(~button_reset), diff --git a/hw/efinix_fpga/super6502.xml b/hw/efinix_fpga/super6502.xml index 73c6a07..5411962 100644 --- a/hw/efinix_fpga/super6502.xml +++ b/hw/efinix_fpga/super6502.xml @@ -1,5 +1,5 @@ - + @@ -20,6 +20,7 @@ + @@ -35,6 +36,9 @@ + + + @@ -62,6 +66,7 @@ + diff --git a/hw/efinix_fpga/uart_wrapper.sv b/hw/efinix_fpga/uart_wrapper.sv new file mode 100644 index 0000000..43fd860 --- /dev/null +++ b/hw/efinix_fpga/uart_wrapper.sv @@ -0,0 +1,106 @@ +module uart_wrapper( + input clk, + input clk_50, + input reset, + input [7:0] i_data, + output logic [7:0] o_data, + input cs, + input rwb, + input addr, + + input rx_i, + output tx_o, + + output logic irqb +); + +logic status, control; + +logic tx_busy, rx_busy; + +logic rx_data_valid, rx_error, rx_parity_error; +logic baud_x16_ce; + +logic tx_en; + +logic [7:0] tx_data, rx_data; + +uart u_uart( + .tx_o ( tx_o ), + .rx_i ( rx_i ), + .tx_busy ( tx_busy ), + .rx_data ( rx_data ), + .rx_data_valid ( rx_data_valid ), + .rx_error ( rx_error ), + .rx_parity_error ( rx_parity_error ), + .rx_busy ( rx_busy ), + .baud_x16_ce ( baud_x16_ce ), + .clk ( clk_50 ), + .reset ( reset ), + .tx_data ( tx_data ), + .baud_rate ( baud_rate ), + .tx_en ( tx_en ) +); + +enum bit [1:0] {READY, WAIT, TRANSMIT} state, next_state; + +always_ff @(negedge clk) begin + if (reset) begin + state = READY; + irqb <= '1; + end else begin + state <= next_state; + end + + case (addr) + 1'b0: begin + tx_data <= i_data; + end + + 1'b1: begin + control <= i_data; + end + endcase + +end + +always_comb begin + case (addr) + 1'b0: begin + o_data = rx_data; + end + + 1'b1: begin + o_data = status; + end + endcase +end + +always_comb begin + next_state = state; + + tx_en = 1'b0; + + case (state) + READY: begin + if (~rwb && addr == 1'b0) begin //write to transmit + tx_en = 1'b1; + next_state = WAIT; + end + end + + WAIT: begin + if (tx_busy) begin + next_state = TRANSMIT; + end + end + + TRANSMIT: begin + if (~tx_busy) begin + next_state = READY; + end + end + endcase +end + +endmodule \ No newline at end of file