From 5f6657a22721dd8d5f54b444d8cb17894b3817c2 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 5 Jan 2023 18:35:42 -0500 Subject: [PATCH] Add divider Adds a 16x16 divider to go with the multiplier. The divider is a single stage with no pipelining, which works at the slow 2MHz frequency. Doing this lowers the maximum clock frequency to 5. This is acceptable for now but means that the cpu can't be run at 14, which is the maximum frequency. --- hw/efinix_fpga/addr_decode.sv | 2 + hw/efinix_fpga/debug_profile.wizard.json | 1261 +++++++++++++------ hw/efinix_fpga/divider_wrapper.sv | 82 ++ hw/efinix_fpga/ip/bram/bram_ini.vh | 4 +- hw/efinix_fpga/ip/bram/init_hex.mem | 26 +- hw/efinix_fpga/ip/divider/divider.v | 390 ++++++ hw/efinix_fpga/ip/divider/divider_define.vh | 51 + hw/efinix_fpga/ip/divider/divider_tmpl.v | 49 + hw/efinix_fpga/ip/divider/divider_tmpl.vhd | 64 + hw/efinix_fpga/ip/divider/settings.json | 33 + hw/efinix_fpga/super6502.sv | 15 + hw/efinix_fpga/super6502.xml | 11 +- hw/efinix_fpga/test_programs/Makefile | 2 +- hw/efinix_fpga/test_programs/divider.s | 33 + 14 files changed, 1585 insertions(+), 438 deletions(-) create mode 100644 hw/efinix_fpga/divider_wrapper.sv create mode 100644 hw/efinix_fpga/ip/divider/divider.v create mode 100644 hw/efinix_fpga/ip/divider/divider_define.vh create mode 100644 hw/efinix_fpga/ip/divider/divider_tmpl.v create mode 100644 hw/efinix_fpga/ip/divider/divider_tmpl.vhd create mode 100644 hw/efinix_fpga/ip/divider/settings.json create mode 100644 hw/efinix_fpga/test_programs/divider.s diff --git a/hw/efinix_fpga/addr_decode.sv b/hw/efinix_fpga/addr_decode.sv index 43b1ed5..c304198 100644 --- a/hw/efinix_fpga/addr_decode.sv +++ b/hw/efinix_fpga/addr_decode.sv @@ -6,12 +6,14 @@ module addr_decode output o_leds_cs, output o_timer_cs, output o_multiplier_cs, + output o_divider_cs, output o_sdram_cs ); 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_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 65d6aa9..2232652 100644 --- a/hw/efinix_fpga/debug_profile.wizard.json +++ b/hw/efinix_fpga/debug_profile.wizard.json @@ -3,7 +3,7 @@ { "name": "la0", "type": "la", - "uuid": "aad3ac84df754229b9f34a0d7163d7ac", + "uuid": "60874ad57d6b45aaae3da20d2734bc20", "trigin_en": false, "trigout_en": false, "auto_inserted": true, @@ -31,35 +31,80 @@ "width": 1, "probe_type": 1 }, - { - "name": "u_timer/count_en", - "width": 1, - "probe_type": 1 - }, { "name": "cpu_data_out", "width": 8, "probe_type": 1 }, - { - "name": "u_timer/timer_latch", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_timer/pulsecount", - "width": 16, - "probe_type": 1 - }, - { - "name": "u_timer/timer_counter", - "width": 16, - "probe_type": 1 - }, { "name": "cpu_irqb", "width": 1, "probe_type": 1 + }, + { + "name": "u_divider/rwb", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/rfd", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/reset", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/remain", + "width": 16, + "probe_type": 1 + }, + { + "name": "u_divider/quotient", + "width": 16, + "probe_type": 1 + }, + { + "name": "u_divider/o_data", + "width": 8, + "probe_type": 1 + }, + { + "name": "u_divider/numer", + "width": 16, + "probe_type": 1 + }, + { + "name": "u_divider/i_data", + "width": 8, + "probe_type": 1 + }, + { + "name": "u_divider/denom", + "width": 16, + "probe_type": 1 + }, + { + "name": "u_divider/cs", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/clken", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/clk", + "width": 1, + "probe_type": 1 + }, + { + "name": "u_divider/addr", + "width": 3, + "probe_type": 1 } ] } @@ -321,392 +366,672 @@ "path": [] }, { - "name": "la0_probe4", - "net": "count_en", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe5[0]", + "name": "la0_probe4[0]", "net": "cpu_data_out[0]", "path": [] }, { - "name": "la0_probe5[1]", + "name": "la0_probe4[1]", "net": "cpu_data_out[1]", "path": [] }, { - "name": "la0_probe5[2]", + "name": "la0_probe4[2]", "net": "cpu_data_out[2]", "path": [] }, { - "name": "la0_probe5[3]", + "name": "la0_probe4[3]", "net": "cpu_data_out[3]", "path": [] }, { - "name": "la0_probe5[4]", + "name": "la0_probe4[4]", "net": "cpu_data_out[4]", "path": [] }, { - "name": "la0_probe5[5]", + "name": "la0_probe4[5]", "net": "cpu_data_out[5]", "path": [] }, { - "name": "la0_probe5[6]", + "name": "la0_probe4[6]", "net": "cpu_data_out[6]", "path": [] }, { - "name": "la0_probe5[7]", + "name": "la0_probe4[7]", "net": "cpu_data_out[7]", "path": [] }, { - "name": "la0_probe6[0]", - "net": "timer_latch[0]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[1]", - "net": "timer_latch[1]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[2]", - "net": "timer_latch[2]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[3]", - "net": "timer_latch[3]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[4]", - "net": "timer_latch[4]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[5]", - "net": "timer_latch[5]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[6]", - "net": "timer_latch[6]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[7]", - "net": "timer_latch[7]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[8]", - "net": "timer_latch[8]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[9]", - "net": "timer_latch[9]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[10]", - "net": "timer_latch[10]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[11]", - "net": "timer_latch[11]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[12]", - "net": "timer_latch[12]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[13]", - "net": "timer_latch[13]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[14]", - "net": "timer_latch[14]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe6[15]", - "net": "timer_latch[15]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[0]", - "net": "pulsecount[0]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[1]", - "net": "pulsecount[1]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[2]", - "net": "pulsecount[2]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[3]", - "net": "pulsecount[3]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[4]", - "net": "pulsecount[4]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[5]", - "net": "pulsecount[5]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[6]", - "net": "pulsecount[6]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[7]", - "net": "pulsecount[7]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[8]", - "net": "pulsecount[8]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[9]", - "net": "pulsecount[9]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[10]", - "net": "pulsecount[10]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[11]", - "net": "pulsecount[11]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[12]", - "net": "pulsecount[12]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[13]", - "net": "pulsecount[13]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[14]", - "net": "pulsecount[14]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe7[15]", - "net": "pulsecount[15]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[0]", - "net": "timer_counter[0]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[1]", - "net": "timer_counter[1]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[2]", - "net": "timer_counter[2]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[3]", - "net": "timer_counter[3]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[4]", - "net": "timer_counter[4]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[5]", - "net": "timer_counter[5]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[6]", - "net": "timer_counter[6]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[7]", - "net": "timer_counter[7]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[8]", - "net": "timer_counter[8]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[9]", - "net": "timer_counter[9]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[10]", - "net": "timer_counter[10]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[11]", - "net": "timer_counter[11]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[12]", - "net": "timer_counter[12]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[13]", - "net": "timer_counter[13]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[14]", - "net": "timer_counter[14]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe8[15]", - "net": "timer_counter[15]", - "path": [ - "u_timer" - ] - }, - { - "name": "la0_probe9", + "name": "la0_probe5", "net": "cpu_irqb", "path": [] + }, + { + "name": "la0_probe6", + "net": "rwb", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe7", + "net": "rfd", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe8", + "net": "reset", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[0]", + "net": "remain[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[1]", + "net": "remain[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[2]", + "net": "remain[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[3]", + "net": "remain[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[4]", + "net": "remain[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[5]", + "net": "remain[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[6]", + "net": "remain[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[7]", + "net": "remain[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[8]", + "net": "remain[8]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[9]", + "net": "remain[9]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[10]", + "net": "remain[10]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[11]", + "net": "remain[11]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[12]", + "net": "remain[12]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[13]", + "net": "remain[13]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[14]", + "net": "remain[14]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe9[15]", + "net": "remain[15]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[0]", + "net": "quotient[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[1]", + "net": "quotient[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[2]", + "net": "quotient[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[3]", + "net": "quotient[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[4]", + "net": "quotient[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[5]", + "net": "quotient[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[6]", + "net": "quotient[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[7]", + "net": "quotient[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[8]", + "net": "quotient[8]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[9]", + "net": "quotient[9]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[10]", + "net": "quotient[10]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[11]", + "net": "quotient[11]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[12]", + "net": "quotient[12]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[13]", + "net": "quotient[13]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[14]", + "net": "quotient[14]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe10[15]", + "net": "quotient[15]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[0]", + "net": "o_data[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[1]", + "net": "o_data[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[2]", + "net": "o_data[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[3]", + "net": "o_data[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[4]", + "net": "o_data[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[5]", + "net": "o_data[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[6]", + "net": "o_data[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe11[7]", + "net": "o_data[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[0]", + "net": "numer[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[1]", + "net": "numer[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[2]", + "net": "numer[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[3]", + "net": "numer[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[4]", + "net": "numer[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[5]", + "net": "numer[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[6]", + "net": "numer[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[7]", + "net": "numer[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[8]", + "net": "numer[8]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[9]", + "net": "numer[9]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[10]", + "net": "numer[10]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[11]", + "net": "numer[11]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[12]", + "net": "numer[12]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[13]", + "net": "numer[13]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[14]", + "net": "numer[14]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe12[15]", + "net": "numer[15]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[0]", + "net": "i_data[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[1]", + "net": "i_data[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[2]", + "net": "i_data[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[3]", + "net": "i_data[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[4]", + "net": "i_data[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[5]", + "net": "i_data[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[6]", + "net": "i_data[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe13[7]", + "net": "i_data[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[0]", + "net": "denom[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[1]", + "net": "denom[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[2]", + "net": "denom[2]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[3]", + "net": "denom[3]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[4]", + "net": "denom[4]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[5]", + "net": "denom[5]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[6]", + "net": "denom[6]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[7]", + "net": "denom[7]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[8]", + "net": "denom[8]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[9]", + "net": "denom[9]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[10]", + "net": "denom[10]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[11]", + "net": "denom[11]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[12]", + "net": "denom[12]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[13]", + "net": "denom[13]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[14]", + "net": "denom[14]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe14[15]", + "net": "denom[15]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe15", + "net": "cs", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe16", + "net": "clken", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe17", + "net": "clk", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe18[0]", + "net": "addr[0]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe18[1]", + "net": "addr[1]", + "path": [ + "u_divider" + ] + }, + { + "name": "la0_probe18[2]", + "net": "addr[2]", + "path": [ + "u_divider" + ] } ] } @@ -759,16 +1084,6 @@ "child": [], "path": [] }, - { - "name": "count_en", - "width": 1, - "clk_domain": "clk_2", - "selected_probe_type": "DATA AND TRIGGER", - "child": [], - "path": [ - "u_timer" - ] - }, { "name": "cpu_data_out", "width": 8, @@ -779,42 +1094,6 @@ "net_idx_left": 7, "net_idx_right": 0 }, - { - "name": "timer_latch", - "width": 16, - "clk_domain": "clk_2", - "selected_probe_type": "DATA AND TRIGGER", - "child": [], - "path": [ - "u_timer" - ], - "net_idx_left": 15, - "net_idx_right": 0 - }, - { - "name": "pulsecount", - "width": 16, - "clk_domain": "clk_2", - "selected_probe_type": "DATA AND TRIGGER", - "child": [], - "path": [ - "u_timer" - ], - "net_idx_left": 15, - "net_idx_right": 0 - }, - { - "name": "timer_counter", - "width": 16, - "clk_domain": "clk_2", - "selected_probe_type": "DATA AND TRIGGER", - "child": [], - "path": [ - "u_timer" - ], - "net_idx_left": 15, - "net_idx_right": 0 - }, { "name": "cpu_irqb", "width": 1, @@ -822,6 +1101,150 @@ "selected_probe_type": "DATA AND TRIGGER", "child": [], "path": [] + }, + { + "name": "rwb", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "rfd", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "reset", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "remain", + "width": 16, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 15, + "net_idx_right": 0 + }, + { + "name": "quotient", + "width": 16, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 15, + "net_idx_right": 0 + }, + { + "name": "o_data", + "width": 8, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 7, + "net_idx_right": 0 + }, + { + "name": "numer", + "width": 16, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 15, + "net_idx_right": 0 + }, + { + "name": "i_data", + "width": 8, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 7, + "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 + }, + { + "name": "cs", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "clken", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "clk", + "width": 1, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ] + }, + { + "name": "addr", + "width": 3, + "clk_domain": "clk_2", + "selected_probe_type": "DATA AND TRIGGER", + "child": [], + "path": [ + "u_divider" + ], + "net_idx_left": 2, + "net_idx_right": 0 } ], "top_module": "super6502", diff --git a/hw/efinix_fpga/divider_wrapper.sv b/hw/efinix_fpga/divider_wrapper.sv new file mode 100644 index 0000000..ef482ff --- /dev/null +++ b/hw/efinix_fpga/divider_wrapper.sv @@ -0,0 +1,82 @@ +module divider_wrapper( + input clk, + input reset, + input [7:0] i_data, + output logic [7:0] o_data, + input cs, + input rwb, + input [2:0] addr +); + +logic [15:0] numer, denom; +logic [15:0] quotient, remain; + +logic clken, rfd; + +assign clken = '1; + + +divider u_divider( +.numer ( numer ), +.denom ( denom ), +.clken ( clken ), +.clk ( clk ), +.reset ( reset ), +.quotient ( quotient ), +.remain ( remain ), +.rfd ( rfd ) +); + + +always_ff @(negedge clk) begin + if (reset) begin + numer <= '0; + denom <= '0; + end + + + if (cs & ~rwb) begin + case (addr) + 3'h0: begin + numer[7:0] <= i_data; + end + + 3'h1: begin + numer[15:8] <= i_data; + end + + 3'h2: begin + denom[7:0] <= i_data; + end + + 3'h3: begin + denom[15:8] <= i_data; + end + endcase + end +end + +always_comb begin + + case (addr) + 3'h4: begin + o_data = quotient[7:0]; + end + + 3'h5: begin + o_data = quotient[15:8]; + end + + 3'h6: begin + o_data = remain[7:0]; + end + + 3'h7: begin + o_data = remain[15:8]; + end + + endcase + +end + +endmodule \ No newline at end of file diff --git a/hw/efinix_fpga/ip/bram/bram_ini.vh b/hw/efinix_fpga/ip/bram/bram_ini.vh index f737621..a61bf89 100644 --- a/hw/efinix_fpga/ip/bram/bram_ini.vh +++ b/hw/efinix_fpga/ip/bram/bram_ini.vh @@ -4,8 +4,8 @@ input integer index;//Mode type input integer val_; //Port A index, Port B Index, Number of Items in Loop, Port A Start, Port B Start, reserved case (index) 0: bram_ini_table= -(val_== 0)?256'h008d000c8000a9000ef000f10008d00000000a9000ef000f00008d0007b000a9: -(val_== 1)?256'h0ef000ff0008d000ef000f5000ad000ef000f30008d00001000a9000ef000f20: +(val_== 0)?256'h008d0000d000a9000ef000e90008d00001000a9000ef000e80008d000c8000a9: +(val_== 1)?256'h0ef000ff0008d000ef000ec000ad000ef000eb0008d00000000a9000ef000ea0: (val_== 2)?256'h00000000000000000000000000000000000000000000000000e300080000cb00: (val_== 3)?256'h0000000000000000000000000000000000000000000000000000000000000000: (val_== 4)?256'h0000000000000000000000000000000000000000000000000000000000000000: diff --git a/hw/efinix_fpga/ip/bram/init_hex.mem b/hw/efinix_fpga/ip/bram/init_hex.mem index 05fb98d..58d6a4e 100644 --- a/hw/efinix_fpga/ip/bram/init_hex.mem +++ b/hw/efinix_fpga/ip/bram/init_hex.mem @@ -1,25 +1,25 @@ a9 -7b -8d -f0 -ef -a9 -00 -8d -f1 -ef -a9 c8 8d -f2 +e8 ef a9 01 8d -f3 +e9 +ef +a9 +0d +8d +ea +ef +a9 +00 +8d +eb ef ad -f5 +ec ef 8d ff diff --git a/hw/efinix_fpga/ip/divider/divider.v b/hw/efinix_fpga/ip/divider/divider.v new file mode 100644 index 0000000..7dc283a --- /dev/null +++ b/hw/efinix_fpga/ip/divider/divider.v @@ -0,0 +1,390 @@ +// ============================================================================= +// Generated by efx_ipmgr +// Version: 2022.2.322 +// IP Version: 2.2 +// ============================================================================= + +//////////////////////////////////////////////////////////////////////////////// +// 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 _1d82aa757d4b4554a855552eadc85243 +`define IP_NAME_CONCAT(a,b) a``b +`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID) +module divider ( +input [15:0] numer, +input [15:0] denom, +input clken, +input clk, +input reset, +output [15:0] quotient, +output [15:0] remain, +output rfd +); +`IP_MODULE_NAME(divider) #( +.NREPRESENTATION ("UNSIGNED"), +.WIDTHN (16), +.WIDTHD (16), +.DREPRESENTATION ("UNSIGNED"), +.PIPELINE (0), +.LATENCY (0) +) u_divider( +.numer ( numer ), +.denom ( denom ), +.clken ( clken ), +.clk ( clk ), +.reset ( reset ), +.quotient ( quotient ), +.remain ( remain ), +.rfd ( rfd ) +); + +endmodule + +`timescale 1ns / 1ps + +module `IP_MODULE_NAME(divider) ( + clk, + reset, + numer, + denom, + quotient, + remain, + rfd, + clken +); + +parameter WIDTHN = 8; +parameter WIDTHD = 8; +parameter LATENCY = 8; +parameter PIPELINE = 1; +parameter NREPRESENTATION = "UNSIGNED"; +parameter DREPRESENTATION = "UNSIGNED"; +parameter ENABLE_OUTREG = 0; + +input clk; +input reset; +input clken; +input [(WIDTHN-1):0] numer; +input [(WIDTHD-1):0] denom; +//output +output reg rfd; +output reg [(WIDTHN-1):0] quotient; +output reg [(WIDTHD-1):0] remain; + +wire [WIDTHN-1:0] numer_temp; +wire [WIDTHD-1:0] denom_temp; +wire sign_numer; +wire sign_denom; + +wire [(WIDTHN-1):0] quotient_copy; +wire [(WIDTHD-1):0] remain_copy; +reg sign_quotient[LATENCY:0]; + +genvar i, j; +// Main operation +generate begin + if(NREPRESENTATION == "SIGNED") begin + assign numer_temp = (numer[(WIDTHN-1)] == 1'b1) ? (~numer + 1) : numer; + assign sign_numer = (numer[(WIDTHN-1)] == 1'b1) ? 1'b1 : 1'b0; + end + else begin + assign numer_temp = numer; + assign sign_numer = 1'b0; + end + + if(DREPRESENTATION == "SIGNED") begin + assign denom_temp = (denom[(WIDTHD-1)] == 1'b1) ? (~denom + 1) : denom; + assign sign_denom = (denom[(WIDTHD-1)] == 1'b1) ? 1'b1 : 1'b0; + end + else begin + assign denom_temp = denom; + assign sign_denom = 1'b0; + end + + always @* begin + sign_quotient[0] = sign_numer ^ sign_denom; + end + + for (i=0; i 0) begin + reg [LATENCY-1:0] ready; + + assign sub = (ready[0] || ~clken_IP) ? ({{(WIDTHN-2){1'b0}}, numer_temp[(WIDTHN-1)]} - denom_sub) : ({remain_reg[(WIDTHN-2):0], quotient_reg[(WIDTHN-1)]} - denom_reg); + + always @(posedge clk,posedge reset) begin + if(reset) begin + ready <= {LATENCY{1'b0}}; + end + else if(clken) begin + if(ready[0] || ~clken_IP) begin + ready <= {1'b1, {LATENCY-1{1'b0}}}; + end + else begin + ready <= {1'b0, ready[LATENCY-1:1]}; + end + end + else begin + ready <= {LATENCY{1'b0}}; + end + end + + always @(posedge clk,posedge reset) begin + if(reset) begin + remain_reg <= {WIDTHN{1'b0}}; + quotient_reg <= {WIDTHN{1'b0}}; + denom_reg <= {WIDTHN{1'b0}}; + end + else if(clken) begin + if(ready[0] || ~clken_IP) begin + denom_reg <= denom_temp; + if (sub[(WIDTHN)] == 0) begin + remain_reg <= sub[(WIDTHN-1):0]; + quotient_reg <= {numer_temp[(WIDTHN-2):0], 1'b1}; + end + else begin + remain_reg <= {{(WIDTHN-2){1'b0}}, numer_temp[(WIDTHN-1)]}; + quotient_reg <= {numer_temp[(WIDTHN-2):0], 1'b0}; + end + end + else begin + if (sub[(WIDTHN)] == 0) begin + remain_reg <= sub[(WIDTHN-1):0]; + quotient_reg <= {quotient_reg[(WIDTHN-2):0], 1'b1}; + end + else begin + remain_reg <= {remain_reg[(WIDTHN-2):0], quotient_reg[(WIDTHN-1)]}; + quotient_reg <= {quotient_reg[(WIDTHN-2):0], 1'b0}; + end + end + end + end + + if (ENABLE_OUTREG) begin + always @(posedge clk,posedge reset) begin + if (reset) begin + rfd <= 1'b0; + end + else begin + rfd <= ready[0]; + end + end + end + else begin + always @* begin + rfd = ready[0]; + end + end + + always @* begin + quotient_combi[0] = quotient_reg; + remain_combi[0] = remain_reg; + end + + for (i=0; i numer, +denom => denom, +clken => clken, +clk => clk, +reset => reset, +quotient => quotient, +remain => remain, +rfd => rfd); +------------------------ End INSTANTIATION Template --------- diff --git a/hw/efinix_fpga/ip/divider/settings.json b/hw/efinix_fpga/ip/divider/settings.json new file mode 100644 index 0000000..cfe9d25 --- /dev/null +++ b/hw/efinix_fpga/ip/divider/settings.json @@ -0,0 +1,33 @@ +{ + "args": [ + "-o", + "divider", + "--base_path", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip", + "--vlnv", + { + "vendor": "efinixinc.com", + "library": "arithmetic", + "name": "efx_divider", + "version": "2.2" + } + ], + "conf": { + "NREPRESENTATION": "0", + "WIDTHN": "16", + "WIDTHD": "16", + "DREPRESENTATION": "0", + "PIPELINE": "0", + "LATENCY": "0" + }, + "output": { + "external_source_source": [ + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/divider/divider.v", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/divider/divider_define.vh", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/divider/divider_tmpl.vhd", + "/home/byron/Projects/super6502/hw/efinix_fpga/ip/divider/divider_tmpl.v" + ] + }, + "sw_version": "2022.2.322", + "generated_date": "2023-01-05T22:36:48.178317" +} \ No newline at end of file diff --git a/hw/efinix_fpga/super6502.sv b/hw/efinix_fpga/super6502.sv index 5c95ee1..411ba79 100644 --- a/hw/efinix_fpga/super6502.sv +++ b/hw/efinix_fpga/super6502.sv @@ -67,6 +67,7 @@ logic w_leds_cs; logic w_sdram_cs; logic w_timer_cs; logic w_multiplier_cs; +logic w_divider_cs; addr_decode u_addr_decode( .i_addr(cpu_addr), @@ -74,6 +75,7 @@ addr_decode u_addr_decode( .o_leds_cs(w_leds_cs), .o_timer_cs(w_timer_cs), .o_multiplier_cs(w_multiplier_cs), + .o_divider_cs(w_divider_cs), .o_sdram_cs(w_sdram_cs) ); @@ -81,6 +83,7 @@ logic [7:0] w_rom_data_out; 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_sdram_data_out; always_comb begin @@ -92,6 +95,8 @@ always_comb begin cpu_data_out = w_timer_data_out; else if (w_multiplier_cs) cpu_data_out = w_multiplier_data_out; + else if (w_divider_cs) + cpu_data_out = w_divider_data_out; else if (w_sdram_cs) cpu_data_out = w_sdram_data_out; else @@ -142,6 +147,16 @@ multiplier u_multiplier( .addr(cpu_addr[2:0]) ); +divider_wrapper u_divider( + .clk(clk_2), + .reset(~cpu_resb), + .i_data(cpu_data_in), + .o_data(w_divider_data_out), + .cs(w_divider_cs), + .rwb(cpu_rwb), + .addr(cpu_addr[2:0]) +); + 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 57982b6..0488b34 100644 --- a/hw/efinix_fpga/super6502.xml +++ b/hw/efinix_fpga/super6502.xml @@ -1,5 +1,5 @@ - + @@ -19,6 +19,7 @@ + @@ -31,6 +32,9 @@ + + + @@ -55,8 +59,9 @@ - + + @@ -89,7 +94,7 @@ - + diff --git a/hw/efinix_fpga/test_programs/Makefile b/hw/efinix_fpga/test_programs/Makefile index 8e7490b..331ad32 100644 --- a/hw/efinix_fpga/test_programs/Makefile +++ b/hw/efinix_fpga/test_programs/Makefile @@ -1,4 +1,4 @@ -TARGETS=stacktest runram timer timer_irq multiplier +TARGETS=stacktest runram timer timer_irq multiplier divider SRC=$(wildcard *.s) DIR=../ip/bram diff --git a/hw/efinix_fpga/test_programs/divider.s b/hw/efinix_fpga/test_programs/divider.s new file mode 100644 index 0000000..df27127 --- /dev/null +++ b/hw/efinix_fpga/test_programs/divider.s @@ -0,0 +1,33 @@ +.code + +LEDS = $efff + +DIVNL = $efe8 +DIVNH = $efe9 +DIVDL = $efea +DIVDH = $efeb + +DIVQL = $efec +DIVQH = $efed +DIVRL = $efee +DIVRH = $efef + +main: + lda #$c8 + sta DIVNL + lda #$01 + sta DIVNH + lda #$0d + sta DIVDL + lda #$00 + sta DIVDH + lda DIVQL + sta LEDS + wai + bra main + +.segment "VECTORS" + +.addr main +.addr main +.addr main \ No newline at end of file