Update SDRAM controller and arbiter.

This commit is contained in:
sorgelig
2018-08-23 21:48:21 +08:00
parent dd1681896c
commit ab284a598a
8 changed files with 299 additions and 369 deletions

View File

@ -392,7 +392,7 @@ set_global_assignment -name VERILOG_FILE src/video/video_top.v
set_global_assignment -name VHDL_FILE src/keyboard.vhd set_global_assignment -name VHDL_FILE src/keyboard.vhd
set_global_assignment -name VERILOG_FILE src/kempston_mouse.v set_global_assignment -name VERILOG_FILE src/kempston_mouse.v
set_global_assignment -name VERILOG_FILE src/spi.v set_global_assignment -name VERILOG_FILE src/spi.v
set_global_assignment -name VHDL_FILE src/sdram.vhd set_global_assignment -name VERILOG_FILE src/sdram.v
set_global_assignment -name VERILOG_FILE src/clock.v set_global_assignment -name VERILOG_FILE src/clock.v
set_global_assignment -name VERILOG_FILE src/tsconf.v set_global_assignment -name VERILOG_FILE src/tsconf.v
set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv

View File

@ -391,7 +391,7 @@ set_global_assignment -name VERILOG_FILE src/video/video_top.v
set_global_assignment -name VHDL_FILE src/keyboard.vhd set_global_assignment -name VHDL_FILE src/keyboard.vhd
set_global_assignment -name VERILOG_FILE src/kempston_mouse.v set_global_assignment -name VERILOG_FILE src/kempston_mouse.v
set_global_assignment -name VERILOG_FILE src/spi.v set_global_assignment -name VERILOG_FILE src/spi.v
set_global_assignment -name VHDL_FILE src/sdram.vhd set_global_assignment -name VERILOG_FILE src/sdram.v
set_global_assignment -name VERILOG_FILE src/clock.v set_global_assignment -name VERILOG_FILE src/clock.v
set_global_assignment -name VERILOG_FILE src/tsconf.v set_global_assignment -name VERILOG_FILE src/tsconf.v
set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv

View File

@ -259,11 +259,11 @@ tsconf tsconf
.SDRAM_BA(SDRAM_BA), .SDRAM_BA(SDRAM_BA),
.SDRAM_DQML(SDRAM_DQML), .SDRAM_DQML(SDRAM_DQML),
.SDRAM_DQMH(SDRAM_DQMH), .SDRAM_DQMH(SDRAM_DQMH),
.SDRAM_WE_N(SDRAM_nWE), .SDRAM_nWE(SDRAM_nWE),
.SDRAM_CAS_N(SDRAM_nCAS), .SDRAM_nCAS(SDRAM_nCAS),
.SDRAM_RAS_N(SDRAM_nRAS), .SDRAM_nRAS(SDRAM_nRAS),
.SDRAM_CKE(SDRAM_CKE), .SDRAM_CKE(SDRAM_CKE),
.SDRAM_CS_N(SDRAM_nCS), .SDRAM_nCS(SDRAM_nCS),
.VGA_R(R), .VGA_R(R),
.VGA_G(G), .VGA_G(G),

View File

@ -49,206 +49,185 @@
// - DMA - CPU // - DMA - CPU
module arbiter( module arbiter
(
input wire clk, input clk,
input wire c0, input c0,
input wire c1, input c1,
input wire c2, input c2,
input wire c3, input c3,
// dram.v interface // dram.v interface
output wire [23:0] dram_addr, // address for dram access output [20:0] dram_addr, // address for dram access
output wire dram_req, // dram request output dram_req, // dram request
output wire dram_rnw, // Read-NotWrite output dram_rnw, // Read-NotWrite
output wire [ 1:0] dram_bsel, // byte select: bsel[1] for wrdata[15:8], bsel[0] for wrdata[7:0] output [ 1:0] dram_bsel, // byte select: bsel[1] for wrdata[15:8], bsel[0] for wrdata[7:0]
output wire [15:0] dram_wrdata, // data to be written output [15:0] dram_wrdata, // data to be written
// video // video
input wire [23:0] video_addr, // during access block, only when video_strobe==1 input [20:0] video_addr, // during access block, only when video_strobe==1
input wire go, // start video access blocks input go, // start video access blocks
input wire [ 4:0] video_bw, // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2 input [ 4:0] video_bw, // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2
// [2:0] - need cycles // [2:0] - need cycles
output wire video_pre_next, // (c1) output video_pre_next, // (c1)
output wire video_next, // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe output video_next, // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe
output wire video_strobe, // (c3) one-cycle strobe meaning that video_data is available output video_strobe, // (c3) one-cycle strobe meaning that video_data is available
output wire video_next_strobe, // (c3) one-cycle strobe meaning that video_data is available output video_next_strobe, // (c3) one-cycle strobe meaning that video_data is available
output wire next_vid, // used for TM prefetch output next_vid, // used for TM prefetch
// CPU
input wire [23:0] cpu_addr,
input wire [ 7:0] cpu_wrdata,
input wire cpu_req,
input wire cpu_rnw,
input wire cpu_wrbsel,
output reg cpu_next, // next cycle is allowed to be used by CPU
output reg cpu_strobe, // c2 strobe
output reg cpu_latch, // c2-c3 strobe
output wire curr_cpu_o, //
// DMA
input wire [23:0] dma_addr,
input wire [15:0] dma_wrdata,
input wire dma_req,
input wire dma_rnw,
output wire dma_next,
// TS // CPU
input wire [23:0] ts_addr, input [20:0] cpu_addr,
input wire ts_req, input [ 7:0] cpu_wrdata,
output wire ts_pre_next, input cpu_req,
output wire ts_next, input cpu_rnw,
input cpu_wrbsel,
output reg cpu_next, // next cycle is allowed to be used by CPU
output reg cpu_strobe, // c2 strobe
output reg cpu_latch, // c2-c3 strobe
output curr_cpu_o,
// DMA
input [20:0] dma_addr,
input [15:0] dma_wrdata,
input dma_req,
input dma_rnw,
output dma_next,
// TM // TS
input wire [23:0] tm_addr, input [20:0] ts_addr,
input wire tm_req, input ts_req,
output wire tm_next, output ts_pre_next,
output ts_next,
//-----
output wire [7:0] TST
// TM
input [20:0] tm_addr,
input tm_req,
output tm_next
); );
assign curr_cpu_o = curr_cpu; assign curr_cpu_o = curr_cpu;
assign TST[0] = curr_dma;
assign TST[1] = curr_cpu;
assign TST[2] = dram_rnw;
assign TST[7:3] = 5'b00000;
localparam CYCLES = 5; localparam CYCLES = 5;
localparam CYC_CPU = 5'b00001;
localparam CYC_VID = 5'b00010;
localparam CYC_TS = 5'b00100;
localparam CYC_TM = 5'b01000;
localparam CYC_DMA = 5'b10000;
localparam CYC_FREE = 5'b00000;
localparam CPU = 0; localparam CYC_CPU = 5'b00001;
localparam VIDEO = 1; localparam CYC_VID = 5'b00010;
localparam TS = 2; localparam CYC_TS = 5'b00100;
localparam TM = 3; localparam CYC_TM = 5'b01000;
localparam DMA = 4; localparam CYC_DMA = 5'b10000;
localparam CYC_FREE = 5'b00000;
reg [CYCLES-1:0] curr_cycle; // type of the cycle in progress
reg [CYCLES-1:0] next_cycle; // type of the next cycle
wire next_cpu = next_cycle[CPU]; localparam CPU = 0;
assign next_vid = next_cycle[VIDEO]; localparam VIDEO = 1;
// wire next_ts = next_cycle[TS]; localparam TS = 2;
// wire next_tm = next_cycle[TM]; localparam TM = 3;
wire next_dma = next_cycle[DMA]; localparam DMA = 4;
wire curr_cpu = curr_cycle[CPU]; reg [CYCLES-1:0] curr_cycle; // type of the cycle in progress
wire curr_vid = curr_cycle[VIDEO]; reg [CYCLES-1:0] next_cycle; // type of the next cycle
wire curr_ts = curr_cycle[TS];
wire curr_tm = curr_cycle[TM]; wire next_cpu = next_cycle[CPU];
wire curr_dma = curr_cycle[DMA]; assign next_vid = next_cycle[VIDEO];
wire next_ts = next_cycle[TS];
wire next_tm = next_cycle[TM];
wire next_dma = next_cycle[DMA];
wire curr_cpu = curr_cycle[CPU];
wire curr_vid = curr_cycle[VIDEO];
wire curr_ts = curr_cycle[TS];
wire curr_tm = curr_cycle[TM];
wire curr_dma = curr_cycle[DMA];
// track blk_rem counter: // track blk_rem counter:
// how many cycles left to the end of block (7..0) // how many cycles left to the end of block (7..0)
wire [2:0] blk_nrem = (video_start && go) ? {video_bw[4:3], 1'b1} : (video_start ? 3'd0 : (blk_rem - 3'd1)); wire [2:0] blk_nrem = (video_start && go) ? {video_bw[4:3], 1'b1} : (video_start ? 3'd0 : (blk_rem - 3'd1));
wire bw_full = ~|{video_bw[4] & video_bw[2], video_bw[3] & video_bw[1], video_bw[0]}; // stall when 000/00/0 wire bw_full = ~|{video_bw[4] & video_bw[2], video_bw[3] & video_bw[1], video_bw[0]}; // stall when 000/00/0
wire video_start = ~|blk_rem; wire video_start = ~|blk_rem;
wire video_only = stall || (vid_rem == blk_rem); wire video_only = stall || (vid_rem == blk_rem);
wire video_idle = ~|vid_rem; wire video_idle = ~|vid_rem;
reg [2:0] blk_rem; // remaining accesses in a block (7..0) reg [2:0] blk_rem; // remaining accesses in a block (7..0)
reg stall; reg stall;
always @(posedge clk) if (c3) always @(posedge clk) begin
begin if (c3) begin
blk_rem <= blk_nrem; blk_rem <= blk_nrem;
if (video_start) if (video_start) stall <= bw_full & go;
stall <= bw_full & go; end
end end
// track vid_rem counter // track vid_rem counter
// how many video cycles left to the end of block (7..0) // how many video cycles left to the end of block (7..0)
wire [2:0] vid_nrem = (go && video_start) ? vid_nrem_start : (next_vid ? vid_nrem_next : vid_rem); wire [2:0] vid_nrem = (go && video_start) ? vid_nrem_start : (next_vid ? vid_nrem_next : vid_rem);
wire [2:0] vid_nrem_start = (cpu_req && !dev_over_cpu) ? vidmax : (vidmax - 3'd1); wire [2:0] vid_nrem_start = (cpu_req && !dev_over_cpu) ? vidmax : (vidmax - 3'd1);
wire [2:0] vid_nrem_next = video_idle ? 3'd0 : (vid_rem - 3'd1); wire [2:0] vid_nrem_next = video_idle ? 3'd0 : (vid_rem - 3'd1);
wire [2:0] vidmax = {video_bw[2:0]}; // number of cycles for video access wire [2:0] vidmax = {video_bw[2:0]}; // number of cycles for video access
reg [2:0] vid_rem; // remaining video accesses in block reg [2:0] vid_rem; // remaining video accesses in block
always @(posedge clk) if (c3) always @(posedge clk) if (c3) vid_rem <= vid_nrem;
vid_rem <= vid_nrem;
// next cycle decision // next cycle decision
wire [CYCLES-1:0] cyc_dev = tm_req ? CYC_TM : (ts_req ? CYC_TS : CYC_DMA); wire [CYCLES-1:0] cyc_dev = tm_req ? CYC_TM : (ts_req ? CYC_TS : CYC_DMA);
wire dev_req = ts_req || tm_req || dma_req; wire dev_req = ts_req || tm_req || dma_req;
// wire dev_over_cpu = (((ts_req || tm_req) && ts_z80_lp) || (dma_req && dma_z80_lp)) && int_n; // CPU gets higher priority to acknowledge the INT // wire dev_over_cpu = (((ts_req || tm_req) && ts_z80_lp) || (dma_req && dma_z80_lp)) && int_n; // CPU gets higher priority to acknowledge the INT
wire dev_over_cpu = 0; wire dev_over_cpu = 0;
always @* always @* begin
if (video_start) // video burst start if (video_start) begin // video burst start
if (go) // video active line - 38us-ON, 26us-ON if (go) begin // video active line - 38us-ON, 26us-ON
begin cpu_next = dev_over_cpu ? 1'b0 : !bw_full;
cpu_next = dev_over_cpu ? 1'b0 : !bw_full; next_cycle = dev_over_cpu ? CYC_VID : (bw_full ? CYC_VID : (cpu_req ? CYC_CPU : CYC_VID));
next_cycle = dev_over_cpu ? CYC_VID : (bw_full ? CYC_VID : (cpu_req ? CYC_CPU : CYC_VID));
end
else // video idle
begin
cpu_next = !dev_over_cpu;
next_cycle = dev_over_cpu ? cyc_dev : (cpu_req ? CYC_CPU : (dev_req ? cyc_dev : CYC_FREE));
end
else // video burst in progress
begin
cpu_next = dev_over_cpu ? 1'b0 : !video_only;
next_cycle = video_only ? CYC_VID : (dev_over_cpu ? cyc_dev : (cpu_req ? CYC_CPU : (!video_idle ? CYC_VID : (dev_req ? cyc_dev : CYC_FREE))));
end end
else begin // video idle
cpu_next = !dev_over_cpu;
next_cycle = dev_over_cpu ? cyc_dev : (cpu_req ? CYC_CPU : (dev_req ? cyc_dev : CYC_FREE));
end
end
else begin // video burst in progress
cpu_next = dev_over_cpu ? 1'b0 : !video_only;
next_cycle = video_only ? CYC_VID : (dev_over_cpu ? cyc_dev : (cpu_req ? CYC_CPU : (!video_idle ? CYC_VID : (dev_req ? cyc_dev : CYC_FREE))));
end
end
always @(posedge clk) if (c3) curr_cycle <= next_cycle;
always @(posedge clk) if (c3)
curr_cycle <= next_cycle;
// DRAM interface // DRAM interface
assign dram_wrdata = curr_dma ? dma_wrdata : {2{cpu_wrdata[7:0]}}; // write data has to be clocked at c0 in dram.v assign dram_wrdata= curr_dma ? dma_wrdata : {cpu_wrdata,cpu_wrdata}; // write data has to be clocked at c0 in dram.v
//assign dram_wrdata = curr_dma ? 16'h0000 : {2{cpu_wrdata[7:0]}}; // write data has to be clocked at c0 in dram.v assign dram_bsel = {cpu_wrbsel | next_dma, ~cpu_wrbsel | next_dma};
assign dram_bsel[1:0] = curr_dma ? 2'b11 : {cpu_wrbsel, ~cpu_wrbsel}; assign dram_req = |next_cycle;
assign dram_addr = {24{curr_cpu}} & cpu_addr assign dram_rnw = next_cpu ? cpu_rnw : ~next_dma | dma_rnw;
| {24{curr_vid}} & video_addr assign dram_addr = {21{next_cpu}} & cpu_addr
| {24{curr_ts}} & ts_addr | {21{next_vid}} & video_addr
| {24{curr_tm}} & tm_addr | {21{next_ts }} & ts_addr
| {24{curr_dma}} & dma_addr; | {21{next_tm }} & tm_addr
//==================================================== | {21{next_dma}} & dma_addr;
assign dram_req = |next_cycle; //for c3=1, rising edge
assign dram_rnw = next_cpu ? cpu_rnw : (next_dma ? dma_rnw : 1'b1);
//assign dram_req = |curr_cycle;
//assign dram_rnw = curr_cpu ? cpu_rnw : (curr_dma ? dma_rnw : 1'b1);
reg cpu_rnw_r; reg cpu_rnw_r;
always @(posedge clk) if (c3) always @(posedge clk) if (c3) cpu_rnw_r <= cpu_rnw;
cpu_rnw_r <= cpu_rnw;
// generation of read strobes: for video and cpu // generation of read strobes: for video and cpu
always @(posedge clk) always @(posedge clk) begin
if (c1) if (c1) begin
begin cpu_strobe <= curr_cpu && cpu_rnw_r;
cpu_strobe <= curr_cpu && cpu_rnw_r; cpu_latch <= curr_cpu && cpu_rnw_r;
cpu_latch <= curr_cpu && cpu_rnw_r; end
end else if (c2) cpu_strobe <= 1'b0;
else if (c2) else if (c3) cpu_latch <= 1'b0;
cpu_strobe <= 1'b0; end
else if (c3)
cpu_latch <= 1'b0;
assign video_pre_next = curr_vid & c1;
assign video_next = curr_vid & c2;
assign video_strobe = curr_vid && c3;
assign video_next_strobe = next_vid && c3;
assign video_pre_next = curr_vid & c1; assign ts_pre_next = curr_ts & c1;
assign video_next = curr_vid & c2; assign ts_next = curr_ts & c2;
assign video_strobe = curr_vid && c3;
assign video_next_strobe = next_vid && c3;
assign ts_pre_next = curr_ts & c1; assign tm_next = curr_tm & c2;
assign ts_next = curr_ts & c2;
assign tm_next = curr_tm & c2;
assign dma_next = curr_dma & c2; assign dma_next = curr_dma & c2;
endmodule endmodule

120
src/sdram.v Normal file
View File

@ -0,0 +1,120 @@
module sdram
(
// Memory port
input clk,
input cyc,
input curr_cpu,
input [1:0] bsel, // Active HI
input [23:0] A,
input [15:0] DI,
output reg [15:0] DO,
output reg [15:0] DO_cpu,
input REQ,
input RNW,
// SDRAM Pin
inout reg [15:0] SDRAM_DQ,
output reg [12:0] SDRAM_A,
output reg [1:0] SDRAM_BA,
output reg SDRAM_DQML,
output reg SDRAM_DQMH,
output SDRAM_nCS,
output SDRAM_nCAS,
output SDRAM_nRAS,
output SDRAM_nWE,
output SDRAM_CKE
);
reg [2:0] sdr_cmd;
localparam SdrCmd_xx = 3'b111; // no operation
localparam SdrCmd_ac = 3'b011; // activate
localparam SdrCmd_rd = 3'b101; // read
localparam SdrCmd_wr = 3'b100; // write
localparam SdrCmd_pr = 3'b010; // precharge all
localparam SdrCmd_re = 3'b001; // refresh
localparam SdrCmd_ms = 3'b000; // mode regiser set
always @(posedge clk) begin
reg [4:0] state;
reg rd;
reg [8:0] col;
case (state)
// Init
'h00: begin
sdr_cmd <= SdrCmd_pr; // PRECHARGE
SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
SDRAM_A <= 0;
SDRAM_BA <= 0;
SDRAM_DQML <= 1;
SDRAM_DQMH <= 1;
state <= state + 1'd1;
end
// REFRESH
'h03, 'h0A: begin
sdr_cmd <= SdrCmd_re;
state <= state + 1'd1;
end
// LOAD MODE REGISTER
'h11: begin
sdr_cmd <= SdrCmd_ms;
SDRAM_A <= {3'b000, 1'b1, 2'b00, 3'b010, 1'b0, 3'b000};
state <= state + 1'd1;
end
// Idle
'h18: begin
rd <= 0;
if (rd) begin
DO <= SDRAM_DQ;
if (curr_cpu) DO_cpu <= SDRAM_DQ;
end
if(cyc) begin
if (REQ) begin
sdr_cmd <= SdrCmd_ac; // ACTIVE
{SDRAM_A,SDRAM_BA,col} <= A;
SDRAM_DQML <= ~(bsel[0] | RNW);
SDRAM_DQMH <= ~(bsel[1] | RNW);
rd <= RNW;
state <= state + 1'd1;
end else begin
sdr_cmd <= SdrCmd_re; // REFRESH
state <= 'h13;
end
end
end
// Single read/write - with auto precharge
'h1A: begin
SDRAM_A <= {4'b0010, col}; // A10 = 1 enable auto precharge; A9..0 = column
state <= 'h16;
if (rd) sdr_cmd <= SdrCmd_rd; // READ
else begin
sdr_cmd <= SdrCmd_wr; // WRITE
SDRAM_DQ <= DI;
end
end
// NOP
default:
begin
SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
sdr_cmd <= SdrCmd_xx;
state <= state + 1'd1;
end
endcase
end
assign SDRAM_CKE = 1;
assign SDRAM_nCS = 0;
assign SDRAM_nRAS = sdr_cmd[2];
assign SDRAM_nCAS = sdr_cmd[1];
assign SDRAM_nWE = sdr_cmd[0];
endmodule

View File

@ -1,165 +0,0 @@
-------------------------------------------------------------------[03.08.2014]
-- SDRAM Controller
-------------------------------------------------------------------------------
-- V1.0 03.08.2014 Initial release
-- modified for 8Mb SDRAM 15.03.2015 (Ivan Gorodetsky)
-- CLK = 84 MHz = 11.9 ns
-- WR/RD = 5T = 59.5 ns
-- RFSH = 6T = 71.4 ns
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity sdram is
port(
CLK : in std_logic;
clk_28MHz: in std_logic;
c0 : in std_logic;
c3 : in std_logic;
-- Memory port
loader : in std_logic;
bsel : in std_logic_vector(1 downto 0); -- Active HI
A : in std_logic_vector(23 downto 0);
DI : in std_logic_vector(15 downto 0);
DO : out std_logic_vector(15 downto 0);
curr_cpu : in std_logic;
DO_cpu : out std_logic_vector(15 downto 0);
REQ : in std_logic;
RNW : in std_logic;
-- SDRAM Pin
CKE : out std_logic;
RAS_n : out std_logic;
CAS_n : out std_logic;
WE_n : out std_logic;
CS_n : out std_logic;
BA : out std_logic_vector(1 downto 0);
MA : out std_logic_vector(12 downto 0);
DQ : inout std_logic_vector(15 downto 0);
DQML : out std_logic;
DQMH : out std_logic
);
end sdram;
architecture rtl of sdram is
signal state : unsigned(4 downto 0) := "00000";
signal col : std_logic_vector(7 downto 0);
signal WR_in : std_logic;
signal RD_in : std_logic;
signal REQ_in : std_logic;
signal RNW_in : std_logic;
signal rd_op : std_logic;
signal RFSH_in : std_logic;
signal sdr_cmd : std_logic_vector(2 downto 0);
constant SdrCmd_xx : std_logic_vector(2 downto 0) := "111"; -- no operation
constant SdrCmd_ac : std_logic_vector(2 downto 0) := "011"; -- activate
constant SdrCmd_rd : std_logic_vector(2 downto 0) := "101"; -- read
constant SdrCmd_wr : std_logic_vector(2 downto 0) := "100"; -- write
constant SdrCmd_pr : std_logic_vector(2 downto 0) := "010"; -- precharge all
constant SdrCmd_re : std_logic_vector(2 downto 0) := "001"; -- refresh
constant SdrCmd_ms : std_logic_vector(2 downto 0) := "000"; -- mode regiser set
-- Init------------------------------------------------------------------- Idle Read------- Write------ Refresh-------
-- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 16 17 1B 1C 16 17 13 14 15 16 17
-- pr xx xx re xx xx xx xx xx xx re xx xx xx xx xx xx ms xx xx xx xx xx xx xx/ac/re xx rd xx xx xx wr xx xx xx xx xx xx xx
begin
process (clk_28MHz)
begin
if rising_edge (clk_28MHz) then
if c3 = '1' then --next_cycle
RD_in <= REQ and RNW;
WR_in <= REQ and not RNW;
RFSH_in <= not REQ;
end if;
if c0 = '1' then --NOT WORK
RD_in <= '0';
WR_in <= '0';
RFSH_in <= '0';
end if;
end if;
end process;
process (CLK)
begin
if rising_edge(CLK) then
---------------------------------------------------------
case state is
-- Init
when "00000" => -- s00
sdr_cmd <= SdrCmd_pr; -- PRECHARGE
DQ <= (others => 'Z');
MA <= (others => '1');
BA <= "00";
DQML <= '1';
DQMH <= '1';
state <= state + 1;
when "00011" | "01010" => -- s03 s0A
sdr_cmd <= SdrCmd_re; -- REFRESH
state <= state + 1;
when "10001" => -- s11
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
MA <= "000" & "1" & "00" & "010" & "0" & "000";
state <= state + 1;
-- Idle
when "11000" => -- s18
rd_op <= '0';
if rd_op = '1' then
DO <= DQ;
if curr_cpu = '1' then
DO_cpu <= DQ;
end if;
end if;
if RD_in = '1' or (WR_in = '1' and (loader = '1' or A(23) = '0')) then
col <= A(7 downto 0); -- LOCK COL
sdr_cmd <= SdrCmd_ac; -- ACTIVE
BA <= A(10 downto 9);
MA <= "0"&A(23)&A(20 downto 11)&A(8); -- RAW_ADDR(12..0)
DQML <= not (bsel(0) or RD_in);
DQMH <= not (bsel(1) or RD_in);
rd_op <= RD_in;
state <= state + 1;
elsif RFSH_in = '1' then
sdr_cmd <= SdrCmd_re; -- REFRESH
state <= "10011"; -- s13
end if;
-- A24 A23 A22 A21 A20 A19 A18 A17 A16 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
-- -----------------------ROW------------------------- BA1 BA0 -----------COLUMN------------
-- Single read/write - with auto precharge
when "11010" => -- s1A
MA <= "00100" & col; -- A10 = 1 enable auto precharge; A9..0 = column
state <= "10110"; -- s16
if rd_op = '1' then
sdr_cmd <= SdrCmd_rd; -- READ
else
sdr_cmd <= SdrCmd_wr; -- WRITE
DQ <= DI;
end if;
when others =>
DQ <= (others => 'Z');
sdr_cmd <= SdrCmd_xx; -- NOP
state <= state + 1;
end case;
end if;
end process;
CKE <= '1';
CS_n <= '0';
RAS_n <= sdr_cmd(2);
CAS_n <= sdr_cmd(1);
WE_n <= sdr_cmd(0);
end rtl;

View File

@ -65,11 +65,11 @@ module tsconf
output [1:0] SDRAM_BA, output [1:0] SDRAM_BA,
output SDRAM_DQML, output SDRAM_DQML,
output SDRAM_DQMH, output SDRAM_DQMH,
output SDRAM_WE_N, output SDRAM_nCS,
output SDRAM_CAS_N, output SDRAM_nCAS,
output SDRAM_RAS_N, output SDRAM_nRAS,
output SDRAM_nWE,
output SDRAM_CKE, output SDRAM_CKE,
output SDRAM_CS_N,
// VGA // VGA
output [7:0] VGA_R, output [7:0] VGA_R,
@ -148,7 +148,7 @@ wire curr_cpu;
// SDRAM // SDRAM
wire [7:0] sdr_do_bus; wire [7:0] sdr_do_bus;
wire [15:0] sdr_do_bus_16; wire [15:0] sdr_do_bus_16;
wire [15:0] sdr2cpu_do_bus_16; wire [15:0] sdr_do_bus_16cpu;
wire sdr_wr; wire sdr_wr;
wire sdr_rd; wire sdr_rd;
wire req; wire req;
@ -484,7 +484,7 @@ zmem TS06
.cpu_req(cpu_req), .cpu_req(cpu_req),
.cpu_addr(cpu_addr_20), .cpu_addr(cpu_addr_20),
.cpu_wrbsel(cpu_wrbsel), // for 16bit data .cpu_wrbsel(cpu_wrbsel), // for 16bit data
.cpu_rddata(sdr2cpu_do_bus_16), .cpu_rddata(sdr_do_bus_16cpu),
.cpu_next(cpu_next), .cpu_next(cpu_next),
.cpu_strobe(cpu_strobe), // from ARBITER ACTIVE=HI .cpu_strobe(cpu_strobe), // from ARBITER ACTIVE=HI
.cpu_latch(cpu_latch), .cpu_latch(cpu_latch),
@ -506,32 +506,32 @@ arbiter TS07
.dram_rnw(dram_rnw), .dram_rnw(dram_rnw),
.dram_bsel(dram_bsel), .dram_bsel(dram_bsel),
.dram_wrdata(dram_wrdata), // data to be written .dram_wrdata(dram_wrdata), // data to be written
.video_addr({3'b000, video_addr}), // during access block, only when video_strobe==1 .video_addr(video_addr), // during access block, only when video_strobe==1
.go(go_arbiter), // start video access blocks .go(go_arbiter), // start video access blocks
.video_bw(video_bw), // ZX="11001", [4:3] -total cycles: 11 = 8 / 01 = 4 / 00 = 2 .video_bw(video_bw), // ZX="11001", [4:3] -total cycles: 11 = 8 / 01 = 4 / 00 = 2
.video_pre_next(video_pre_next), .video_pre_next(video_pre_next),
.video_next(video_next), // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe .video_next(video_next), // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe
.video_strobe(video_strobe), // (c3) one-cycle strobe meaning that video_data is available .video_strobe(video_strobe), // (c3) one-cycle strobe meaning that video_data is available
.next_vid(next_video), // used for TM prefetch .next_vid(next_video), // used for TM prefetch
.cpu_addr({csvrom, 2'b00, cpu_addr_20}), .cpu_addr(cpu_addr_20),
.cpu_wrdata(cpu_do_bus), .cpu_wrdata(cpu_do_bus),
.cpu_req(cpu_req), .cpu_req(cpu_req),
.cpu_rnw(rd), .cpu_rnw(rd | csvrom),
.cpu_wrbsel(cpu_wrbsel), .cpu_wrbsel(cpu_wrbsel),
.cpu_next(cpu_next), // next cycle is allowed to be used by CPU .cpu_next(cpu_next), // next cycle is allowed to be used by CPU
.cpu_strobe(cpu_strobe), // c2 strobe .cpu_strobe(cpu_strobe), // c2 strobe
.cpu_latch(cpu_latch), // c2-c3 strobe .cpu_latch(cpu_latch), // c2-c3 strobe
.curr_cpu_o(curr_cpu), .curr_cpu_o(curr_cpu),
.dma_addr({3'b000, dma_addr}), .dma_addr(dma_addr),
.dma_wrdata(dma_wrdata), .dma_wrdata(dma_wrdata),
.dma_req(dma_req), .dma_req(dma_req),
.dma_rnw(dma_rnw), .dma_rnw(dma_rnw),
.dma_next(dma_next), .dma_next(dma_next),
.ts_addr({3'b000, ts_addr}), .ts_addr(ts_addr),
.ts_req(ts_req), .ts_req(ts_req),
.ts_pre_next(ts_pre_next), .ts_pre_next(ts_pre_next),
.ts_next(ts_next), .ts_next(ts_next),
.tm_addr({3'b000, tm_addr}), .tm_addr(tm_addr),
.tm_req(tm_req), .tm_req(tm_req),
.tm_next(tm_next) .tm_next(tm_next)
); );
@ -696,28 +696,27 @@ dpram #(.ADDRWIDTH(16), .MEM_INIT_FILE("tsbios.mif")) BIOS
sdram SE4 sdram SE4
( (
.clk(clk), .clk(clk),
.clk_28mhz(clk_28mhz), .cyc(ce&c3),
.c0(c0),
.c3(c3), .curr_cpu(curr_cpu),
.curr_cpu(curr_cpu), // from arbiter for luch DO_cpu
.loader(0), // loader = 1: wr to ROM
.bsel(dram_bsel), .bsel(dram_bsel),
.a(dram_addr), .A(dram_addr),
.di(dram_wrdata), .DI(dram_wrdata),
.do(sdr_do_bus_16), .DO(sdr_do_bus_16),
.do_cpu(sdr2cpu_do_bus_16), .DO_cpu(sdr_do_bus_16cpu),
.req(dram_req), .REQ(dram_req),
.rnw(dram_rnw), .RNW(dram_rnw),
.cke(SDRAM_CKE),
.ras_n(SDRAM_RAS_N), .SDRAM_DQ(SDRAM_DQ),
.cas_n(SDRAM_CAS_N), .SDRAM_A(SDRAM_A),
.we_n(SDRAM_WE_N), .SDRAM_BA(SDRAM_BA),
.cs_n(SDRAM_CS_N), .SDRAM_DQML(SDRAM_DQML),
.ba(SDRAM_BA), .SDRAM_DQMH(SDRAM_DQMH),
.ma(SDRAM_A), .SDRAM_nCS(SDRAM_nCS),
.dq(SDRAM_DQ[15:0]), .SDRAM_nCAS(SDRAM_nCAS),
.dqml(SDRAM_DQML), .SDRAM_nRAS(SDRAM_nRAS),
.dqmh(SDRAM_DQMH) .SDRAM_nWE(SDRAM_nWE),
.SDRAM_CKE(SDRAM_CKE)
); );

View File

@ -16,9 +16,6 @@ create_generated_clock -source [get_pins -compatibility_mode {pll_hdmi|pll_hdmi_
create_generated_clock -source [get_pins { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}] \ create_generated_clock -source [get_pins { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}] \
-name VID_CLK -divide_by 2 -duty_cycle 50 [get_nets {vip|output_inst|vid_clk}] -name VID_CLK -divide_by 2 -duty_cycle 50 [get_nets {vip|output_inst|vid_clk}]
create_generated_clock -source [get_pins -compatibility_mode {*|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk}] \
-name ZCLK -divide_by 2 -duty_cycle 50 [get_nets {emu:emu|tsconf:tsconf|zclock:TS02|zclk_o}]
derive_clock_uncertainty derive_clock_uncertainty
@ -35,7 +32,7 @@ set_output_delay -min -clock SDRAM_CLK -0.9ns [get_ports {SDRAM_D* SDRAM_A* SDRA
# Decouple different clock groups (to simplify routing) # Decouple different clock groups (to simplify routing)
set_clock_groups -asynchronous \ set_clock_groups -asynchronous \
-group [get_clocks { *|pll|pll_inst|altera_pll_i|general[*].gpll~PLL_OUTPUT_COUNTER|divclk ZCLK}] \ -group [get_clocks { *|pll|pll_inst|altera_pll_i|general[*].gpll~PLL_OUTPUT_COUNTER|divclk}] \
-group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk VID_CLK}] \ -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk VID_CLK}] \
-group [get_clocks { *|h2f_user0_clk}] \ -group [get_clocks { *|h2f_user0_clk}] \
-group [get_clocks { FPGA_CLK1_50 FPGA_CLK2_50 FPGA_CLK3_50}] -group [get_clocks { FPGA_CLK1_50 FPGA_CLK2_50 FPGA_CLK3_50}]