From 46bd0dd0c1c987083ac25fc0398a84b3dbf3b8f6 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 16 Aug 2019 18:59:26 +0200 Subject: [PATCH 1/4] Archie: common FDC with the ST core --- .../archie/fpga/mist/archimedes_mist_top.qsf | 8 +- cores/archie/rtl/archimedes_top.v | 96 +- cores/archie/rtl/fdc1772.v | 1175 ++++++++++------- cores/archie/rtl/floppy.v | 224 ++-- 4 files changed, 865 insertions(+), 638 deletions(-) diff --git a/cores/archie/fpga/mist/archimedes_mist_top.qsf b/cores/archie/fpga/mist/archimedes_mist_top.qsf index 9108bcf..62862db 100644 --- a/cores/archie/fpga/mist/archimedes_mist_top.qsf +++ b/cores/archie/fpga/mist/archimedes_mist_top.qsf @@ -41,7 +41,7 @@ set_global_assignment -name DEVICE EP3C25E144C8 set_global_assignment -name TOP_LEVEL_ENTITY archimedes_mist_top set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:48:24 SEPTEMBER 20, 2014" -set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26" set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 @@ -136,7 +136,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_* set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to DRAM_* set_global_assignment -name ENABLE_SIGNALTAP OFF -set_global_assignment -name USE_SIGNALTAP_FILE output_files/sd.stp +set_global_assignment -name USE_SIGNALTAP_FILE output_files/fdc.stp set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF set_global_assignment -name ENABLE_NCE_PIN OFF @@ -171,12 +171,13 @@ set_global_assignment -name SMART_RECOMPILE ON set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON -set_global_assignment -name FITTER_EFFORT "AUTO FIT" +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" set_instance_assignment -name FAST_INPUT_REGISTER ON -to DRAM_DQ[*] set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to DRAM_DQ[*] set_global_assignment -name SEED 1 set_global_assignment -name ENABLE_DRC_SETTINGS OFF set_location_assignment PLL_1 -to CLOCKS|altpll_component|auto_generated|pll1 +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA set_global_assignment -name VERILOG_FILE archimedes_mist_top.v set_global_assignment -name SYSTEMVERILOG_FILE rgb2ypbpr.sv set_global_assignment -name VERILOG_FILE sigma_delta_dac.v @@ -226,5 +227,4 @@ set_global_assignment -name QIP_FILE rom_reconfig_36.qip set_global_assignment -name QIP_FILE pll_vidc.qip set_global_assignment -name SIGNALTAP_FILE output_files/vidc.stp set_global_assignment -name SIGNALTAP_FILE output_files/sd.stp -set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/cores/archie/rtl/archimedes_top.v b/cores/archie/rtl/archimedes_top.v index 20e215b..d16a653 100644 --- a/cores/archie/rtl/archimedes_top.v +++ b/cores/archie/rtl/archimedes_top.v @@ -297,63 +297,63 @@ podules PODULES( .speed_i ( ioc_speed ), - .wb_cyc ( cpu_cyc & podules_en), - .wb_stb ( cpu_stb & podules_en), - .wb_we ( cpu_we & podules_en), + .wb_cyc ( cpu_cyc & podules_en ), + .wb_stb ( cpu_stb & podules_en ), + .wb_we ( cpu_we & podules_en ), .wb_dat_o ( pod_dat_o ), .wb_dat_i ( cpu_dat_o[15:0] ), - .wb_adr ( cpu_address[15:2] ) + .wb_adr ( cpu_address[15:2] ), ); -wire [7:0] floppy_dat_o; -wire floppy_en = ioc_cs & ioc_select[1]; +wire [7:0] floppy_dat_o; +wire floppy_en = ioc_cs & ioc_select[1]; // floppy drive signals. -wire [3:0] floppy_drive; -wire floppy_side; -wire floppy_motor; -wire floppy_inuse; -wire floppy_density; -wire floppy_reset; - -fdc1772 FDC1772 ( - - .clkcpu ( CLKCPU_I ), - .clk8m_en ( ioc_clk8m_en ), - - .wb_cyc ( cpu_cyc & floppy_en ), - .wb_stb ( cpu_stb & floppy_en ), - .wb_we ( cpu_we & floppy_en ), - - .wb_dat_o ( floppy_dat_o ), - .wb_dat_i ( cpu_dat_o[23:16] ), - .wb_adr ( cpu_address[15:2] ), - - .floppy_firq ( floppy_firq ), - .floppy_drq ( floppy_drq ), - - .img_mounted ( img_mounted ), - .img_size ( img_size ), - .img_wp ( 0 ), - .sd_lba ( sd_lba ), - .sd_rd ( sd_rd ), - .sd_wr ( sd_wr ), - .sd_ack ( sd_ack ), - .sd_buff_addr ( sd_buff_addr ), - .sd_dout ( sd_dout ), - .sd_din ( sd_din ), - .sd_dout_strobe ( sd_dout_strobe ), - .sd_din_strobe ( sd_din_strobe ), +wire [3:0] floppy_drive; +wire floppy_side; +wire floppy_motor; +wire floppy_inuse; +wire floppy_density; +wire floppy_reset; - .floppy_drive ( floppy_drive ), - .floppy_motor ( floppy_motor ), - .floppy_inuse ( floppy_inuse ), - .floppy_side ( floppy_side ), - .floppy_density ( floppy_density ), - .floppy_reset ( floppy_reset ) +wire fdc_sel = cpu_stb & cpu_cyc & floppy_en; + +fdc1772 #(.CLK(42000000)) FDC1772 ( + + .clkcpu ( CLKCPU_I ), + .clk8m_en ( ioc_clk8m_en ), + + .cpu_sel ( fdc_sel ), + .cpu_rw ( !cpu_we ), + .cpu_addr ( cpu_address[3:2] ), + .cpu_dout ( floppy_dat_o ), + .cpu_din ( cpu_dat_o[23:16] ), + + .irq ( floppy_firq ), + .drq ( floppy_drq ), + + .img_mounted ( img_mounted ), + .img_size ( img_size ), + .img_wp ( 0 ), + .sd_lba ( sd_lba ), + .sd_rd ( sd_rd ), + .sd_wr ( sd_wr ), + .sd_ack ( sd_ack ), + .sd_buff_addr ( sd_buff_addr ), + .sd_dout ( sd_dout ), + .sd_din ( sd_din ), + .sd_dout_strobe ( sd_dout_strobe ), + .sd_din_strobe ( sd_din_strobe ), + + .floppy_drive ( floppy_drive ), +// .floppy_motor ( floppy_motor ), +// .floppy_inuse ( floppy_inuse ), + .floppy_side ( floppy_side ), +// .floppy_density ( floppy_density ), + .floppy_reset ( floppy_reset ) ); - + wire [7:0] latches_dat_o; wire latches_en = ioc_cs & ioc_select[5] & (ioc_speed == 2'd2); diff --git a/cores/archie/rtl/fdc1772.v b/cores/archie/rtl/fdc1772.v index e94853c..d657d4b 100644 --- a/cores/archie/rtl/fdc1772.v +++ b/cores/archie/rtl/fdc1772.v @@ -18,67 +18,119 @@ // // TODO: -// - Don't directly set track register but control it with the step commands // - 30ms settle time after step before data can be read -// - some parts are hard coded for archie floppy format (not dos) +// - implement sector size 0,1 module fdc1772 ( - input clkcpu, // system cpu clock. - input clk8m_en, + input clkcpu, // system cpu clock. + input clk8m_en, - // external set signals - input [3:0] floppy_drive, - input floppy_side, - input floppy_motor, - input floppy_inuse, - input floppy_density, - input floppy_reset, + // external set signals + input [3:0] floppy_drive, + input floppy_side, + input floppy_reset, - // interrupts - output floppy_firq, // floppy fast irq - output floppy_drq, // data request interrupt + // interrupts + output reg irq, + output reg drq, // data request - // "wishbone bus" the ack is externally generated currently. - input wb_cyc, - input wb_stb, - input wb_we, + input [1:0] cpu_addr, + input cpu_sel, + input cpu_rw, + input [7:0] cpu_din, + output reg [7:0] cpu_dout, - input [15:2] wb_adr, // la - input [7:0] wb_dat_i, // bd - output reg [7:0] wb_dat_o, // bd - - // place any signals that need to be passed up to the top after here. - input [1:0] img_mounted, // signaling that new image has been mounted - input img_wp, // write protect. latched at img_mounted - input [31:0] img_size, // size of image in bytes - output [31:0] sd_lba, - output reg [1:0] sd_rd, - output reg [1:0] sd_wr, - input sd_ack, - input [8:0] sd_buff_addr, - input [7:0] sd_dout, - output [7:0] sd_din, - input sd_dout_strobe, - input sd_din_strobe + // place any signals that need to be passed up to the top after here. + input [1:0] img_mounted, // signaling that new image has been mounted + input [1:0] img_wp, // write protect + input [31:0] img_size, // size of image in bytes + output reg[31:0] sd_lba, + output reg [1:0] sd_rd, + output reg [1:0] sd_wr, + input sd_ack, + input [8:0] sd_buff_addr, + input [7:0] sd_dout, + output [7:0] sd_din, + input sd_dout_strobe, + input sd_din_strobe ); -localparam CLK = 42000000; -localparam CLK_EN = 8000000; +parameter CLK = 32000000; +parameter CLK_EN = 16'd8000; // in kHz +parameter SECTOR_SIZE_CODE = 2'd3; // sec size 0=128, 1=256, 2=512, 3=1024 +parameter SECTOR_BASE = 1'b0; // number of first sector on track (archie 0, dos 1) + +localparam SECTOR_SIZE = 11'd128 << SECTOR_SIZE_CODE; // ------------------------------------------------------------------------- -// --------------------- IO controller status handling --------------------- +// --------------------- IO controller image handling ---------------------- // ------------------------------------------------------------------------- -assign sd_lba = { 4'd10*track[6:0] + (floppy_side ? 0 : 4'd5) + sector[3:0], s_odd }; +always @(*) begin + if (SECTOR_SIZE_CODE == 3) + // archie + sd_lba = {(16'd0 + (fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0], s_odd }; + else + // st + sd_lba = ((fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0] - 1'd1; +end reg [1:0] floppy_ready = 0; -reg [1:0] floppy_wp = 1; wire floppy_present = (floppy_drive == 4'b1110)?floppy_ready[0]: - (floppy_drive == 4'b1101)?floppy_ready[1]:1'b0; + (floppy_drive == 4'b1101)?floppy_ready[1]:1'b0; -wire floppy_write_protected = (floppy_drive == 4'b1110)?floppy_wp[0]: - (floppy_drive == 4'b1101)?floppy_wp[1]:1'b1; +wire floppy_write_protected = (floppy_drive == 4'b1110)?img_wp[0]: + (floppy_drive == 4'b1101)?img_wp[1]:1'b1; + +reg [10:0] sector_len[2]; +reg [4:0] spt[2]; // sectors/track +reg [9:0] gap_len[2]; // gap len/sector +reg [1:0] doubleside; +reg [1:0] hd; + +wire [11:0] image_sectors = img_size[20:9]; +reg [11:0] image_sps; // sectors/side +reg [4:0] image_spt; // sectors/track +reg [9:0] image_gap_len; +reg image_doubleside; +wire image_hd = img_size[20]; + +always @(*) begin + if (SECTOR_SIZE_CODE == 3) begin + // archie + image_doubleside = 1'b1; + image_spt = image_hd ? 5'd10 : 5'd5; + image_gap_len = 10'd220; + end else begin + // this block is valid for the .st format (or similar arrangement) + image_doubleside = 1'b0; + image_sps = image_sectors; + if (image_sectors > (85*12)) begin + image_doubleside = 1'b1; + image_sps = image_sectors >> 1'b1; + end + if (image_hd) image_sps = image_sps >> 1'b1; + + // spt : 9-12, tracks: 79-85 + case (image_sps) + 711,720,729,738,747,756,765 : image_spt = 5'd9; + 790,800,810,820,830,840,850 : image_spt = 5'd10; + 948,960,972,984,996,1008,1020 : image_spt = 5'd12; + default : image_spt = 5'd11; + endcase; + + if (image_hd) image_spt = image_spt << 1'b1; + + // SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN) = 6250/SPT - (512+6) + case (image_spt) + 5'd9, 5'd18: image_gap_len = 10'd176; + 5'd10,5'd20: image_gap_len = 10'd107; + 5'd11,5'd22: image_gap_len = 10'd50; + default : image_gap_len = 10'd2; + endcase; + end +end always @(posedge clkcpu) begin reg [1:0] img_mountedD; @@ -86,56 +138,56 @@ always @(posedge clkcpu) begin img_mountedD <= img_mounted; if (~img_mountedD[0] && img_mounted[0]) begin floppy_ready[0] <= |img_size; - floppy_wp[0] <= img_wp; + sector_len[0] <= SECTOR_SIZE; + spt[0] <= image_spt; + gap_len[0] <= image_gap_len; + doubleside[0] <= image_doubleside; + hd[0] <= image_hd; end if (~img_mountedD[1] && img_mounted[1]) begin floppy_ready[1] <= |img_size; - floppy_wp[1] <= img_wp; + sector_len[1] <= SECTOR_SIZE; + spt[1] <= image_spt; + gap_len[1] <= image_gap_len; + doubleside[1] <= image_doubleside; + hd[1] <= image_hd; end end // ------------------------------------------------------------------------- // ---------------------------- IRQ/DRQ handling --------------------------- // ------------------------------------------------------------------------- -reg irq; +reg cpu_selD; +always @(posedge clkcpu) cpu_selD <= cpu_sel; +wire cpu_we = ~cpu_selD & cpu_sel & ~cpu_rw; + reg irq_set; -// floppy_reset and read of status register clears irq -reg cpu_read_status; +// floppy_reset and read of status register/write of command register clears irq +reg cpu_rw_cmdstatus; always @(posedge clkcpu) - cpu_read_status <= wb_stb && wb_cyc && !wb_we && - (wb_adr[3:2] == FDC_REG_CMDSTATUS); - -wire irq_clr = !floppy_reset || cpu_read_status; - -always @(posedge clkcpu or posedge irq_clr) begin - reg irq_setD; + cpu_rw_cmdstatus <= ~cpu_selD && cpu_sel && cpu_addr == FDC_REG_CMDSTATUS; +wire irq_clr = !floppy_reset || cpu_rw_cmdstatus; + +always @(posedge clkcpu) begin if(irq_clr) irq <= 1'b0; - else begin - irq_setD <= irq_set; - if(~irq_setD & irq_set) irq <= 1'b1; - end + else if(irq_set) irq <= 1'b1; end - -assign floppy_firq = irq; - -reg drq; + reg drq_set; reg cpu_rw_data; always @(posedge clkcpu) - cpu_rw_data <= wb_stb && wb_cyc && (wb_adr[3:2] == FDC_REG_DATA); + cpu_rw_data <= ~cpu_selD && cpu_sel && cpu_addr == FDC_REG_DATA; wire drq_clr = !floppy_reset || cpu_rw_data; -always @(posedge clkcpu or posedge drq_clr) begin - if(drq_clr) drq <= 1'b0; - else if(drq_set) drq <= 1'b1; +always @(posedge clkcpu) begin + if(drq_clr) drq <= 1'b0; + else if(drq_set) drq <= 1'b1; end -assign floppy_drq = drq; - // ------------------------------------------------------------------------- // -------------------- virtual floppy drive mechanics --------------------- // ------------------------------------------------------------------------- @@ -146,28 +198,35 @@ assign floppy_drq = drq; wire fd0_index; wire fd0_ready; wire [6:0] fd0_track; -wire [3:0] fd0_sector; +wire [4:0] fd0_sector; wire fd0_sector_hdr; wire fd0_sector_data; wire fd0_dclk; floppy #(.SYS_CLK(CLK)) floppy0 ( - .clk ( clkcpu ), + .clk ( clkcpu ), - // control signals into floppy - .select (!floppy_drive[0] ), - .motor_on ( motor_on ), - .step_in ( step_in ), - .step_out ( step_out ), + // control signals into floppy + .select (!floppy_drive[0] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), - // status signals generated by floppy - .dclk_en ( fd0_dclk ), - .track ( fd0_track ), - .sector ( fd0_sector ), - .sector_hdr ( fd0_sector_hdr ), - .sector_data ( fd0_sector_data ), - .ready ( fd0_ready ), - .index ( fd0_index ) + // physical parameters + .sector_len ( sector_len[0] ), + .spt ( spt[0] ), + .sector_gap_len ( gap_len[0] ), + .sector_base ( SECTOR_BASE ), + .hd ( hd[0] ), + + // status signals generated by floppy + .dclk_en ( fd0_dclk ), + .track ( fd0_track ), + .sector ( fd0_sector ), + .sector_hdr ( fd0_sector_hdr ), + .sector_data ( fd0_sector_data ), + .ready ( fd0_ready ), + .index ( fd0_index ) ); // ------------------------------------------------------------------------- @@ -176,28 +235,35 @@ floppy #(.SYS_CLK(CLK)) floppy0 ( wire fd1_index; wire fd1_ready; wire [6:0] fd1_track; -wire [3:0] fd1_sector; +wire [4:0] fd1_sector; wire fd1_sector_hdr; wire fd1_sector_data; wire fd1_dclk; floppy #(.SYS_CLK(CLK)) floppy1 ( - .clk ( clkcpu ), + .clk ( clkcpu ), - // control signals into floppy - .select (!floppy_drive[1] ), - .motor_on ( motor_on ), - .step_in ( step_in ), - .step_out ( step_out ), + // control signals into floppy + .select (!floppy_drive[1] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), - // status signals generated by floppy - .dclk_en ( fd1_dclk ), - .track ( fd1_track ), - .sector ( fd1_sector ), - .sector_hdr ( fd1_sector_hdr ), - .sector_data ( fd1_sector_data ), - .ready ( fd1_ready ), - .index ( fd1_index ) + // physical parameters + .sector_len ( sector_len[1] ), + .spt ( spt[1] ), + .sector_gap_len ( gap_len[1] ), + .sector_base ( SECTOR_BASE ), + .hd ( hd[1] ), + + // status signals generated by floppy + .dclk_en ( fd1_dclk ), + .track ( fd1_track ), + .sector ( fd1_sector ), + .sector_hdr ( fd1_sector_hdr ), + .sector_data ( fd1_sector_data ), + .ready ( fd1_ready ), + .index ( fd1_index ) ); // ------------------------------------------------------------------------- @@ -206,28 +272,35 @@ floppy #(.SYS_CLK(CLK)) floppy1 ( wire fd2_index; wire fd2_ready; wire [6:0] fd2_track; -wire [3:0] fd2_sector; +wire [4:0] fd2_sector; wire fd2_sector_hdr; wire fd2_sector_data; wire fd2_dclk; floppy #(.SYS_CLK(CLK)) floppy2 ( - .clk ( clkcpu ), + .clk ( clkcpu ), - // control signals into floppy - .select (!floppy_drive[2] ), - .motor_on ( motor_on ), - .step_in ( step_in ), - .step_out ( step_out ), + // control signals into floppy + .select (!floppy_drive[2] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), - // status signals generated by floppy - .dclk_en ( fd2_dclk ), - .track ( fd2_track ), - .sector ( fd2_sector ), - .sector_hdr ( fd2_sector_hdr ), - .sector_data ( fd2_sector_data ), - .ready ( fd2_ready ), - .index ( fd2_index ) + // physical parameters + .sector_len ( ), + .spt ( ), + .sector_gap_len ( ), + .sector_base ( SECTOR_BASE ), + .hd ( ), + + // status signals generated by floppy + .dclk_en ( fd2_dclk ), + .track ( fd2_track ), + .sector ( fd2_sector ), + .sector_hdr ( fd2_sector_hdr ), + .sector_data ( fd2_sector_data ), + .ready ( fd2_ready ), + .index ( fd2_index ) ); // ------------------------------------------------------------------------- @@ -236,75 +309,85 @@ floppy #(.SYS_CLK(CLK)) floppy2 ( wire fd3_index; wire fd3_ready; wire [6:0] fd3_track; -wire [3:0] fd3_sector; +wire [4:0] fd3_sector; wire fd3_sector_hdr; wire fd3_sector_data; wire fd3_dclk; floppy #(.SYS_CLK(CLK)) floppy3 ( - .clk ( clkcpu ), + .clk ( clkcpu ), - // control signals into floppy - .select (!floppy_drive[3] ), - .motor_on ( motor_on ), - .step_in ( step_in ), - .step_out ( step_out ), + // control signals into floppy + .select (!floppy_drive[3] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), - // status signals generated by floppy - .dclk_en ( fd3_dclk ), - .track ( fd3_track ), - .sector ( fd3_sector ), - .sector_hdr ( fd3_sector_hdr ), - .sector_data ( fd3_sector_data ), - .ready ( fd3_ready ), - .index ( fd3_index ) + // physical parameters + .sector_len ( ), + .spt ( ), + .sector_gap_len ( ), + .sector_base ( SECTOR_BASE ), + .hd ( ), + + // status signals generated by floppy + .dclk_en ( fd3_dclk ), + .track ( fd3_track ), + .sector ( fd3_sector ), + .sector_hdr ( fd3_sector_hdr ), + .sector_data ( fd3_sector_data ), + .ready ( fd3_ready ), + .index ( fd3_index ) ); // ------------------------------------------------------------------------- // ----------------------------- floppy demux ------------------------------ // ------------------------------------------------------------------------- -wire fd_index = (!floppy_drive[0])?fd0_index: - (!floppy_drive[1])?fd1_index: - (!floppy_drive[2])?fd2_index: - (!floppy_drive[3])?fd3_index: - 1'b0; +wire fd_index = (!floppy_drive[0])?fd0_index: + (!floppy_drive[1])?fd1_index: + (!floppy_drive[2])?fd2_index: + (!floppy_drive[3])?fd3_index: + 1'b0; -wire fd_ready = (!floppy_drive[0])?fd0_ready: - (!floppy_drive[1])?fd1_ready: - (!floppy_drive[2])?fd2_ready: - (!floppy_drive[3])?fd3_ready: - 1'b0; +wire fd_ready = (!floppy_drive[0])?fd0_ready: + (!floppy_drive[1])?fd1_ready: + (!floppy_drive[2])?fd2_ready: + (!floppy_drive[3])?fd3_ready: + 1'b0; -wire [6:0] fd_track = (!floppy_drive[0])?fd0_track: - (!floppy_drive[1])?fd1_track: - (!floppy_drive[2])?fd2_track: - (!floppy_drive[3])?fd3_track: - 7'd0; +wire [6:0] fd_track = (!floppy_drive[0])?fd0_track: + (!floppy_drive[1])?fd1_track: + (!floppy_drive[2])?fd2_track: + (!floppy_drive[3])?fd3_track: + 7'd0; -wire [3:0] fd_sector = (!floppy_drive[0])?fd0_sector: - (!floppy_drive[1])?fd1_sector: - (!floppy_drive[2])?fd2_sector: - (!floppy_drive[3])?fd3_sector: - 4'd0; +wire [4:0] fd_sector = (!floppy_drive[0])?fd0_sector: + (!floppy_drive[1])?fd1_sector: + (!floppy_drive[2])?fd2_sector: + (!floppy_drive[3])?fd3_sector: + 4'd0; -wire fd_sector_hdr = (!floppy_drive[0])?fd0_sector_hdr: - (!floppy_drive[1])?fd1_sector_hdr: - (!floppy_drive[2])?fd2_sector_hdr: - (!floppy_drive[3])?fd3_sector_hdr: - 1'b0; +wire fd_sector_hdr = (!floppy_drive[0])?fd0_sector_hdr: + (!floppy_drive[1])?fd1_sector_hdr: + (!floppy_drive[2])?fd2_sector_hdr: + (!floppy_drive[3])?fd3_sector_hdr: + 1'b0; -wire fd_sector_data = (!floppy_drive[0])?fd0_sector_data: - (!floppy_drive[1])?fd1_sector_data: - (!floppy_drive[2])?fd2_sector_data: - (!floppy_drive[3])?fd3_sector_data: - 1'b0; +wire fd_sector_data = (!floppy_drive[0])?fd0_sector_data: + (!floppy_drive[1])?fd1_sector_data: + (!floppy_drive[2])?fd2_sector_data: + (!floppy_drive[3])?fd3_sector_data: + 1'b0; -wire fd_dclk_en = (!floppy_drive[0])?fd0_dclk: - (!floppy_drive[1])?fd1_dclk: - (!floppy_drive[2])?fd2_dclk: - (!floppy_drive[3])?fd3_dclk: - 1'b0; +wire fd_dclk_en = (!floppy_drive[0])?fd0_dclk: + (!floppy_drive[1])?fd1_dclk: + (!floppy_drive[2])?fd2_dclk: + (!floppy_drive[3])?fd3_dclk: + 1'b0; + +wire fd_doubleside = (!floppy_drive[0])?doubleside[0]:doubleside[1]; +wire [4:0] fd_spt = (!floppy_drive[0])?spt[0]:spt[1]; wire fd_track0 = (fd_track == 0); @@ -313,18 +396,18 @@ wire fd_track0 = (fd_track == 0); // ------------------------------------------------------------------------- // --------------------------- Motor handling ------------------------------ - + // if motor is off and type 1 command with "spin up sequnce" bit 3 set // is received then the command is executed after the motor has // reached full speed for 5 rotations (800ms spin-up time + 5*200ms = // 1.8sec) If the floppy is idle for 10 rotations (2 sec) then the // motor is switched off again localparam MOTOR_IDLE_COUNTER = 4'd10; -reg [3:0] motor_timeout_index; +reg [3:0] motor_timeout_index /* verilator public */; reg indexD; -reg busy; +reg busy /* verilator public */; reg step_in, step_out; -reg [3:0] motor_spin_up_sequence; +reg [3:0] motor_spin_up_sequence /* verilator public */; // consider spin up done either if the motor is not supposed to spin at all or // if it's supposed to run and has left the spin up sequence @@ -332,178 +415,313 @@ wire motor_spin_up_done = (!motor_on) || (motor_on && (motor_spin_up_sequence == // ---------------------------- step handling ------------------------------ -localparam STEP_PULSE_LEN = 1; -localparam STEP_PULSE_CLKS = (STEP_PULSE_LEN * CLK_EN)/1000; +localparam STEP_PULSE_LEN = 16'd1; +localparam STEP_PULSE_CLKS = STEP_PULSE_LEN * CLK_EN; reg [15:0] step_pulse_cnt; // the step rate is only valid for command type I wire [15:0] step_rate_clk = - (cmd[1:0]==2'b00)?(2*CLK_EN/1000-1): // 2ms - (cmd[1:0]==2'b01)?(3*CLK_EN/1000-1): // 3ms - (cmd[1:0]==2'b10)?(5*CLK_EN/1000-1): // 5ms - (6*CLK_EN/1000-1); // 6ms - + (cmd[1:0]==2'b00)?(16'd6*CLK_EN-1'd1): // 6ms + (cmd[1:0]==2'b01)?(16'd12*CLK_EN-1'd1): // 12ms + (cmd[1:0]==2'b10)?(16'd2*CLK_EN-1'd1): // 2ms + (16'd3*CLK_EN-1'd1); // 3ms + reg [15:0] step_rate_cnt; +reg [23:0] delay_cnt; // flag indicating that a "step" is in progress wire step_busy = (step_rate_cnt != 0); +wire delaying = (delay_cnt != 0); + reg [7:0] step_to; +reg RNF; +reg sector_inc_strobe; +reg track_inc_strobe; +reg track_dec_strobe; +reg track_clear_strobe; always @(posedge clkcpu) begin - reg data_transfer_can_start; + reg data_transfer_can_start; + reg [1:0] seek_state; + reg notready_wait; + reg sector_not_found; + reg irq_at_index; - if(!floppy_reset) begin - motor_on <= 1'b0; - busy <= 1'b0; - step_in <= 1'b0; - step_out <= 1'b0; - irq_set <= 1'b0; - sd_card_read <= 0; - sd_card_write <= 0; - data_transfer_start <= 1'b0; - data_transfer_can_start <= 0; - end else if (clk8m_en) begin - sd_card_read <= 0; - sd_card_write <= 0; - irq_set <= 1'b0; - data_transfer_start <= 1'b0; + sector_inc_strobe <= 1'b0; + track_inc_strobe <= 1'b0; + track_dec_strobe <= 1'b0; + track_clear_strobe <= 1'b0; + irq_set <= 1'b0; - // disable step signal after 1 msec - if(step_pulse_cnt != 0) - step_pulse_cnt <= step_pulse_cnt - 16'd1; - else begin - step_in <= 1'b0; - step_out <= 1'b0; - end - - // step rate timer - if(step_rate_cnt != 0) - step_rate_cnt <= step_rate_cnt - 16'd1; + if(!floppy_reset) begin + motor_on <= 1'b0; + busy <= 1'b0; + step_in <= 1'b0; + step_out <= 1'b0; + sd_card_read <= 0; + sd_card_write <= 0; + data_transfer_start <= 1'b0; + data_transfer_can_start <= 0; + seek_state <= 0; + notready_wait <= 1'b0; + sector_not_found <= 1'b0; + irq_at_index <= 1'b0; + end else if (clk8m_en) begin + sd_card_read <= 0; + sd_card_write <= 0; + data_transfer_start <= 1'b0; - // just received a new command - if(cmd_rx) begin - busy <= 1'b1; + // disable step signal after 1 msec + if(step_pulse_cnt != 0) + step_pulse_cnt <= step_pulse_cnt - 16'd1; + else begin + step_in <= 1'b0; + step_out <= 1'b0; + end - // type I commands can wait for the disk to spin up - if(cmd_type_1 && cmd[3] && !motor_on) begin - motor_on <= 1'b1; - motor_spin_up_sequence <= 6; // wait for 6 full rotations - end + // step rate timer + if(step_rate_cnt != 0) + step_rate_cnt <= step_rate_cnt - 16'd1; - // handle "forced interrupt" - if(cmd[7:4] == 4'b1101) begin - busy <= 1'b0; - if(cmd[3]) irq_set <= 1'b1; - end - end + // delay timer + if(delay_cnt != 0) + delay_cnt <= delay_cnt - 1'd1; - // execute command if motor is not supposed to be running or - // wait for motor spinup to finish - if(busy && motor_spin_up_done && !step_busy) begin + // just received a new command + if(cmd_rx) begin + busy <= 1'b1; + notready_wait <= 1'b0; + sector_not_found <= 1'b0; - // ------------------------ TYPE I ------------------------- - if(cmd_type_1) begin - // all type 1 commands are step commands and step_to has been set - if(fd_track == step_to) begin - busy <= 1'b0; // done if reached track 0 - motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; - irq_set <= 1'b1; // emit irq when command done - end else begin - // do the step - if(step_to < fd_track) step_in <= 1'b1; - else step_out <= 1'b1; - - // update track register -// if( (!cmd[6] && !cmd[5]) || // restore/seek -// ((cmd[6] || cmd[5]) && cmd[4])) begin // step(in/out) with update flag -// if(step_to < fd_track) track <= track - 1'd0; -// else track <= track + 1'd0; -// end - - step_pulse_cnt <= STEP_PULSE_CLKS-1; - step_rate_cnt <= step_rate_clk; - end - end // if (cmd_type_1) + if(cmd_type_1 || cmd_type_2 || cmd_type_3) begin + motor_on <= 1'b1; + // 'h' flag '0' -> wait for spin up + if (!motor_on && !cmd[3]) motor_spin_up_sequence <= 6; // wait for 6 full rotations + end - // ------------------------ TYPE II ------------------------- - if(cmd_type_2) begin - if(!floppy_present) begin - // no image selected -> send irq immediately - busy <= 1'b0; - motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; - irq_set <= 1'b1; // emit irq when command done - end else begin - // read sector - if(cmd[7:5] == 3'b100) begin - if (fifo_cpuptr == 0) sd_card_read <= 1; - // we are busy until the right sector header passes under - // the head and the sd-card controller indicates the sector - // is in the fifo - if(sd_card_done) data_transfer_can_start <= 1; - if(fd_ready && fd_sector_hdr && (fd_sector == sector) && data_transfer_can_start) begin - data_transfer_can_start <= 0; - data_transfer_start <= 1; - end + // handle "forced interrupt" + if(cmd_type_4) begin + busy <= 1'b0; + if(cmd[3]) irq_set <= 1'b1; + if(cmd[3:2] == 2'b01) irq_at_index <= 1'b1; + end + end - if(data_transfer_done) begin + // execute command if motor is not supposed to be running or + // wait for motor spinup to finish + if(busy && motor_spin_up_done && !step_busy && !delaying) begin + + // ------------------------ TYPE I ------------------------- + if(cmd_type_1) begin + // evaluate command + case (seek_state) + 0: begin + // restore + if(cmd[7:4] == 4'b0000) begin + if (fd_track0) begin + track_clear_strobe <= 1'b1; + seek_state <= 2; + end else begin + step_dir <= 1'b1; + seek_state <= 1; + end + end + + // seek + if(cmd[7:4] == 4'b0001) begin + if (track == step_to) seek_state <= 2; + else begin + step_dir <= (step_to < track); + seek_state <= 1; + end + end + + // step + if(cmd[7:5] == 3'b001) seek_state <= 1; + + // step-in + if(cmd[7:5] == 3'b010) begin + step_dir <= 1'b0; + seek_state <= 1; + end + + // step-out + if(cmd[7:5] == 3'b011) begin + step_dir <= 1'b1; + seek_state <= 1; + end + end + + // do the step + 1: begin + if (step_dir) + step_in <= 1'b1; + else + step_out <= 1'b1; + + // update the track register if seek/restore or the update flag set + if( (!cmd[6] && !cmd[5]) || ((cmd[6] || cmd[5]) && cmd[4])) + if (step_dir) + track_dec_strobe <= 1'b1; + else + track_inc_strobe <= 1'b1; + + step_pulse_cnt <= STEP_PULSE_CLKS - 1'd1; + step_rate_cnt <= step_rate_clk; + + seek_state <= (!cmd[6] && !cmd[5]) ? 0 : 2; // loop for seek/restore + end + + // verify + 2: begin + if (cmd[2]) begin + delay_cnt <= 16'd3*CLK_EN; // TODO: implement verify, now just delay one more step + RNF <= 1'b0; + end + seek_state <= 3; + end + + // finish + 3: begin busy <= 1'b0; motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; irq_set <= 1'b1; // emit irq when command done - end - end + seek_state <= 0; + end + endcase + end // if (cmd_type_1) - // write sector - if(cmd[7:5] == 3'b101) begin - if (fifo_cpuptr == 0) data_transfer_start <= 1'b1; - if (data_transfer_done) sd_card_write <= 1; - if (sd_card_done) begin + // ------------------------ TYPE II ------------------------- + if(cmd_type_2) begin + if(!floppy_present) begin + // no image selected -> send irq after 6 ms + if (!notready_wait) begin + delay_cnt <= 16'd6*CLK_EN; + notready_wait <= 1'b1; + end else begin + RNF <= 1'b1; + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + end + end else if (sector_not_found) begin busy <= 1'b0; motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; irq_set <= 1'b1; // emit irq when command done + RNF <= 1'b1; + end else if (cmd[2] && !notready_wait) begin + // e flag: 15 ms settling delay + delay_cnt <= 16'd15*CLK_EN; + notready_wait <= 1'b1; + // read sector + end else begin + if(cmd[7:5] == 3'b100) begin + if ((sector - SECTOR_BASE) >= fd_spt) begin + // wait 5 rotations (1 sec) before setting RNF + sector_not_found <= 1'b1; + delay_cnt <= 24'd1000 * CLK_EN; + end else begin + if (fifo_cpuptr == 0) sd_card_read <= 1; + // we are busy until the right sector header passes under + // the head and the sd-card controller indicates the sector + // is in the fifo + if(sd_card_done) data_transfer_can_start <= 1; + if(fd_ready && fd_sector_hdr && (fd_sector == sector) && data_transfer_can_start) begin + data_transfer_can_start <= 0; + data_transfer_start <= 1; + end + + if(data_transfer_done) begin + if (cmd[4]) sector_inc_strobe <= 1'b1; // multiple sector transfer + else begin + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + RNF <= 1'b0; + end + end + end + end + + // write sector + if(cmd[7:5] == 3'b101) begin + if ((sector - SECTOR_BASE) >= fd_spt) begin + // wait 5 rotations (1 sec) before setting RNF + sector_not_found <= 1'b1; + delay_cnt <= 24'd1000 * CLK_EN; + end else begin + if (fifo_cpuptr == 0) data_transfer_start <= 1'b1; + if (data_transfer_done) sd_card_write <= 1; + if (sd_card_done) begin + if (cmd[4]) sector_inc_strobe <= 1'b1; // multiple sector transfer + else begin + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + RNF <= 1'b0; + end + end + end + end end end + + // ------------------------ TYPE III ------------------------- + if(cmd_type_3) begin + if(!floppy_present) begin + // no image selected -> send irq immediately + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + end else begin + // read track TODO: fake + if(cmd[7:4] == 4'b1110) begin + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + end + + // write track TODO: fake + if(cmd[7:4] == 4'b1111) begin + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + end + + // read address + if(cmd[7:4] == 4'b1100) begin + // we are busy until the next setor header passes under the head + if(fd_ready && fd_sector_hdr) + data_transfer_start <= 1'b1; + + if(data_transfer_done) begin + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; + irq_set <= 1'b1; // emit irq when command done + end + end + end + end + end + + // stop motor if there was no command for 10 index pulses + indexD <= fd_index; + if(indexD && !fd_index) begin + irq_at_index <= 1'b0; + if (irq_at_index) irq_set <= 1'b1; + + // led motor timeout run once fdc is not busy anymore + if(!busy) begin + if(motor_timeout_index != 0) + motor_timeout_index <= motor_timeout_index - 4'd1; + else + motor_on <= 1'b0; + end + + if(motor_spin_up_sequence != 0) + motor_spin_up_sequence <= motor_spin_up_sequence - 4'd1; end end - - // ------------------------ TYPE III ------------------------- - if(cmd_type_3) begin - if(!floppy_present) begin - // no image selected -> send irq immediately - busy <= 1'b0; - motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; - irq_set <= 1'b1; // emit irq when command done - end else begin - // read address - if(cmd[7:4] == 4'b1100) begin - // we are busy until the next setor header passes under the head - if(fd_ready && fd_sector_hdr) - data_transfer_start <= 1'b1; - - if(data_transfer_done) begin - busy <= 1'b0; - motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1; - irq_set <= 1'b1; // emit irq when command done - end - end - end - end - end - - // stop motor if there was no command for 10 index pulses - indexD <= fd_index; - if(indexD && !fd_index) begin - // led motor timeout run once fdc is not busy anymore - if(!busy) begin - if(motor_timeout_index != 0) - motor_timeout_index <= motor_timeout_index - 4'd1; - else - motor_on <= 1'b0; - end - - if(motor_spin_up_sequence != 0) - motor_spin_up_sequence <= motor_spin_up_sequence - 4'd1; - end - end end // floppy delivers data at a floppy generated rate (usually 250kbit/s), so the start and stop @@ -513,17 +731,25 @@ reg data_transfer_done; // ==================================== FIFO ================================== -// 1 kB buffer used to receive a sector as fast as possible from from the io +// 0.5/1 kB buffer used to receive a sector as fast as possible from from the io // controller. The internal transfer afterwards then runs at 250000 Bit/s -reg [10:0] fifo_cpuptr; -reg s_odd; //odd sector +reg [SECTOR_SIZE_CODE + 7:0] fifo_cpuptr; wire [7:0] fifo_q; +reg s_odd; //odd sector +reg [SECTOR_SIZE_CODE + 6:0] fifo_sdptr; -fdc1772_dpram fifo +always @(*) begin + if (SECTOR_SIZE_CODE == 3) + fifo_sdptr = { s_odd, sd_buff_addr }; + else + fifo_sdptr = sd_buff_addr; +end + +fdc1772_dpram #(8, SECTOR_SIZE_CODE + 7) fifo ( .clock(clkcpu), - .address_a({s_odd, sd_buff_addr}), + .address_a(fifo_sdptr), .data_a(sd_dout), .wren_a(sd_dout_strobe & sd_ack), .q_a(sd_din), @@ -558,7 +784,7 @@ always @(posedge clkcpu) begin case (sd_state) SD_IDLE: begin - s_odd <= 0; + s_odd <= 1'b0; if (~sd_card_readD & sd_card_read) begin sd_rd <= ~{ floppy_drive[1], floppy_drive[0] }; sd_state <= SD_READ; @@ -570,28 +796,24 @@ always @(posedge clkcpu) begin end SD_READ: - begin - if (sd_ackD & ~sd_ack) begin - if (s_odd) begin - sd_state <= SD_IDLE; - sd_card_done <= 1; // to be on the safe side now, can be issued earlier - end else begin - s_odd <= 1; - sd_rd <= ~{ floppy_drive[1], floppy_drive[0] }; - end + if (sd_ackD & ~sd_ack) begin + if (s_odd || SECTOR_SIZE_CODE != 3) begin + sd_state <= SD_IDLE; + sd_card_done <= 1; // to be on the safe side now, can be issued earlier + end else begin + s_odd <= 1; + sd_rd <= ~{ floppy_drive[1], floppy_drive[0] }; end end SD_WRITE: - begin - if (sd_ackD & ~sd_ack) begin - if (s_odd) begin - sd_state <= SD_IDLE; - sd_card_done <= 1; - end else begin - s_odd <= 1; - sd_wr <= ~{ floppy_drive[1], floppy_drive[0] }; - end + if (sd_ackD & ~sd_ack) begin + if (s_odd || SECTOR_SIZE_CODE != 3) begin + sd_state <= SD_IDLE; + sd_card_done <= 1; + end else begin + s_odd <= 1; + sd_wr <= ~{ floppy_drive[1], floppy_drive[0] }; end end @@ -602,85 +824,91 @@ end // -------------------- CPU data read/write ----------------------- always @(posedge clkcpu) begin - reg data_transfer_startD; - reg [10:0] data_transfer_cnt; + reg data_transfer_startD; + reg [10:0] data_transfer_cnt; - // reset fifo read pointer on reception of a new command - if(cmd_rx) - fifo_cpuptr <= 11'd0; + // reset fifo read pointer on reception of a new command or + // when multi-sector transfer increments the sector number + if(cmd_rx || sector_inc_strobe) begin + data_transfer_cnt <= 11'd0; + fifo_cpuptr <= 10'd0; + end - drq_set <= 1'b0; - if (clk8m_en) data_transfer_done <= 0; - data_transfer_startD <= data_transfer_start; - // received request to read data - if(~data_transfer_startD & data_transfer_start) begin + drq_set <= 1'b0; + if (clk8m_en) data_transfer_done <= 0; + data_transfer_startD <= data_transfer_start; + // received request to read data + if(~data_transfer_startD & data_transfer_start) begin - // read_address command has 6 data bytes - if(cmd[7:4] == 4'b1100) + // read_address command has 6 data bytes + if(cmd[7:4] == 4'b1100) data_transfer_cnt <= 11'd6+11'd1; - // read/write sector has 1024 data bytes - if(cmd[7:6] == 2'b10) - data_transfer_cnt <= 11'd1024+11'd1; - end + // read/write sector has SECTOR_SIZE data bytes + if(cmd[7:6] == 2'b10) + data_transfer_cnt <= SECTOR_SIZE + 1'd1; + end - // write sector data arrived from CPU - if(cmd[7:5] == 3'b101 && data_in_strobe) fifo_cpuptr <= fifo_cpuptr + 1'd1; + // write sector data arrived from CPU + if(cmd[7:5] == 3'b101 && data_in_strobe) fifo_cpuptr <= fifo_cpuptr + 1'd1; - if(fd_dclk_en) begin - if(data_transfer_cnt != 0) begin + if(fd_dclk_en) begin + if(data_transfer_cnt != 0) begin if(data_transfer_cnt != 1) begin + data_lost <= 1'b0; + if (drq) data_lost <= 1'b1; drq_set <= 1'b1; - + // read_address if(cmd[7:4] == 4'b1100) begin case(data_transfer_cnt) 7: data_out <= fd_track; 6: data_out <= { 7'b0000000, floppy_side }; 5: data_out <= fd_sector; - 4: data_out <= 8'd3; // TODO: sec size 0=128, 1=256, 2=512, 3=1024 + 4: data_out <= SECTOR_SIZE_CODE; // TODO: sec size 0=128, 1=256, 2=512, 3=1024 3: data_out <= 8'ha5; 2: data_out <= 8'h5a; endcase // case (data_read_cnt) end - + // read sector if(cmd[7:5] == 3'b100) begin - if(fifo_cpuptr != 11'd1024) begin + if(fifo_cpuptr != SECTOR_SIZE) begin data_out <= fifo_q; - fifo_cpuptr <= fifo_cpuptr + 11'd1; + fifo_cpuptr <= fifo_cpuptr + 1'd1; end end end - + // count down and stop after last byte data_transfer_cnt <= data_transfer_cnt - 11'd1; if(data_transfer_cnt == 1) data_transfer_done <= 1'b1; end - end + end end - + // the status byte wire [7:0] status = { motor_on, floppy_write_protected, // wrprot cmd_type_1?motor_spin_up_done:1'b0, // data mark - !floppy_present, // record not found + !floppy_present | RNF, // record not found 1'b0, // crc error - cmd_type_1?(fd_track == 0):1'b0, - cmd_type_1?~fd_index:floppy_drq, + cmd_type_1?fd_track0:data_lost, + cmd_type_1?~fd_index:drq, busy } /* synthesis keep */; -reg [7:0] track; +reg [7:0] track /* verilator public */; reg [7:0] sector; reg [7:0] data_in; reg [7:0] data_out; reg step_dir; -reg motor_on; +reg motor_on /* verilator public */ = 1'b0; +reg data_lost; // ---------------------------- command register ----------------------- -reg [7:0] cmd; +reg [7:0] cmd /* verilator public */; wire cmd_type_1 = (cmd[7] == 1'b0); wire cmd_type_2 = (cmd[7:6] == 2'b10); wire cmd_type_3 = (cmd[7:5] == 3'b111) || (cmd[7:4] == 4'b1100); @@ -693,153 +921,144 @@ localparam FDC_REG_DATA = 3; // CPU register read always @(*) begin - wb_dat_o = 8'h00; + cpu_dout = 8'h00; - if(wb_stb && wb_cyc && !wb_we) begin - case(wb_adr[3:2]) - FDC_REG_CMDSTATUS: wb_dat_o = status; - FDC_REG_TRACK: wb_dat_o = track; - FDC_REG_SECTOR: wb_dat_o = sector; - FDC_REG_DATA: wb_dat_o = data_out; - endcase - end + if(cpu_sel && cpu_rw) begin + case(cpu_addr) + FDC_REG_CMDSTATUS: cpu_dout = status; + FDC_REG_TRACK: cpu_dout = track; + FDC_REG_SECTOR: cpu_dout = sector; + FDC_REG_DATA: cpu_dout = data_out; + endcase + end end // cpu register write -reg cmd_rx; +reg cmd_rx /* verilator public */; reg cmd_rx_i; -reg last_stb; reg data_in_strobe; always @(posedge clkcpu) begin - if(!floppy_reset) begin - // clear internal registers - cmd <= 8'h00; - track <= 8'h00; - sector <= 8'h00; + if(!floppy_reset) begin + // clear internal registers + cmd <= 8'h00; + track <= 8'h00; + sector <= 8'h00; - // reset state machines and counters - cmd_rx_i <= 1'b0; - cmd_rx <= 1'b0; - last_stb <= 1'b0; - data_in_strobe <= 0; - end else begin - data_in_strobe <= 0; - last_stb <= wb_stb; + // reset state machines and counters + cmd_rx_i <= 1'b0; + cmd_rx <= 1'b0; + data_in_strobe <= 0; + end else begin + data_in_strobe <= 0; // cmd_rx is delayed to make sure all signals (the cmd!) are stable when // cmd_rx is evaluated cmd_rx <= cmd_rx_i; - // command reception is ack'd by fdc going busy - if(busy) - cmd_rx_i <= 1'b0; + // command reception is ack'd by fdc going busy + if((!cmd_type_4 && busy) || (clk8m_en && cmd_type_4 && !busy)) cmd_rx_i <= 1'b0; - // only react if stb just raised - if(!last_stb && wb_stb && wb_cyc && wb_we) begin - if(wb_adr[3:2] == FDC_REG_CMDSTATUS) begin // command register - cmd <= wb_dat_i; + // only react if stb just raised + if(cpu_we) begin + if(cpu_addr == FDC_REG_CMDSTATUS) begin // command register + cmd <= cpu_din; cmd_rx_i <= 1'b1; - - // ------------- TYPE I commands ------------- - if(wb_dat_i[7:4] == 4'b0000) begin // RESTORE + // ------------- TYPE I commands ------------- + if(cpu_din[7:4] == 4'b0000) begin // RESTORE step_to <= 8'd0; - track <= 8'd0; - end - - if(wb_dat_i[7:4] == 4'b0001) begin // SEEK + track <= 8'hff; + end + + if(cpu_din[7:4] == 4'b0001) begin // SEEK step_to <= data_in; - track <= data_in; - end - - if(wb_dat_i[7:5] == 3'b001) begin // STEP - step_to <= (step_dir == 1)?(track + 8'd1):(track - 8'd1); - if(wb_dat_i[4]) track <= (step_dir == 1)?(track + 8'd1):(track - 8'd1); - end - - if(wb_dat_i[7:5] == 3'b010) begin // STEP-IN - step_to <= track + 8'd1; - step_dir <= 1'b1; - if(wb_dat_i[4]) track <= track + 8'd1; - end - - if(wb_dat_i[7:5] == 3'b011) begin // STEP-OUT - step_to <= track - 8'd1; - step_dir <= 1'b0; - if(wb_dat_i[4]) track <= track - 8'd1; - end - - // ------------- TYPE II commands ------------- - if(wb_dat_i[7:5] == 3'b100) begin // read sector - end + end - if(wb_dat_i[7:5] == 3'b101) begin // write sector - end - - // ------------- TYPE III commands ------------ - if(wb_dat_i[7:4] == 4'b1100) begin // read address + if(cpu_din[7:5] == 3'b001) begin // STEP end - - if(wb_dat_i[7:4] == 4'b1110) begin // read track - end - - if(wb_dat_i[7:4] == 4'b1111) begin // write track - end - - // ------------- TYPE IV commands ------------- - if(wb_dat_i[7:4] == 4'b1101) begin // force intrerupt - end - end - - if(wb_adr[3:2] == FDC_REG_TRACK) // track register - track <= wb_dat_i; - - if(wb_adr[3:2] == FDC_REG_SECTOR) // sector register - sector <= wb_dat_i; - if(wb_adr[3:2] == FDC_REG_DATA) begin // data register - data_in_strobe <= 1; - data_in <= wb_dat_i; - end - end - end + if(cpu_din[7:5] == 3'b010) begin // STEP-IN + end + + if(cpu_din[7:5] == 3'b011) begin // STEP-OUT + end + + // ------------- TYPE II commands ------------- + if(cpu_din[7:5] == 3'b100) begin // read sector + end + + if(cpu_din[7:5] == 3'b101) begin // write sector + end + + // ------------- TYPE III commands ------------ + if(cpu_din[7:4] == 4'b1100) begin // read address + end + + if(cpu_din[7:4] == 4'b1110) begin // read track + end + + if(cpu_din[7:4] == 4'b1111) begin // write track + end + + // ------------- TYPE IV commands ------------- + if(cpu_din[7:4] == 4'b1101) begin // force intrerupt + end + end + + if(cpu_addr == FDC_REG_TRACK) // track register + track <= cpu_din; + + if(cpu_addr == FDC_REG_SECTOR) // sector register + sector <= cpu_din; + + if(cpu_addr == FDC_REG_DATA) begin // data register + data_in_strobe <= 1; + data_in <= cpu_din; + end + end + + if (sector_inc_strobe) sector <= sector + 1'd1; + if (track_inc_strobe) track <= track + 1'd1; + if (track_dec_strobe) track <= track - 1'd1; + if (track_clear_strobe) track <= 8'd0; + end end endmodule -module fdc1772_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=10) +module fdc1772_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=9) ( - input clock, + input clock, - input [ADDRWIDTH-1:0] address_a, - input [DATAWIDTH-1:0] data_a, - input wren_a, - output reg [DATAWIDTH-1:0] q_a, + input [ADDRWIDTH-1:0] address_a, + input [DATAWIDTH-1:0] data_a, + input wren_a, + output reg [DATAWIDTH-1:0] q_a, - input [ADDRWIDTH-1:0] address_b, - input [DATAWIDTH-1:0] data_b, - input wren_b, - output reg [DATAWIDTH-1:0] q_b + input [ADDRWIDTH-1:0] address_b, + input [DATAWIDTH-1:0] data_b, + input wren_b, + output reg [DATAWIDTH-1:0] q_b ); reg [DATAWIDTH-1:0] ram[0:(1< SPIN_UP_CLKS) begin - if(rate < RATE) - rate <= rate + 32'd1; - spin_up_counter <= spin_up_counter - (SPIN_UP_CLKS - RATE); - end - end else begin - // spinning down - if(spin_up_counter > SPIN_DOWN_CLKS) begin - if(rate > 0) - rate <= rate - 32'd1; - spin_up_counter <= spin_up_counter - (SPIN_DOWN_CLKS - RATE); - end - end // else: !if(motor_on) - end // else: !if(motor_onD != motor_on) + if(motor_on_sel) begin + // spinning up + if(spin_up_counter > SPIN_UP_CLKS) begin + if(rate < (hd ? RATEHD : RATEDD)) + rate <= rate + 32'd1; + spin_up_counter <= spin_up_counter - (SPIN_UP_CLKS - (hd ? RATEHD : RATEDD)); + end + end else begin + // spinning down + if(spin_up_counter > SPIN_DOWN_CLKS) begin + if(rate > 0) + rate <= rate - 32'd1; + spin_up_counter <= spin_up_counter - (SPIN_DOWN_CLKS - (hd ? RATEHD : RATEDD)); + end + end // else: !if(motor_on) + end // else: !if(motor_onD != motor_on) end - + // Generate a data clock from the system clock. This depends on motor // speed and reaches the full rate when the disk rotates at 300RPM. No // valid data can be read until the disk has reached it's full speed. @@ -259,13 +267,13 @@ reg data_clk; reg data_clk_en; reg [31:0] clk_cnt; always @(posedge clk) begin - data_clk_en <= 0; - if(clk_cnt + rate > SYS_CLK/2) begin - clk_cnt <= clk_cnt - (SYS_CLK/2 - rate); - data_clk <= !data_clk; - if (~data_clk) data_clk_en <= 1; - end else - clk_cnt <= clk_cnt + rate; -end - + data_clk_en <= 0; + if(clk_cnt + rate > SYS_CLK/2) begin + clk_cnt <= clk_cnt - (SYS_CLK/2 - rate); + data_clk <= !data_clk; + if (~data_clk) data_clk_en <= 1; + end else + clk_cnt <= clk_cnt + rate; +end + endmodule From 7122e993fc996ebc15ac39b1b451c91d7197255b Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 18 Oct 2019 19:54:49 +0200 Subject: [PATCH 2/4] Archie: reduce clock to 40MHz --- cores/archie/fpga/mist/clockgen.v | 38 +++++++++++++++---------------- cores/archie/rtl/archimedes_top.v | 2 +- cores/archie/rtl/ioc.v | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/cores/archie/fpga/mist/clockgen.v b/cores/archie/fpga/mist/clockgen.v index 9bf424b..4e80651 100644 --- a/cores/archie/fpga/mist/clockgen.v +++ b/cores/archie/fpga/mist/clockgen.v @@ -14,7 +14,7 @@ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! // -// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition // ************************************************************ @@ -111,17 +111,17 @@ module clockgen ( .vcounderrange ()); defparam altpll_component.bandwidth_type = "AUTO", - altpll_component.clk0_divide_by = 9, + altpll_component.clk0_divide_by = 27, altpll_component.clk0_duty_cycle = 50, - altpll_component.clk0_multiply_by = 14, + altpll_component.clk0_multiply_by = 40, altpll_component.clk0_phase_shift = "0", - altpll_component.clk1_divide_by = 3, + altpll_component.clk1_divide_by = 9, altpll_component.clk1_duty_cycle = 50, - altpll_component.clk1_multiply_by = 14, + altpll_component.clk1_multiply_by = 40, altpll_component.clk1_phase_shift = "0", - altpll_component.clk3_divide_by = 3, + altpll_component.clk3_divide_by = 9, altpll_component.clk3_duty_cycle = 50, - altpll_component.clk3_multiply_by = 14, + altpll_component.clk3_multiply_by = 40, altpll_component.clk3_phase_shift = "-1845", altpll_component.compensate_clock = "CLK0", altpll_component.inclk0_input_frequency = 37037, @@ -202,9 +202,9 @@ endmodule // Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" // Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" // Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000" -// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "42.000000" -// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "126.000000" -// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "126.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "40.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "120.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "120.000000" // Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" // Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" // Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" @@ -235,9 +235,9 @@ endmodule // Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1" // Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "1" // Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" -// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "42.00000000" -// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "126.00000000" -// Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "126.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "40.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "120.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "120.00000000" // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "1" @@ -290,17 +290,17 @@ endmodule // Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all // Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" -// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "27" // Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" -// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "14" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "40" // Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" -// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "3" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9" // Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" -// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "14" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "40" // Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" -// Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "3" +// Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "9" // Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50" -// Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "14" +// Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "40" // Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "-1845" // Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" // Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" diff --git a/cores/archie/rtl/archimedes_top.v b/cores/archie/rtl/archimedes_top.v index d16a653..f2173ff 100644 --- a/cores/archie/rtl/archimedes_top.v +++ b/cores/archie/rtl/archimedes_top.v @@ -319,7 +319,7 @@ wire floppy_reset; wire fdc_sel = cpu_stb & cpu_cyc & floppy_en; -fdc1772 #(.CLK(42000000)) FDC1772 ( +fdc1772 #(.CLK(40000000)) FDC1772 ( .clkcpu ( CLKCPU_I ), .clk8m_en ( ioc_clk8m_en ), diff --git a/cores/archie/rtl/ioc.v b/cores/archie/rtl/ioc.v index 33d01c0..322b597 100644 --- a/cores/archie/rtl/ioc.v +++ b/cores/archie/rtl/ioc.v @@ -249,9 +249,9 @@ always @(posedge clkcpu) begin end - // increment the clock counter. 42 MHz clkcpu assumed. + // increment the clock counter. 40 MHz clkcpu assumed. clken_counter <= clken_counter + 1'd1; - if (clken_counter == 20) clken_counter <= 0; + if (clken_counter == 19) clken_counter <= 0; if (write_request & ctrl_selected) begin From 375c423a852207898e6d95662bc42c5e9ad08ae8 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 18 Oct 2019 20:56:39 +0200 Subject: [PATCH 3/4] Archie: 128bit SDRAM interface (by Sorgelig) --- cores/archie/rtl/archimedes_top.v | 7 +- cores/archie/rtl/memc.v | 104 ++++--- cores/archie/rtl/sdram/sdram_defines.v | 47 --- cores/archie/rtl/sdram/sdram_top.v | 377 ++++++++++--------------- 4 files changed, 220 insertions(+), 315 deletions(-) delete mode 100644 cores/archie/rtl/sdram/sdram_defines.v diff --git a/cores/archie/rtl/archimedes_top.v b/cores/archie/rtl/archimedes_top.v index f2173ff..5ec2b59 100644 --- a/cores/archie/rtl/archimedes_top.v +++ b/cores/archie/rtl/archimedes_top.v @@ -155,6 +155,7 @@ wire sirq_n; wire ram_cs; wire vid_we; wire snd_ack, snd_req; +wire [31:0] cpu_dout; memc MEMC( @@ -170,7 +171,8 @@ memc MEMC( .cpu_we ( cpu_we ), .cpu_sel ( cpu_sel ), .cpu_ack ( cpu_ack ), - .cpu_err ( cpu_err ), + .cpu_err ( cpu_err ), + .cpu_dout ( cpu_dout ), // memory interface .mem_addr_o ( MEM_ADDR_O ), @@ -180,6 +182,7 @@ memc MEMC( .mem_sel_o ( MEM_SEL_O ), .mem_we_o ( MEM_WE_O ), .mem_cti_o ( MEM_CTI_O ), + .mem_dat_i ( MEM_DAT_I ), // vidc interface .hsync ( HSYNC ), @@ -390,7 +393,7 @@ assign cpu_dat_i = floppy_en ? {24'd0, floppy_dat_o} : latches_en ? {24'd0, latches_dat_o} : podules_en ? {16'd0, pod_dat_o} : ioc_cs & ~ioc_sext ? {24'd0, ioc_dat_o} : - ram_cs ? MEM_DAT_I : + ram_cs ? cpu_dout : 32'hFFFF_FFFF; assign I2C_CLOCK = ioc_cout[1]; diff --git a/cores/archie/rtl/memc.v b/cores/archie/rtl/memc.v index ecb6180..93f8634 100644 --- a/cores/archie/rtl/memc.v +++ b/cores/archie/rtl/memc.v @@ -37,6 +37,7 @@ module memc( input cpu_cyc, output cpu_err, output cpu_ack, + output [31:0] cpu_dout, input [25:0] cpu_address, input [3:0] cpu_sel, @@ -47,6 +48,7 @@ module memc( output mem_cyc_o, output mem_we_o, output [3:0] mem_sel_o, + input [31:0] mem_dat_i, input mem_ack_i, output [2:0] mem_cti_o, // burst / normal @@ -127,13 +129,8 @@ localparam REG_SendN = 3'b101; localparam REG_Sptr = 3'b110; localparam REG_Ctrl = 3'b111; -wire table_valid; -wire err; -wire memw; -wire logcs; -wire vidc_cs; -wire mem_virtual; wire[25:0] phys_address; +wire table_valid; memc_translator PAGETABLES( @@ -174,9 +171,21 @@ initial begin end -always @(posedge clkcpu) begin +reg [31:0] cache_data[4]; +reg cache_valid; +reg [23:4] cache_addr; +reg cache_ack; - if (rst_i == 1'b1) begin +assign cpu_dout = cache_data[caddr[3:2]]; + +always @(posedge clkcpu) begin + reg cache_rcv, cache_test; + reg [1:0] cache_cnt; + reg [1:0] cache_wraddr; + + cache_ack <= 0; + + if (rst_i) begin vid_init <= INITIAL_SCREEN_BASE; cur_init <= INITIAL_CURSOR_BASE; @@ -191,15 +200,33 @@ always @(posedge clkcpu) begin memc_control[11] <= 1'b0; // disable sound dma on reset. dma_request_r <= 1'b0; + cache_rcv <= 0; + cache_valid <= 0; + cache_test <= 0; end else begin + if(cache_rcv & mem_ack_i) begin + cache_data[cache_wraddr] <= mem_dat_i; + cache_wraddr <= cache_wraddr + 1'd1; + cache_cnt <= cache_cnt + 1'd1; + if(cache_cnt == 2) cache_ack <= 1; + if(&cache_cnt) begin + cache_rcv <= 0; + cache_valid <= 1; + end + end dma_request_r <= dma_request; // cpu cycle. if (cpu_cyc & cpu_stb) begin - + cache_test <= 1; + if(cache_valid & (cache_addr == caddr[23:4]) & ~cpu_mem_we) begin + // cache hit + if(~cache_test) cache_ack <= 1; + end + else begin // logic to ensure that the rom overlay gets deactivated. if (cpu_address[25:24] == 2'b11) begin @@ -209,16 +236,18 @@ always @(posedge clkcpu) begin // ensure no video cycle is active or about to start. if (~dma_request_r & ~dma_in_progress) begin - cpu_load <= 1'b1; - + if(~cpu_load) begin + if(cpu_mem_we) begin + if(cache_addr == caddr[23:4]) cache_valid <= 0; + end + else begin + {cache_addr,cache_wraddr} <= caddr[23:2]; + cache_valid <= 0; + cache_rcv <= 1; + cache_cnt <= 0; + end end - - // prevent the cpu hogging the bus. - if (cpu_load & dma_request_r & (cpu_ack | cpu_err)) begin - - cpu_load <= 1'b0; - end if (memw) begin @@ -233,11 +262,9 @@ always @(posedge clkcpu) begin REG_Cinit: cur_init <= {cpu_address[16:2], 4'b0000}; REG_Sstart: begin - $display("Sstart: %x", {cpu_address[16:2], 4'b0000}); snd_next_valid <= 1'b1; snd_start <= {cpu_address[16:2], 4'b0000}; - end REG_SendN: begin @@ -269,11 +296,13 @@ always @(posedge clkcpu) begin endcase end + end end else begin - cpu_load <= 1'b0; - + cpu_load <= 0; + cache_rcv <= 0; + cache_test <= 0; end // video dma stuff. @@ -338,12 +367,12 @@ always @(posedge clkcpu) begin if ((vidak & vid_load) == 1'b1) begin // advance the pointer to the next location. - vid_address <= vid_address + 4'd4; + vid_address <= vid_address + 19'd4; end else if ((vidak & cur_load) == 1'b1) begin // advance the cursor pointer to the next location. - cur_address <= cur_address + 4'd4; + cur_address <= cur_address + 19'd4; end @@ -364,7 +393,7 @@ always @(posedge clkcpu) begin if ((sndak & snd_load) == 1'b1) begin // advance the pointer to the next location. - snd_sptr <= snd_sptr + 4'd4; + snd_sptr <= snd_sptr + 19'd4; end end else begin @@ -394,35 +423,38 @@ wire [21:2] ram_page = memc_control[3:2] == 2'b00 ? {3'd0, cpu_address[18:2]}: assign mem_addr_o = vid_load ? {5'd0, vid_address[18:2]} : cur_load ? {5'd0, cur_address[18:2]} : snd_load ? {5'd0, snd_sptr[18:2]} : - phycs ? {2'd0, ram_page} : // use physical memory + caddr; + +wire [23:2] caddr = phycs ? {2'd0, ram_page} : // use physical memory romcs ? {3'b010, cpu_address[20:2]} : // use 2mb and up for rom space. table_valid & logcs ? phys_address[23:2] : 22'd0; // use logical memory. - // does this cpu cycle need to go to external RAM/ROM? -assign cpu_ram_cycle = cpu_cyc & cpu_stb & (table_valid | phycs | romcs); +//assign cpu_ram_cycle = cpu_cyc & cpu_stb & (table_valid | phycs | romcs); -assign mem_cyc_o = cpu_load ? cpu_cyc : dma_in_progress; +assign mem_cyc_o = cpu_load ? cpu_cyc & ~err : dma_in_progress; assign mem_stb_o = cpu_load ? cpu_stb : dma_in_progress; assign mem_sel_o = cpu_load ? cpu_sel : 4'b1111; -assign mem_we_o = cpu_load ? cpu_we & (phycs & spvmd | table_valid & logcs) & ~romcs : 1'b0; -assign mem_cti_o = cpu_load ? 3'b000 : 3'b010; +assign mem_we_o = cpu_load ? cpu_mem_we : 1'b0; +assign mem_cti_o = 3'b010; + +wire cpu_mem_we = cpu_we & ((phycs & spvmd) | (table_valid & logcs)) & ~romcs; assign address_valid = (logcs & table_valid) | rom_low_cs| ioc_cs | memw | tablew | vidc_cs | (phycs & ~cpu_we) | (phycs & spvmd & cpu_we) | romcs; -assign err = ~address_valid; +wire err = ~address_valid; -assign cpu_ack = cpu_load ? mem_ack_i & ~err : 1'b0; +assign cpu_ack = (mem_we_o ? mem_ack_i : cache_ack) & ~err; assign cpu_err = cpu_load ? mem_ack_i & err : 1'b0; assign tablew = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:23] == 3'b111) & (cpu_address[12] == 0) & (cpu_address[7] == 0); // &3800000+ -assign memw = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:21] == 5'b11011); // &3600000 +wire memw = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:21] == 5'b11011); // &3600000 assign vidw = cpu_load & cpu_cyc & cpu_we & vidc_cs; // &3400000 // bus chip selects -assign logcs = cpu_address[25] == 1'b0; // 0000000-&1FFFFFF +wire logcs = cpu_address[25] == 1'b0; // 0000000-&1FFFFFF assign phycs = cpu_address[25:24] == 2'b10; //&2000000 - &2FFFFFF assign ioc_cs = spvmd & (cpu_address[25:22] == 4'b1100); //&3000000 - &33FFFFF -assign vidc_cs = spvmd & (cpu_address[25:21] == 5'b11010); // &3400000 - &35FFFFF (WE & SPVMD) +wire vidc_cs = spvmd & (cpu_address[25:21] == 5'b11010); // &3400000 - &35FFFFF (WE & SPVMD) assign rom_low_cs = (cpu_address[25:22] == 4'b1101); assign romcs = ((cpu_address[25:23] == 3'b111) | (cpu_address[25:19] == 7'h00) & rom_overlay); @@ -433,6 +465,6 @@ assign sndak = cpu_load ? 1'b0 : sound_dma_ip & mem_ack_i; assign sirq_n = snd_next_valid; assign ram_cs = table_valid | phycs | romcs; -assign mem_virtual = table_valid & ~cpu_address[25]; +//wire mem_virtual= table_valid & ~cpu_address[25]; endmodule diff --git a/cores/archie/rtl/sdram/sdram_defines.v b/cores/archie/rtl/sdram/sdram_defines.v deleted file mode 100644 index 58bfc2e..0000000 --- a/cores/archie/rtl/sdram/sdram_defines.v +++ /dev/null @@ -1,47 +0,0 @@ -/* sdram_defines.v - - Copyright (c) 2013-2014, Stephen J. Leary - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Stephen J. Leary nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL STEPHEN J. LEARY BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 3 cycles@128MHz -localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8, 111 = continuous. -localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved -localparam CAS_LATENCY = 3'd3; // 2/3 allowed -localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed -localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write -localparam WRITE_BURST = 1'b0; // 0= write burst enabled, 1=only single access write -localparam RFC_DELAY = 4'd7; // tRFC=66ns -> 9 cycles@128MHz - -// all possible commands -localparam CMD_INHIBIT = 4'b1111; -localparam CMD_NOP = 4'b0111; -localparam CMD_ACTIVE = 4'b0011; -localparam CMD_READ = 4'b0101; -localparam CMD_WRITE = 4'b0100; -localparam CMD_BURST_TERMINATE = 4'b0110; -localparam CMD_PRECHARGE = 4'b0010; -localparam CMD_AUTO_REFRESH = 4'b0001; -localparam CMD_LOAD_MODE = 4'b0000; \ No newline at end of file diff --git a/cores/archie/rtl/sdram/sdram_top.v b/cores/archie/rtl/sdram/sdram_top.v index d8c55a5..5660962 100644 --- a/cores/archie/rtl/sdram/sdram_top.v +++ b/cores/archie/rtl/sdram/sdram_top.v @@ -1,5 +1,4 @@ -/* sdram_top.v - +/* Copyright (c) 2013-2014, Stephen J. Leary All rights reserved. @@ -26,105 +25,115 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -module sdram_top ( - +module sdram_top +( // interface to the MT48LC16M16 chip - input sd_clk, // sdram is accessed at 128MHz - input sd_rst, // reset the sdram controller. - output sd_cke, // clock enable. - inout reg[15:0]sd_dq, // 16 bit bidirectional data bus - output reg[12:0]sd_addr, // 13 bit multiplexed address bus - output reg[1:0] sd_dqm = 2'b00, // two byte masks - output reg[1:0] sd_ba = 2'b00, // two banks - output sd_cs_n, // a single chip select - output sd_we_n, // write enable - output sd_ras_n, // row address select - output sd_cas_n, // columns address select - output reg sd_ready = 0, // sd ready. + input sd_clk, // sdram is accessed at 128MHz + input sd_rst, // reset the sdram controller. + output sd_cke, // clock enable. + inout reg[15:0] sd_dq, // 16 bit bidirectional data bus + output reg[12:0] sd_addr, // 13 bit multiplexed address bus + output [1:0] sd_dqm, // two byte masks + output reg [1:0] sd_ba, // two banks + output sd_cs_n, // a single chip select + output sd_we_n, // write enable + output sd_ras_n, // row address select + output sd_cas_n, // columns address select + output reg sd_ready, // sd ready. // cpu/chipset interface - input wb_clk, // 32MHz chipset clock to which sdram state machine is synchonized - input [31:0] wb_dat_i, // data input from chipset/cpu - output reg[31:0]wb_dat_o = 0, // data output to chipset/cpu - output reg wb_ack = 0, - input [23:0] wb_adr, // lower 2 bits are ignored. - input [3:0] wb_sel, // - input [2:0] wb_cti, // cycle type. - input wb_stb, // - input wb_cyc, // cpu/chipset requests cycle - input wb_we // cpu/chipset requests write + input wb_clk, // 32MHz chipset clock to which sdram state machine is synchonized + input [31:0] wb_dat_i, // data input from chipset/cpu + output reg[31:0] wb_dat_o = 0, // data output to chipset/cpu + output reg wb_ack = 0, + input [23:0] wb_adr, // lower 2 bits are ignored. + input [3:0] wb_sel, // + input [2:0] wb_cti, // cycle type. + input wb_stb, // + input wb_cyc, // cpu/chipset requests cycle + input wb_we // cpu/chipset requests write ); -`include "sdram_defines.v" +localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 3 cycles@128MHz +localparam BURST_LENGTH = 3'b011; // 000=1, 001=2, 010=4, 011=8, 111 = continuous. +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd3; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write +localparam WRITE_BURST = 1'b0; // 0= write burst enabled, 1=only single access write +localparam RFC_DELAY = 4'd7; // tRFC=66ns -> 9 cycles@128MHz + +// all possible commands +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; -reg [3:0] t; -reg [4:0] reset; +reg [3:0] t; +reg [4:0] reset; +reg[31:0] sd_dat[4]; // data output to chipset/cpu -reg[31:0] sd_dat = 0; // data output to chipset/cpu -reg[31:0] sd_dat_nxt = 0; // data output to chipset/cpu - -reg sd_stb = 1'b0; // copy of the wishbone bus signal. -reg sd_we = 1'b0; // copy of the wishbone bus signal. -reg sd_cyc = 1'b0; // copy of the wishbone bus signal. -reg sd_burst = 1'b0; - -reg [3:0] sd_cycle= 4'd0; reg sd_done = 1'b0; - -reg [3:0] sd_cmd = 4'd0; // current command sent to sd ram +reg [3:0] sd_cmd; // current command sent to sd ram reg [9:0] sd_refresh = 10'd0; reg sd_auto_refresh = 1'b0; -wire sd_req = wb_stb & wb_cyc & ~wb_ack; -reg [11:0] sd_active_row[3:0]; -reg [3:0] sd_bank_active; -wire [1:0] sd_bank = wb_adr[22:21]; -wire [11:0] sd_row = wb_adr[20:9]; +wire sd_req = wb_stb & wb_cyc & ~wb_ack; +wire sd_reading = wb_stb & wb_cyc & ~wb_we; +wire sd_writing = wb_stb & wb_cyc & wb_we; initial begin - t = 4'd0; - reset = 5'h1f; - sd_addr = 13'd0; - sd_cmd = CMD_INHIBIT; + t = 4'd0; + reset = 5'h1f; + sd_cmd = CMD_NOP; + sd_ready= 0; end -localparam CYCLE_PRECHARGE = 4'd0; -localparam CYCLE_RAS_START = 4'd3; +localparam CYCLE_IDLE = 4'd0; +localparam CYCLE_RAS_START = CYCLE_IDLE; localparam CYCLE_RFSH_START = CYCLE_RAS_START; -localparam CYCLE_CAS0 = CYCLE_RAS_START + RASCAS_DELAY; -localparam CYCLE_CAS1 = CYCLE_CAS0 + 4'd1; -localparam CYCLE_CAS2 = CYCLE_CAS1 + 4'd1; -localparam CYCLE_CAS3 = CYCLE_CAS2 + 4'd1; -localparam CYCLE_READ0 = CYCLE_CAS0 + CAS_LATENCY + 4'd1; -localparam CYCLE_READ1 = CYCLE_READ0+ 1'd1; -localparam CYCLE_READ2 = CYCLE_READ1+ 1'd1; -localparam CYCLE_READ3 = CYCLE_READ2+ 1'd1; -localparam CYCLE_END = CYCLE_READ3+ 1'd1; -localparam CYCLE_RFSH_END = CYCLE_RFSH_START + RFC_DELAY; +localparam CYCLE_CAS0 = CYCLE_RAS_START + RASCAS_DELAY; +localparam CYCLE_CAS1 = CYCLE_CAS0 + 4'd1; +localparam CYCLE_CAS2 = CYCLE_CAS1 + 4'd1; +localparam CYCLE_CAS3 = CYCLE_CAS2 + 4'd1; +localparam CYCLE_READ0 = CYCLE_CAS0 + CAS_LATENCY + 4'd1; +localparam CYCLE_READ1 = CYCLE_READ0+ 1'd1; +localparam CYCLE_READ2 = CYCLE_READ1+ 1'd1; +localparam CYCLE_READ3 = CYCLE_READ2+ 1'd1; +localparam CYCLE_READ4 = CYCLE_READ3+ 1'd1; +localparam CYCLE_READ5 = CYCLE_READ4+ 1'd1; +localparam CYCLE_READ6 = CYCLE_READ5+ 1'd1; +localparam CYCLE_READ7 = CYCLE_READ6+ 1'd1; +localparam CYCLE_RFSH_END = CYCLE_RFSH_START + RFC_DELAY; -localparam RAM_CLK = 128000000; -localparam REFRESH_PERIOD = (RAM_CLK / (16 * 8192)) - CYCLE_END; - -`ifdef VERILATOR -reg [15:0] sd_q; -assign sd_dq = (sd_writing && (sd_cycle == CYCLE_CAS1 || sd_cycle == CYCLE_CAS2)) ? sd_q : 16'bZZZZZZZZZZZZZZZZ; -`endif +localparam RAM_CLK = 120000000; +localparam REFRESH_PERIOD = (RAM_CLK / (16 * 8192)); always @(posedge sd_clk) begin + reg sd_reqD, sd_reqD2; + reg sd_newreq; + reg [3:0] sd_cycle = CYCLE_IDLE; + reg [2:0] word; -`ifndef VERILATOR - sd_dq <= 16'bZZZZZZZZZZZZZZZZ; -`endif + sd_dq <= 16'bZZZZZZZZZZZZZZZZ; sd_cmd <= CMD_NOP; + sd_reqD <= sd_req; + if(~sd_reqD & sd_req) sd_newreq <= 1; + if (sd_rst) begin - t <= 4'd0; + t <= 0; reset <= 5'h1f; - sd_addr <= 13'd0; - sd_ready <= 0; + sd_addr <= 0; + sd_ready <= 0; + sd_ba <= 0; end else begin if (!sd_ready) begin t <= t + 4'd1; @@ -138,7 +147,7 @@ always @(posedge sd_clk) begin if(reset == 13) begin $display("precharging all banks"); sd_cmd <= CMD_PRECHARGE; - sd_addr[10] <= 1'b1; // precharge all banks + sd_addr[10] <= 1'b1; // precharge all banks end if(reset == 2) begin @@ -152,222 +161,130 @@ always @(posedge sd_clk) begin sd_addr <= MODE; end - if(reset == 0) sd_ready <= 1; + if(!reset) sd_ready <= 1; + word <= 0; end end else begin - - // bring the wishbone bus signal into the ram clock domain. - - sd_we <= wb_we; - if (sd_req) begin - sd_stb <= wb_stb; - sd_cyc <= wb_cyc; - end sd_refresh <= sd_refresh + 9'd1; + if(word) begin + word <= word + 1'd1; + sd_dat[word[2:1]][{word[0],4'b0000} +:16] <= sd_dq; + end // this is the auto refresh code. // it kicks in so that 8192 auto refreshes are // issued in a 64ms period. Other bus operations // are stalled during this period. - if ((sd_refresh > REFRESH_PERIOD) && (sd_cycle == 4'd0)) begin - sd_auto_refresh <= 1'b1; + if ((sd_refresh > REFRESH_PERIOD) && !sd_cycle) begin + sd_auto_refresh<= 1'b1; sd_refresh <= 10'd0; - sd_cmd <= CMD_PRECHARGE; - sd_addr[10] <= 1; - sd_bank_active <= 0; + sd_cmd <= CMD_AUTO_REFRESH; end else if (sd_auto_refresh) begin // while the cycle is active count. sd_cycle <= sd_cycle + 3'd1; - case (sd_cycle) - CYCLE_RFSH_START: begin - sd_cmd <= CMD_AUTO_REFRESH; - end - CYCLE_RFSH_END: begin + if(sd_cycle == CYCLE_RFSH_END) begin // reset the count. - sd_auto_refresh <= 1'b0; - sd_cycle <= 4'd0; + sd_auto_refresh <= 0; + sd_cycle <= CYCLE_IDLE; end - endcase + end + else begin + // count while the cycle is active + if(sd_cycle != CYCLE_IDLE) sd_cycle <= sd_cycle + 3'd1; - end else if (sd_cyc | (sd_cycle != 0) | (sd_cycle == 0 && sd_req)) begin - - // while the cycle is active count. - sd_cycle <= sd_cycle + 3'd1; - case (sd_cycle) - CYCLE_PRECHARGE: begin - if (~sd_bank_active[sd_bank]) - sd_cycle <= CYCLE_RAS_START; - else if (sd_active_row[sd_bank] == sd_row) - sd_cycle <= CYCLE_CAS0 - 1'd1; // FIXME: Why doesn't work without -1? - else begin - sd_cmd <= CMD_PRECHARGE; - sd_addr[10] <= 0; - sd_ba <= sd_bank; - end - end - - CYCLE_RAS_START: begin - sd_cmd <= CMD_ACTIVE; - sd_addr <= { 1'b0, sd_row }; - sd_ba <= sd_bank; - sd_active_row[sd_bank] <= sd_row; - sd_bank_active[sd_bank] <= 1; - - if(sd_reading) begin - sd_dqm <= 2'b00; - end else begin - sd_dqm <= 2'b11; + case(sd_cycle) + CYCLE_IDLE: begin + if(sd_newreq) begin + sd_cmd <= CMD_ACTIVE; + sd_addr <= wb_adr[21:10]; + sd_ba <= wb_adr[23:22]; + sd_cycle <= sd_cycle + 3'd1; end end // this is the first CAS cycle CYCLE_CAS0: begin // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. - sd_addr <= { 4'b0000, wb_adr[23], wb_adr[8:2], 1'b0 }; // no auto precharge - sd_dqm <= ~wb_sel[1:0]; - sd_ba <= sd_bank; + sd_addr <= { 4'b0000, wb_adr[9:1] }; // no auto precharge if (sd_reading) begin - sd_cmd <= CMD_READ; + sd_cmd <= CMD_READ; + sd_addr[10] <= 1; // auto precharge end else if (sd_writing) begin - sd_cmd <= CMD_WRITE; -`ifdef VERILATOR - sd_q <= wb_dat_i[15:0]; -`else - sd_dq <= wb_dat_i[15:0]; -`endif + sd_cmd <= CMD_WRITE; + sd_addr[12:11] <= ~wb_sel[1:0]; + sd_dq <= wb_dat_i[15:0]; end end CYCLE_CAS1: begin // now we access the second part of the 32 bit location. - sd_addr <= { 4'b0000, wb_adr[23], wb_adr[8:2], 1'b1 }; // no auto precharge - sd_dqm <= ~wb_sel[3:2]; - if (sd_reading) begin - sd_cmd <= CMD_READ; - if (burst_mode & can_burst) begin - sd_burst <= 1'b1; - end - end else if (sd_writing) begin - sd_cmd <= CMD_WRITE; - sd_done <= ~sd_done; -`ifdef VERILATOR - sd_q <= wb_dat_i[31:16]; -`else - sd_dq <= wb_dat_i[31:16]; -`endif - end - end - - CYCLE_CAS2: begin - if (sd_burst) begin - // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. - sd_addr <= { 4'b0000, wb_adr[23], wb_adr[8:3], 2'b10 }; // no auto precharge - sd_dqm <= ~wb_sel[1:0]; - if (sd_reading) begin - sd_cmd <= CMD_READ; - end - end - end - - CYCLE_CAS3: begin - if (sd_burst) begin - // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. - sd_addr <= { 4'b0000, wb_adr[23], wb_adr[8:3], 2'b11 }; // no auto precharge - sd_dqm <= ~wb_sel[3:2]; - if (sd_reading) begin - sd_cmd <= CMD_READ; - end + if (sd_writing) begin + sd_addr[10] <= 1; // auto precharge + sd_addr[0] <= 1; + sd_cmd <= CMD_WRITE; + sd_addr[12:11] <= ~wb_sel[3:2]; + sd_done <= ~sd_done; + sd_newreq <= 0; + sd_dq <= wb_dat_i[31:16]; end end CYCLE_READ0: begin if (sd_reading) begin - sd_dat[15:0] <= sd_dq; + sd_dat[0][15:0]<= sd_dq; + word <= 1; end else begin - if (sd_writing) sd_cycle <= CYCLE_END; - end + if (sd_writing) sd_cycle <= CYCLE_IDLE; + end end - CYCLE_READ1: begin - if (sd_reading) begin - sd_dat[31:16] <= sd_dq; - sd_done <= ~sd_done; - end + sd_done <= ~sd_done; + sd_newreq <= 0; end - CYCLE_READ2: begin - if (sd_reading) begin - sd_dat_nxt[15:0] <= sd_dq; - end - end - - CYCLE_READ3: begin - if (sd_reading) begin - sd_dat_nxt[31:16] <= sd_dq; - end - end - - CYCLE_END: begin - sd_burst <= 1'b0; - sd_cyc <= 1'b0; - sd_stb <= 1'b0; + CYCLE_READ5: begin + sd_cycle <= CYCLE_IDLE; end endcase - end else begin - sd_cycle <= 4'd0; - sd_burst <= 1'b0; end end end end -reg wb_burst; - always @(posedge wb_clk) begin reg sd_doneD; + reg [1:0] word; sd_doneD <= sd_done; - wb_ack <= (sd_done ^ sd_doneD) & ~wb_ack; - + wb_ack <= 0; + + if(word) word <= word + 1'd1; + if (wb_stb & wb_cyc) begin - if ((sd_done ^ sd_doneD) & ~wb_ack) begin - - wb_dat_o <= sd_dat; - wb_burst <= burst_mode; - + wb_dat_o <= sd_dat[0]; + word <= ~wb_cti[2] & (wb_cti[1] ^ wb_cti[0]); // burst constant/incremental + wb_ack <= 1; + end + + if (word) begin + wb_dat_o <= sd_dat[word]; + wb_ack <= 1; end - - if (wb_ack & wb_burst) begin - - wb_ack <= 1'b1; - wb_burst <= 1'b0; - wb_dat_o <= sd_dat_nxt; - - end - - - end else begin - - wb_burst <= 1'b0; - end - - + else begin + word <= 0; + end end -wire burst_mode = wb_cti == 3'b010; -wire can_burst = wb_adr[2] === 1'b0; -wire sd_reading = sd_stb & sd_cyc & ~sd_we; -wire sd_writing = sd_stb & sd_cyc & sd_we; - // drive control signals according to current command assign sd_cs_n = sd_cmd[3]; assign sd_ras_n = sd_cmd[2]; assign sd_cas_n = sd_cmd[1]; assign sd_we_n = sd_cmd[0]; -assign sd_cke = 1'b1; +assign sd_cke = 1'b1; +assign sd_dqm = sd_addr[12:11]; endmodule From 4a1a470d0e7fb222dc3ce0d2ee843b9fe8650503 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 18 Oct 2019 21:55:09 +0200 Subject: [PATCH 4/4] Archie: change video timing events to simple equality checks Display event registers less likely to glitch --- cores/archie/rtl/vidc_timing.v | 99 +++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/cores/archie/rtl/vidc_timing.v b/cores/archie/rtl/vidc_timing.v index 0a418b9..102334d 100644 --- a/cores/archie/rtl/vidc_timing.v +++ b/cores/archie/rtl/vidc_timing.v @@ -37,15 +37,15 @@ module vidc_timing( input cevid, input rst, - output reg o_vsync, - output reg o_hsync, + output o_vsync, + output o_hsync, - output reg o_cursor, - output reg o_enabled, - output reg o_border, - output reg o_flyback /* synthesis keep */ + output o_cursor, + output o_enabled, + output o_border, + output o_flyback ); - + reg [9:0] hcount; reg [9:0] vcount; @@ -91,12 +91,6 @@ reg [9:0] vidc_vcer; // vertical cursor end initial begin - o_flyback = 1'b0; - o_cursor = 1'b0; - - hcount = 10'h3FF; - vcount = 10'h3FF; - vidc_vcr = 10'd0; // vertical cycle register vidc_vswr = 10'd0; // vertical sync width vidc_vbsr = 10'd0; // vertical border start @@ -153,42 +147,71 @@ always @(posedge clkcpu) begin end -wire vborder = (vcount >= vidc_vbsr) & (vcount < vidc_vber); -wire hborder = (hcount >= vidc_hbsr) & (hcount < vidc_hber); -wire vdisplay = (vcount >= vidc_vdsr) & (vcount < vidc_vder); -wire hdisplay = (hcount >= vidc_hdsr) & (hcount < vidc_hder); -wire vflyback = (vcount >= vidc_vber); +reg vborder; +reg hborder; +reg vdisplay; +reg hdisplay; +reg vflyback; +reg vcursor; +reg hcursor; +reg hsync; +reg vsync; + +assign o_cursor = hcursor & vcursor; +assign o_flyback = vflyback; +assign o_enabled = hdisplay & vdisplay; +assign o_border = hborder & vborder; +assign o_vsync = ~vsync; +assign o_hsync = ~hsync; -wire vcursor = (vcount >= vidc_vcsr) & (vcount < vidc_vcer); -wire hcursor = ({1'b0, hcount} >= vidc_hcsr); - always @(posedge clkvid) begin + if (rst) begin + hcount <= 0; + vcount <= 0; + hborder <= 0; + vborder <= 0; + hsync <= 0; + vsync <= 0; + vflyback <= 0; + hdisplay <= 0; + vdisplay <= 0; + hcursor <= 0; + vcursor <= 0; + end else if (cevid) begin - o_flyback <= vflyback; - o_enabled <= hdisplay && vdisplay; - o_border <= hborder && vborder; - o_vsync <= ~((vcount <= vidc_vswr) & !rst); - o_hsync <= ~((hcount < vidc_hswr) & !rst); - - o_cursor <= hcursor & vcursor; - // video frame control - if (hcount < vidc_hcr) begin - hcount <= hcount + 9'd1; - end else begin - // horizontal refresh time. + hcount <= hcount + 1'd1; + if (hcount == vidc_hbsr) hborder <= 1; + if (hcount == vidc_hber) hborder <= 0; + if (hcount == vidc_hdsr) hdisplay <= 1; + if (hcount == vidc_hder) hdisplay <= 0; + if ({1'b0, hcount} == vidc_hcsr) hcursor <= 1; + if (hcount == vidc_hswr) hsync <= 0; + + if (hcount == vidc_hcr) begin hcount <= 0; + hcursor <= 0; + hsync <= 1; - if (vcount < vidc_vcr) begin - vcount <= vcount + 9'd1; - end else begin - // vertical refresh time + vcount <= vcount + 1'd1; + if (vcount == vidc_vbsr) vborder <= 1; + if (vcount == vidc_vber) vborder <= 0; + if (vcount == vidc_vdsr) vdisplay <= 1; + if (vcount == vidc_vder) vdisplay <= 0; + if (vcount == vidc_vber) vflyback <= 1; + if (vcount == vidc_vcsr) vcursor <= 1; + if (vcount == vidc_vcer) vcursor <= 0; + if (vcount == vidc_vswr) vsync <= 0; + + if (vcount == vidc_vcr) begin vcount <= 0; - + vflyback <= 0; + vsync <= 1; end end + end end