mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 14:51:25 +03:00
Update SDRAM controller and arbiter.
This commit is contained in:
@ -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 VERILOG_FILE src/kempston_mouse.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/tsconf.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv
|
||||
|
@ -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 VERILOG_FILE src/kempston_mouse.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/tsconf.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ddram.sv
|
||||
|
@ -259,11 +259,11 @@ tsconf tsconf
|
||||
.SDRAM_BA(SDRAM_BA),
|
||||
.SDRAM_DQML(SDRAM_DQML),
|
||||
.SDRAM_DQMH(SDRAM_DQMH),
|
||||
.SDRAM_WE_N(SDRAM_nWE),
|
||||
.SDRAM_CAS_N(SDRAM_nCAS),
|
||||
.SDRAM_RAS_N(SDRAM_nRAS),
|
||||
.SDRAM_nWE(SDRAM_nWE),
|
||||
.SDRAM_nCAS(SDRAM_nCAS),
|
||||
.SDRAM_nRAS(SDRAM_nRAS),
|
||||
.SDRAM_CKE(SDRAM_CKE),
|
||||
.SDRAM_CS_N(SDRAM_nCS),
|
||||
.SDRAM_nCS(SDRAM_nCS),
|
||||
|
||||
.VGA_R(R),
|
||||
.VGA_G(G),
|
||||
|
@ -49,206 +49,185 @@
|
||||
// - DMA - CPU
|
||||
|
||||
|
||||
module arbiter(
|
||||
module arbiter
|
||||
(
|
||||
|
||||
input wire clk,
|
||||
input wire c0,
|
||||
input wire c1,
|
||||
input wire c2,
|
||||
input wire c3,
|
||||
input clk,
|
||||
input c0,
|
||||
input c1,
|
||||
input c2,
|
||||
input c3,
|
||||
|
||||
// dram.v interface
|
||||
output wire [23:0] dram_addr, // address for dram access
|
||||
output wire dram_req, // dram request
|
||||
output wire 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 wire [15:0] dram_wrdata, // data to be written
|
||||
// dram.v interface
|
||||
output [20:0] dram_addr, // address for dram access
|
||||
output dram_req, // dram request
|
||||
output dram_rnw, // Read-NotWrite
|
||||
output [ 1:0] dram_bsel, // byte select: bsel[1] for wrdata[15:8], bsel[0] for wrdata[7:0]
|
||||
output [15:0] dram_wrdata, // data to be written
|
||||
|
||||
// video
|
||||
input wire [23:0] video_addr, // during access block, only when video_strobe==1
|
||||
input wire go, // start video access blocks
|
||||
input wire [ 4:0] video_bw, // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2
|
||||
// video
|
||||
input [20:0] video_addr, // during access block, only when video_strobe==1
|
||||
input go, // start video access blocks
|
||||
input [ 4:0] video_bw, // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2
|
||||
// [2:0] - need cycles
|
||||
output wire 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 wire 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 wire next_vid, // used for TM prefetch
|
||||
output video_pre_next, // (c1)
|
||||
output video_next, // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe
|
||||
output video_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 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,
|
||||
// CPU
|
||||
input [20:0] cpu_addr,
|
||||
input [ 7:0] cpu_wrdata,
|
||||
input cpu_req,
|
||||
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 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,
|
||||
output curr_cpu_o,
|
||||
// DMA
|
||||
input [20:0] dma_addr,
|
||||
input [15:0] dma_wrdata,
|
||||
input dma_req,
|
||||
input dma_rnw,
|
||||
output dma_next,
|
||||
|
||||
// TS
|
||||
input wire [23:0] ts_addr,
|
||||
input wire ts_req,
|
||||
output wire ts_pre_next,
|
||||
output wire ts_next,
|
||||
|
||||
// TM
|
||||
input wire [23:0] tm_addr,
|
||||
input wire tm_req,
|
||||
output wire tm_next,
|
||||
|
||||
//-----
|
||||
output wire [7:0] TST
|
||||
// TS
|
||||
input [20:0] ts_addr,
|
||||
input ts_req,
|
||||
output ts_pre_next,
|
||||
output ts_next,
|
||||
|
||||
// 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 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 VIDEO = 1;
|
||||
localparam TS = 2;
|
||||
localparam TM = 3;
|
||||
localparam DMA = 4;
|
||||
|
||||
localparam CPU = 0;
|
||||
localparam VIDEO = 1;
|
||||
localparam TS = 2;
|
||||
localparam TM = 3;
|
||||
localparam DMA = 4;
|
||||
reg [CYCLES-1:0] curr_cycle; // type of the cycle in progress
|
||||
reg [CYCLES-1:0] next_cycle; // type of the next cycle
|
||||
|
||||
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];
|
||||
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 next_cpu = next_cycle[CPU];
|
||||
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];
|
||||
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:
|
||||
// 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 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_only = stall || (vid_rem == blk_rem);
|
||||
wire video_idle = ~|vid_rem;
|
||||
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 video_start = ~|blk_rem;
|
||||
wire video_only = stall || (vid_rem == blk_rem);
|
||||
wire video_idle = ~|vid_rem;
|
||||
|
||||
reg [2:0] blk_rem; // remaining accesses in a block (7..0)
|
||||
reg stall;
|
||||
always @(posedge clk) if (c3)
|
||||
begin
|
||||
reg [2:0] blk_rem; // remaining accesses in a block (7..0)
|
||||
reg stall;
|
||||
always @(posedge clk) begin
|
||||
if (c3) begin
|
||||
blk_rem <= blk_nrem;
|
||||
if (video_start)
|
||||
stall <= bw_full & go;
|
||||
if (video_start) stall <= bw_full & go;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// track vid_rem counter
|
||||
// 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_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] vidmax = {video_bw[2:0]}; // number of cycles for video access
|
||||
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_next = video_idle ? 3'd0 : (vid_rem - 3'd1);
|
||||
wire [2:0] vidmax = {video_bw[2:0]}; // number of cycles for video access
|
||||
|
||||
reg [2:0] vid_rem; // remaining video accesses in block
|
||||
always @(posedge clk) if (c3)
|
||||
vid_rem <= vid_nrem;
|
||||
reg [2:0] vid_rem; // remaining video accesses in block
|
||||
always @(posedge clk) if (c3) vid_rem <= vid_nrem;
|
||||
|
||||
|
||||
// next cycle decision
|
||||
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_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 [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_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;
|
||||
|
||||
always @*
|
||||
if (video_start) // video burst start
|
||||
if (go) // video active line - 38us-ON, 26us-ON
|
||||
begin
|
||||
always @* begin
|
||||
if (video_start) begin // video burst start
|
||||
if (go) begin // video active line - 38us-ON, 26us-ON
|
||||
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));
|
||||
end
|
||||
|
||||
else // video idle
|
||||
begin
|
||||
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
|
||||
|
||||
else // video burst in progress
|
||||
begin
|
||||
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
|
||||
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 ? 16'h0000 : {2{cpu_wrdata[7:0]}}; // write data has to be clocked at c0 in dram.v
|
||||
assign dram_bsel[1:0] = curr_dma ? 2'b11 : {cpu_wrbsel, ~cpu_wrbsel};
|
||||
assign dram_addr = {24{curr_cpu}} & cpu_addr
|
||||
| {24{curr_vid}} & video_addr
|
||||
| {24{curr_ts}} & ts_addr
|
||||
| {24{curr_tm}} & tm_addr
|
||||
| {24{curr_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);
|
||||
assign dram_wrdata= curr_dma ? dma_wrdata : {cpu_wrdata,cpu_wrdata}; // write data has to be clocked at c0 in dram.v
|
||||
assign dram_bsel = {cpu_wrbsel | next_dma, ~cpu_wrbsel | next_dma};
|
||||
assign dram_req = |next_cycle;
|
||||
assign dram_rnw = next_cpu ? cpu_rnw : ~next_dma | dma_rnw;
|
||||
assign dram_addr = {21{next_cpu}} & cpu_addr
|
||||
| {21{next_vid}} & video_addr
|
||||
| {21{next_ts }} & ts_addr
|
||||
| {21{next_tm }} & tm_addr
|
||||
| {21{next_dma}} & dma_addr;
|
||||
|
||||
|
||||
reg cpu_rnw_r;
|
||||
always @(posedge clk) if (c3)
|
||||
cpu_rnw_r <= cpu_rnw;
|
||||
reg cpu_rnw_r;
|
||||
always @(posedge clk) if (c3) cpu_rnw_r <= cpu_rnw;
|
||||
|
||||
|
||||
// generation of read strobes: for video and cpu
|
||||
always @(posedge clk)
|
||||
if (c1)
|
||||
begin
|
||||
always @(posedge clk) begin
|
||||
if (c1) begin
|
||||
cpu_strobe <= curr_cpu && cpu_rnw_r;
|
||||
cpu_latch <= curr_cpu && cpu_rnw_r;
|
||||
end
|
||||
else if (c2)
|
||||
cpu_strobe <= 1'b0;
|
||||
else if (c3)
|
||||
cpu_latch <= 1'b0;
|
||||
else if (c2) cpu_strobe <= 1'b0;
|
||||
else if (c3) cpu_latch <= 1'b0;
|
||||
end
|
||||
|
||||
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 video_next = curr_vid & c2;
|
||||
assign video_strobe = curr_vid && c3;
|
||||
assign video_next_strobe = next_vid && c3;
|
||||
assign ts_pre_next = curr_ts & c1;
|
||||
assign ts_next = curr_ts & c2;
|
||||
|
||||
assign ts_pre_next = curr_ts & c1;
|
||||
assign ts_next = curr_ts & c2;
|
||||
assign tm_next = curr_tm & c2;
|
||||
|
||||
assign tm_next = curr_tm & c2;
|
||||
|
||||
assign dma_next = curr_dma & c2;
|
||||
assign dma_next = curr_dma & c2;
|
||||
|
||||
|
||||
endmodule
|
||||
|
120
src/sdram.v
Normal file
120
src/sdram.v
Normal 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
|
165
src/sdram.vhd
165
src/sdram.vhd
@ -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;
|
65
src/tsconf.v
65
src/tsconf.v
@ -65,11 +65,11 @@ module tsconf
|
||||
output [1:0] SDRAM_BA,
|
||||
output SDRAM_DQML,
|
||||
output SDRAM_DQMH,
|
||||
output SDRAM_WE_N,
|
||||
output SDRAM_CAS_N,
|
||||
output SDRAM_RAS_N,
|
||||
output SDRAM_nCS,
|
||||
output SDRAM_nCAS,
|
||||
output SDRAM_nRAS,
|
||||
output SDRAM_nWE,
|
||||
output SDRAM_CKE,
|
||||
output SDRAM_CS_N,
|
||||
|
||||
// VGA
|
||||
output [7:0] VGA_R,
|
||||
@ -148,7 +148,7 @@ wire curr_cpu;
|
||||
// SDRAM
|
||||
wire [7:0] sdr_do_bus;
|
||||
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_rd;
|
||||
wire req;
|
||||
@ -484,7 +484,7 @@ zmem TS06
|
||||
.cpu_req(cpu_req),
|
||||
.cpu_addr(cpu_addr_20),
|
||||
.cpu_wrbsel(cpu_wrbsel), // for 16bit data
|
||||
.cpu_rddata(sdr2cpu_do_bus_16),
|
||||
.cpu_rddata(sdr_do_bus_16cpu),
|
||||
.cpu_next(cpu_next),
|
||||
.cpu_strobe(cpu_strobe), // from ARBITER ACTIVE=HI
|
||||
.cpu_latch(cpu_latch),
|
||||
@ -506,32 +506,32 @@ arbiter TS07
|
||||
.dram_rnw(dram_rnw),
|
||||
.dram_bsel(dram_bsel),
|
||||
.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
|
||||
.video_bw(video_bw), // ZX="11001", [4:3] -total cycles: 11 = 8 / 01 = 4 / 00 = 2
|
||||
.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_strobe(video_strobe), // (c3) one-cycle strobe meaning that video_data is available
|
||||
.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_req(cpu_req),
|
||||
.cpu_rnw(rd),
|
||||
.cpu_rnw(rd | csvrom),
|
||||
.cpu_wrbsel(cpu_wrbsel),
|
||||
.cpu_next(cpu_next), // next cycle is allowed to be used by CPU
|
||||
.cpu_strobe(cpu_strobe), // c2 strobe
|
||||
.cpu_latch(cpu_latch), // c2-c3 strobe
|
||||
.curr_cpu_o(curr_cpu),
|
||||
.dma_addr({3'b000, dma_addr}),
|
||||
.dma_addr(dma_addr),
|
||||
.dma_wrdata(dma_wrdata),
|
||||
.dma_req(dma_req),
|
||||
.dma_rnw(dma_rnw),
|
||||
.dma_next(dma_next),
|
||||
.ts_addr({3'b000, ts_addr}),
|
||||
.ts_addr(ts_addr),
|
||||
.ts_req(ts_req),
|
||||
.ts_pre_next(ts_pre_next),
|
||||
.ts_next(ts_next),
|
||||
.tm_addr({3'b000, tm_addr}),
|
||||
.tm_addr(tm_addr),
|
||||
.tm_req(tm_req),
|
||||
.tm_next(tm_next)
|
||||
);
|
||||
@ -696,28 +696,27 @@ dpram #(.ADDRWIDTH(16), .MEM_INIT_FILE("tsbios.mif")) BIOS
|
||||
sdram SE4
|
||||
(
|
||||
.clk(clk),
|
||||
.clk_28mhz(clk_28mhz),
|
||||
.c0(c0),
|
||||
.c3(c3),
|
||||
.curr_cpu(curr_cpu), // from arbiter for luch DO_cpu
|
||||
.loader(0), // loader = 1: wr to ROM
|
||||
.cyc(ce&c3),
|
||||
|
||||
.curr_cpu(curr_cpu),
|
||||
.bsel(dram_bsel),
|
||||
.a(dram_addr),
|
||||
.di(dram_wrdata),
|
||||
.do(sdr_do_bus_16),
|
||||
.do_cpu(sdr2cpu_do_bus_16),
|
||||
.req(dram_req),
|
||||
.rnw(dram_rnw),
|
||||
.cke(SDRAM_CKE),
|
||||
.ras_n(SDRAM_RAS_N),
|
||||
.cas_n(SDRAM_CAS_N),
|
||||
.we_n(SDRAM_WE_N),
|
||||
.cs_n(SDRAM_CS_N),
|
||||
.ba(SDRAM_BA),
|
||||
.ma(SDRAM_A),
|
||||
.dq(SDRAM_DQ[15:0]),
|
||||
.dqml(SDRAM_DQML),
|
||||
.dqmh(SDRAM_DQMH)
|
||||
.A(dram_addr),
|
||||
.DI(dram_wrdata),
|
||||
.DO(sdr_do_bus_16),
|
||||
.DO_cpu(sdr_do_bus_16cpu),
|
||||
.REQ(dram_req),
|
||||
.RNW(dram_rnw),
|
||||
|
||||
.SDRAM_DQ(SDRAM_DQ),
|
||||
.SDRAM_A(SDRAM_A),
|
||||
.SDRAM_BA(SDRAM_BA),
|
||||
.SDRAM_DQML(SDRAM_DQML),
|
||||
.SDRAM_DQMH(SDRAM_DQMH),
|
||||
.SDRAM_nCS(SDRAM_nCS),
|
||||
.SDRAM_nCAS(SDRAM_nCAS),
|
||||
.SDRAM_nRAS(SDRAM_nRAS),
|
||||
.SDRAM_nWE(SDRAM_nWE),
|
||||
.SDRAM_CKE(SDRAM_CKE)
|
||||
);
|
||||
|
||||
|
||||
|
@ -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}] \
|
||||
-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
|
||||
|
||||
|
||||
@ -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)
|
||||
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 { *|h2f_user0_clk}] \
|
||||
-group [get_clocks { FPGA_CLK1_50 FPGA_CLK2_50 FPGA_CLK3_50}]
|
||||
|
Reference in New Issue
Block a user