From 15e3ae9688bfb86dd0054f46cfca845258d68a59 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 17 Mar 2022 13:31:56 -0500 Subject: [PATCH] Add SDRAM controller (controller) Turns out there are some issues with holding the chip select for the SDRAM controller high for too long, so there is a simple 2-state fsm which ensures that the chip select is only held for 1 clock cycle for writes and for as long as it takes to read the data from sdram for reads. --- hw/fpga/addr_decode.sv | 6 ++- hw/fpga/sdram_platform.qsys | 4 +- hw/fpga/super6502.qsf | 104 +++++++++++++++++++++++++++++++----- hw/fpga/super6502.sdc | 27 ++++++++-- hw/fpga/super6502.sv | 71 +++++++++++++++++++++++- 5 files changed, 191 insertions(+), 21 deletions(-) diff --git a/hw/fpga/addr_decode.sv b/hw/fpga/addr_decode.sv index 8d7da6a..c791668 100644 --- a/hw/fpga/addr_decode.sv +++ b/hw/fpga/addr_decode.sv @@ -1,14 +1,16 @@ module addr_decode( input logic [15:0] addr, output logic ram_cs, + output logic sdram_cs, output logic rom_cs, output logic hex_cs, output logic uart_cs, output logic irq_cs ); -assign rom_cs = addr[15]; -assign ram_cs = ~addr[15] && addr < 16'h7ff0; +assign rom_cs = addr >= 16'h8000; +assign ram_cs = addr < 16'h4000; +assign sdram_cs = addr >= 16'h4000 && addr < 16'h7ff0; assign hex_cs = addr >= 16'h7ff0 && addr < 16'h7ff4; assign uart_cs = addr >= 16'h7ff4 && addr < 16'h7ff6; assign irq_cs = addr == 16'h7fff; diff --git a/hw/fpga/sdram_platform.qsys b/hw/fpga/sdram_platform.qsys index 6e69912..ec790f6 100644 --- a/hw/fpga/sdram_platform.qsys +++ b/hw/fpga/sdram_platform.qsys @@ -6,7 +6,7 @@ version="1.0" description="" tags="INTERNAL_COMPONENT=true" - categories="" /> + categories="System" /> - + diff --git a/hw/fpga/super6502.qsf b/hw/fpga/super6502.qsf index 258c17c..55f3a8e 100644 --- a/hw/fpga/super6502.qsf +++ b/hw/fpga/super6502.qsf @@ -188,7 +188,7 @@ set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_sob set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_sync set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clk_50 set_global_assignment -name ENABLE_SIGNALTAP OFF -set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp +set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp2.stp set_location_assignment PIN_F20 -to HEX4[6] set_location_assignment PIN_F19 -to HEX4[5] set_location_assignment PIN_H19 -to HEX4[4] @@ -205,17 +205,6 @@ set_location_assignment PIN_F18 -to HEX4[0] set_location_assignment PIN_E20 -to HEX4[1] set_location_assignment PIN_AB5 -to UART_RXD set_location_assignment PIN_AB6 -to UART_TXD -set_global_assignment -name SYSTEMVERILOG_FILE uart.sv -set_global_assignment -name SYSTEMVERILOG_FILE addr_decode.sv -set_global_assignment -name SYSTEMVERILOG_FILE bb_spi_controller.sv -set_global_assignment -name SYSTEMVERILOG_FILE super6502.sv -set_global_assignment -name QIP_FILE ram.qip -set_global_assignment -name SDC_FILE super6502.sdc -set_global_assignment -name QIP_FILE rom.qip -set_global_assignment -name SYSTEMVERILOG_FILE HexDriver.sv -set_global_assignment -name SYSTEMVERILOG_FILE SevenSeg.sv -set_global_assignment -name QIP_FILE cpu_clk.qip -set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_RXD set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[6] @@ -283,4 +272,95 @@ set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[8] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[9] set_location_assignment PIN_A7 -to button_1 set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to button_1 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CAS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CKE +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_LDQM +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_RAS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_UDQM +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_WE_N +set_location_assignment PIN_U17 -to DRAM_ADDR[0] +set_location_assignment PIN_T20 -to DRAM_ADDR[10] +set_location_assignment PIN_P20 -to DRAM_ADDR[11] +set_location_assignment PIN_R20 -to DRAM_ADDR[12] +set_location_assignment PIN_W19 -to DRAM_ADDR[1] +set_location_assignment PIN_V18 -to DRAM_ADDR[2] +set_location_assignment PIN_U18 -to DRAM_ADDR[3] +set_location_assignment PIN_U19 -to DRAM_ADDR[4] +set_location_assignment PIN_T18 -to DRAM_ADDR[5] +set_location_assignment PIN_T19 -to DRAM_ADDR[6] +set_location_assignment PIN_R18 -to DRAM_ADDR[7] +set_location_assignment PIN_P18 -to DRAM_ADDR[8] +set_location_assignment PIN_P19 -to DRAM_ADDR[9] +set_location_assignment PIN_T21 -to DRAM_BA[0] +set_location_assignment PIN_T22 -to DRAM_BA[1] +set_location_assignment PIN_U21 -to DRAM_CAS_N +set_location_assignment PIN_N22 -to DRAM_CKE +set_location_assignment PIN_L14 -to DRAM_CLK +set_location_assignment PIN_U20 -to DRAM_CS_N +set_location_assignment PIN_Y21 -to DRAM_DQ[0] +set_location_assignment PIN_H21 -to DRAM_DQ[10] +set_location_assignment PIN_H22 -to DRAM_DQ[11] +set_location_assignment PIN_G22 -to DRAM_DQ[12] +set_location_assignment PIN_G20 -to DRAM_DQ[13] +set_location_assignment PIN_G19 -to DRAM_DQ[14] +set_location_assignment PIN_F22 -to DRAM_DQ[15] +set_location_assignment PIN_Y20 -to DRAM_DQ[1] +set_location_assignment PIN_AA22 -to DRAM_DQ[2] +set_location_assignment PIN_AA21 -to DRAM_DQ[3] +set_location_assignment PIN_Y22 -to DRAM_DQ[4] +set_location_assignment PIN_W22 -to DRAM_DQ[5] +set_location_assignment PIN_W20 -to DRAM_DQ[6] +set_location_assignment PIN_V21 -to DRAM_DQ[7] +set_location_assignment PIN_P21 -to DRAM_DQ[8] +set_location_assignment PIN_J22 -to DRAM_DQ[9] +set_location_assignment PIN_V22 -to DRAM_LDQM +set_location_assignment PIN_U22 -to DRAM_RAS_N +set_location_assignment PIN_J21 -to DRAM_UDQM +set_location_assignment PIN_V20 -to DRAM_WE_N +set_global_assignment -name QIP_FILE sdram_platform/synthesis/sdram_platform.qip +set_global_assignment -name SYSTEMVERILOG_FILE uart.sv +set_global_assignment -name SYSTEMVERILOG_FILE addr_decode.sv +set_global_assignment -name SYSTEMVERILOG_FILE bb_spi_controller.sv +set_global_assignment -name SYSTEMVERILOG_FILE super6502.sv +set_global_assignment -name QIP_FILE ram.qip +set_global_assignment -name SDC_FILE super6502.sdc +set_global_assignment -name QIP_FILE rom.qip +set_global_assignment -name SYSTEMVERILOG_FILE HexDriver.sv +set_global_assignment -name SYSTEMVERILOG_FILE SevenSeg.sv +set_global_assignment -name QIP_FILE cpu_clk.qip +set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp +set_global_assignment -name SIGNALTAP_FILE output_files/stp2.stp set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/hw/fpga/super6502.sdc b/hw/fpga/super6502.sdc index 1e1dc19..b6b8652 100644 --- a/hw/fpga/super6502.sdc +++ b/hw/fpga/super6502.sdc @@ -1,11 +1,30 @@ #************************************************************** # Create Clock (where ‘clk’ is the user-defined system clock name) #************************************************************** -create_clock -name {clk_50} -period 20ns -waveform {0.000 5.000} [get_ports {clk}] +create_clock -name {clk_50} -period 20ns -waveform {0.000 5.000} [get_ports {clk_50}] + +create_generated_clock -source [get_pins {u0|sdram_pll|sd1|pll7|clk[1] }] \ + -name clk_dram_ext [get_ports {DRAM_CLK}] + +derive_pll_clocks + # Constrain the input I/O path -set_input_delay -clock {clk} -max 3 [all_inputs] -set_input_delay -clock {clk} -min 2 [all_inputs] +# set_input_delay -clock {clk} -max 3 [all_inputs] +# set_input_delay -clock {clk} -min 2 [all_inputs] # Constrain the output I/O path -set_output_delay -clock {clk} 2 [all_outputs] +#set_output_delay -clock {clk} 2 [all_outputs] derive_clock_uncertainty + +set_input_delay -max -clock clk_dram_ext 5.9 [get_ports DRAM_DQ*] +set_input_delay -min -clock clk_dram_ext 3.0 [get_ports DRAM_DQ*] + + +set_multicycle_path -from [get_clocks {clk_dram_ext}] \ + -to [get_clocks {u0|sdram_pll|sd1|pll7|clk[0] }] \ + -setup 2 + +set_output_delay -max -clock clk_dram_ext 1.6 [get_ports {DRAM_DQ* DRAM_*DQM}] +set_output_delay -min -clock clk_dram_ext -0.9 [get_ports {DRAM_DQ* DRAM_*DQM}] +set_output_delay -max -clock clk_dram_ext 1.6 [get_ports {DRAM_ADDR* DRAM_BA* DRAM_RAS_N DRAM_CAS_N DRAM_WE_N DRAM_CKE DRAM_CS_N}] +set_output_delay -min -clock clk_dram_ext -0.9 [get_ports {DRAM_ADDR* DRAM_BA* DRAM_RAS_N DRAM_CAS_N DRAM_WE_N DRAM_CKE DRAM_CS_N}] \ No newline at end of file diff --git a/hw/fpga/super6502.sv b/hw/fpga/super6502.sv index af0eae9..073a06d 100644 --- a/hw/fpga/super6502.sv +++ b/hw/fpga/super6502.sv @@ -24,7 +24,20 @@ module super6502( output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, input logic UART_RXD, - output logic UART_TXD + output logic UART_TXD, + + ///////// SDRAM ///////// + output DRAM_CLK, + output DRAM_CKE, + output [12: 0] DRAM_ADDR, + output [ 1: 0] DRAM_BA, + inout [15: 0] DRAM_DQ, + output DRAM_LDQM, + output DRAM_UDQM, + output DRAM_CS_N, + output DRAM_WE_N, + output DRAM_CAS_N, + output DRAM_RAS_N ); logic rst; @@ -41,10 +54,12 @@ assign cpu_data = cpu_rwb ? cpu_data_out : 'z; logic [7:0] rom_data_out; logic [7:0] ram_data_out; +logic [7:0] sdram_data_out; logic [7:0] uart_data_out; logic [7:0] irq_data_out; logic ram_cs; +logic sdram_cs; logic rom_cs; logic hex_cs; logic uart_cs; @@ -69,6 +84,7 @@ assign cpu_irqb = irq_data_out == 0; addr_decode decode( .addr(cpu_addr), .ram_cs(ram_cs), + .sdram_cs(sdram_cs), .rom_cs(rom_cs), .hex_cs(hex_cs), .uart_cs(uart_cs), @@ -79,6 +95,8 @@ addr_decode decode( always_comb begin if (ram_cs) cpu_data_out = ram_data_out; + else if (sdram_cs) + cpu_data_out = sdram_data_out; else if (rom_cs) cpu_data_out = rom_data_out; else if (uart_cs) @@ -89,7 +107,58 @@ always_comb begin cpu_data_out = 'x; end +enum logic {S_0, S_1 } teststate, next_teststate; +logic ack; +logic write; +logic _sdram_cs; +always @(posedge clk_50) begin + if (rst) + teststate <= S_0; + else + teststate <= next_teststate; +end + +always_comb begin + next_teststate = teststate; + write = '0; + _sdram_cs = '0; + case (teststate) + S_0: begin + write = sdram_cs & ~cpu_rwb & cpu_phi2; + _sdram_cs = sdram_cs & cpu_phi2; + if (sdram_cs & ~cpu_rwb & ack) + next_teststate = S_1; + end + S_1: begin + if (~(sdram_cs & ~cpu_rwb)) + next_teststate = S_0; + end + endcase +end + +sdram_platform u0 ( + .clk_clk (clk_50), // clk.clk + .reset_reset_n (1'b1), // reset.reset_n + .ext_bus_address (cpu_addr), // ext_bus.address + .ext_bus_byte_enable (1'b1), // .byte_enable + .ext_bus_read (_sdram_cs & cpu_rwb), // .read + .ext_bus_write (write), // .write + .ext_bus_write_data (cpu_data_in), // .write_data + .ext_bus_acknowledge (ack), // .acknowledge + .ext_bus_read_data (sdram_data_out), // .read_data + //SDRAM + .sdram_clk_clk(DRAM_CLK), //clk_sdram.clk + .sdram_wire_addr(DRAM_ADDR), //sdram_wire.addr + .sdram_wire_ba(DRAM_BA), //.ba + .sdram_wire_cas_n(DRAM_CAS_N), //.cas_n + .sdram_wire_cke(DRAM_CKE), //.cke + .sdram_wire_cs_n(DRAM_CS_N), //.cs_n + .sdram_wire_dq(DRAM_DQ), //.dq + .sdram_wire_dqm({DRAM_UDQM,DRAM_LDQM}), //.dqm + .sdram_wire_ras_n(DRAM_RAS_N), //.ras_n + .sdram_wire_we_n(DRAM_WE_N) //.we_n +); ram main_memory(