mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 23:54:41 +00:00
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user