1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-05 23:54:41 +00:00

Merge pull request #122 from gyurco/master

Some Archie updates
This commit is contained in:
gyurco
2019-10-18 22:17:28 +02:00
committed by GitHub
10 changed files with 1167 additions and 1012 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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 ),
@@ -297,63 +300,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(40000000)) 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);
@@ -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];

File diff suppressed because it is too large Load Diff

View File

@@ -25,9 +25,15 @@ module floppy (
input step_in,
input step_out,
input [10:0] sector_len,
input sector_base, // number of first sector on track (archie 0, dos 1)
input [4:0] spt, // sectors/track
input [9:0] sector_gap_len, // gap len/sector
input hd,
output dclk_en, // data clock enable
output [6:0] track, // number of track under head
output [3:0] sector, // number of sector under head, 0 = no sector
output [4:0] sector, // number of sector under head, 0 = no sector
output sector_hdr, // valid sector header under head
output sector_data, // valid sector data under head
@@ -41,9 +47,10 @@ parameter SYS_CLK = 8000000;
assign sector_hdr = (sec_state == SECTOR_STATE_HDR);
assign sector_data = (sec_state == SECTOR_STATE_DATA);
// a standard DD floppy has a data rate of 250kBit/s and rotates at 300RPM
localparam RATE = 20'd250000;
localparam RATEDD = 20'd250000;
localparam RATEHD = 20'd500000;
localparam RPM = 10'd300;
localparam STEPBUSY = 8'd18; // 18ms after step data can be read
localparam SPINUP = 10'd500; // drive spins up in up to 800ms
@@ -53,34 +60,36 @@ localparam SECTOR_HDR_LEN = 4'd6; // GUESSED: Sector header is 6 bytes
localparam TRACKS = 8'd85; // max allowed track
// Archimedes specific values
localparam SECTOR_LEN = 11'd1024; // Default sector size is 1k on Archie ...
localparam SPT = 4'd5; // ... with 5 sectors per track
localparam SECTOR_BASE = 4'd0; // number of first sector on track (archie 0, dos 1)
//localparam SECTOR_LEN = 11'd1024 // Default sector size is 1024 on Archie
//localparam SECTOR_LEN = 11'd512; // Default sector size is 512 on ST ...
//localparam SPT = 4'd10; // ... with 5 sectors per track
//localparam SECTOR_BASE = 4'd1; // number of first sector on track (archie 0, dos 1)
// number of physical bytes per track
localparam BPT = RATE*60/(8*RPM);
localparam BPTDD = RATEDD*60/(8*RPM);
localparam BPTHD = RATEHD*60/(8*RPM);
// report disk ready if it spins at full speed and head is not moving
assign ready = select && (rate == RATE) && (step_busy == 0);
assign ready = select && (rate == (hd ? RATEHD : RATEDD)) && (step_busy == 0);
// ================================================================
// ========================= INDEX PULSE ==========================
// ================================================================
// Index pulse generation. Pulse starts with the begin of index_pulse_start
// and lasts INDEX_PULSE_CYCLES system clock cycles
localparam INDEX_PULSE_CYCLES = INDEX_PULSE_LEN * SYS_CLK / 1000;
reg [18:0] index_pulse_cnt;
always @(posedge clk) begin
if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin
index <= 1'b0;
index_pulse_cnt <= 16'd0;
end else if(index_pulse_cnt == INDEX_PULSE_CYCLES-1)
index <= 1'b1;
else
index_pulse_cnt <= index_pulse_cnt + 16'd1;
if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin
index <= 1'b0;
index_pulse_cnt <= 19'd0;
end else if(index_pulse_cnt == INDEX_PULSE_CYCLES-1)
index <= 1'b1;
else
index_pulse_cnt <= index_pulse_cnt + 1'd1;
end
// ================================================================
// ======================= track handling =========================
// ================================================================
@@ -88,91 +97,90 @@ end
localparam[19:0] STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms
assign track = current_track;
reg [6:0] current_track = 7'd0;
reg [6:0] current_track /* verilator public */ = 7'd0;
reg step_inD;
reg step_outD;
reg [19:0] step_busy;
reg [19:0] step_busy /* verilator public */;
always @(posedge clk) begin
step_inD <= step_in;
step_outD <= step_out;
step_inD <= step_in;
step_outD <= step_out;
if(step_busy != 0)
step_busy <= step_busy - 18'd1;
if(step_busy != 0)
step_busy <= step_busy - 18'd1;
if(select) begin
// rising edge of step signal starts step
if(step_in && !step_inD) begin
if(current_track != 0) current_track <= current_track - 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
if(select) begin
// rising edge of step signal starts step
if(step_in && !step_inD) begin
if(current_track != 0) current_track <= current_track - 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
if(step_out && !step_outD) begin
if(current_track != TRACKS-1) current_track <= current_track + 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
end
if(step_out && !step_outD) begin
if(current_track != TRACKS-1) current_track <= current_track + 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
end
end
// ================================================================
// ====================== sector handling =========================
// ================================================================
// track has BPT bytes
// SPT sectors are stored on the track
localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN);
//localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN);
assign sector = current_sector;
localparam SECTOR_STATE_GAP = 2'd0;
localparam SECTOR_STATE_HDR = 2'd1;
localparam SECTOR_STATE_DATA = 2'd2;
// we simulate an interleave of 1
reg [3:0] start_sector = SECTOR_BASE;
reg [4:0] start_sector = 4'd1;
reg [1:0] sec_state;
reg [9:0] sec_byte_cnt; // counting bytes within sectors
reg [3:0] current_sector = SECTOR_BASE;
reg [4:0] current_sector = 4'd1;
always @(posedge clk) begin
if (byte_clk_en) begin
if(index_pulse_start) begin
sec_byte_cnt <= SECTOR_GAP_LEN-1'd1;
sec_state <= SECTOR_STATE_GAP; // track starts with gap
current_sector <= start_sector; // track starts with sector 1
end else begin
if(sec_byte_cnt == 0) begin
case(sec_state)
SECTOR_STATE_GAP: begin
sec_state <= SECTOR_STATE_HDR;
sec_byte_cnt <= SECTOR_HDR_LEN-1'd1;
end
if(index_pulse_start) begin
sec_byte_cnt <= sector_gap_len-1'd1;
sec_state <= SECTOR_STATE_GAP; // track starts with gap
current_sector <= start_sector; // track starts with sector 1
end else begin
if(sec_byte_cnt == 0) begin
case(sec_state)
SECTOR_STATE_GAP: begin
sec_state <= SECTOR_STATE_HDR;
sec_byte_cnt <= SECTOR_HDR_LEN-1'd1;
end
SECTOR_STATE_HDR: begin
sec_state <= SECTOR_STATE_DATA;
sec_byte_cnt <= SECTOR_LEN-1'd1;
end
SECTOR_STATE_HDR: begin
sec_state <= SECTOR_STATE_DATA;
sec_byte_cnt <= sector_len-1'd1;
end
SECTOR_STATE_DATA: begin
sec_state <= SECTOR_STATE_GAP;
sec_byte_cnt <= SECTOR_GAP_LEN-1'd1;
if(current_sector == SECTOR_BASE+SPT-1)
current_sector <= SECTOR_BASE;
else
current_sector <= sector + 4'd1;
end
SECTOR_STATE_DATA: begin
sec_state <= SECTOR_STATE_GAP;
sec_byte_cnt <= sector_gap_len-1'd1;
if(current_sector == sector_base+spt-1)
current_sector <= sector_base;
else
current_sector <= sector + 1'd1;
end
default:
sec_state <= SECTOR_STATE_GAP;
default:
sec_state <= SECTOR_STATE_GAP;
endcase
end else
sec_byte_cnt <= sec_byte_cnt - 10'd1;
end
end
endcase
end else
sec_byte_cnt <= sec_byte_cnt - 10'd1;
end
end
end
// ================================================================
@@ -187,7 +195,7 @@ always @(posedge clk) begin
if (byte_clk_en) begin
index_pulse_start <= 1'b0;
if(byte_cnt == BPT-1) begin
if(byte_cnt == ((hd ? BPTHD : BPTDD)-1'd1)) begin
byte_cnt <= 0;
index_pulse_start <= 1'b1;
end else
@@ -217,41 +225,41 @@ end
localparam SPIN_UP_CLKS = SYS_CLK/1000*SPINUP;
localparam SPIN_DOWN_CLKS = SYS_CLK/1000*SPINDOWN;
reg [31:0] spin_up_counter;
// internal motor on signal that is only true if the drive is selected
wire motor_on_sel = motor_on && select;
// data rate determines rotation speed
reg [31:0] rate = 0;
reg [31:0] rate /* verilator public */ = 0;
reg motor_onD;
always @(posedge clk) begin
motor_onD <= motor_on_sel;
motor_onD <= motor_on_sel;
// reset spin_up counter whenever motor state changes
if(motor_onD != motor_on_sel)
spin_up_counter <= 32'd0;
else begin
spin_up_counter <= spin_up_counter + RATE;
// reset spin_up counter whenever motor state changes
if(motor_onD != motor_on_sel)
spin_up_counter <= 32'd0;
else begin
spin_up_counter <= spin_up_counter + (hd ? RATEHD : RATEDD);
if(motor_on_sel) begin
// spinning up
if(spin_up_counter > 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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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