first somehow working version for MIST

This commit is contained in:
Eugene Lozovoy
2024-09-08 23:02:45 +03:00
parent a2692e3446
commit b575eed412
92 changed files with 1163 additions and 22527 deletions

View File

@ -49,7 +49,7 @@
// - DMA - CPU
module arbiter
module arbiter
(
input clk,
@ -57,16 +57,17 @@ module arbiter
input c1,
input c2,
input c3,
input cyc,
// dram.v interface
output [20:0] dram_addr, // address for dram access
output [21: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 [20: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 go, // start video access blocks
input [ 4:0] video_bw, // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2
// [2:0] - need cycles
@ -77,65 +78,77 @@ module arbiter
output next_vid, // used for TM prefetch
// CPU
input [20:0] cpu_addr,
input [20:0] cpu_addr,
input [ 7:0] cpu_wrdata,
input cpu_req,
input cpu_rnw,
input cpu_csrom,
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 [20:0] dma_addr,
input [15:0] dma_wrdata,
input dma_req,
input dma_rnw,
output dma_next,
// TS
input [20:0] ts_addr,
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
input [20:0] tm_addr,
input tm_req,
output tm_next,
// ROM loader
input loader_clk,
input [15:0] loader_addr,
input [7:0] loader_data,
input loader_wr
);
assign curr_cpu_o = curr_cpu;
localparam CYCLES = 5;
localparam CYCLES = 6;
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 = 6'b000001;
localparam CYC_VID = 6'b000010;
localparam CYC_TS = 6'b000100;
localparam CYC_TM = 6'b001000;
localparam CYC_DMA = 6'b010000;
localparam CYC_LOADER = 6'b100000;
localparam CYC_FREE = 6'b000000;
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;
localparam LOADER = 5;
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 next_loader = next_cycle[LOADER];
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];
wire curr_loader = curr_cycle[LOADER];
// track blk_rem counter:
@ -148,11 +161,11 @@ wire video_idle = ~|vid_rem;
reg [2:0] blk_rem; // remaining accesses in a block (7..0)
reg stall;
always @(posedge clk) begin
always @(posedge clk) begin
if (c3) begin
blk_rem <= blk_nrem;
if (video_start) stall <= bw_full & go;
end
end
end
@ -167,6 +180,18 @@ reg [2:0] vid_rem; // remaining video accesses in block
always @(posedge clk) if (c3) vid_rem <= vid_nrem;
reg loader_wr0;
reg [7:0] loader_data0;
always @(posedge loader_clk) begin
if (loader_wr) begin
loader_wr0 <= 1'd1;
loader_data0 <= loader_data;
end
else if (cyc) begin
loader_wr0 <= 1'd0;
end
end
// 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;
@ -174,7 +199,11 @@ wire dev_req = ts_req || tm_req || dma_req;
wire dev_over_cpu = 0;
always @* begin
if (video_start) begin // video burst start
if (loader_wr0) begin
cpu_next = 1'b0;
next_cycle = CYC_LOADER;
end
else 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));
@ -182,26 +211,27 @@ always @* 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
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
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 : {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_wrdata= curr_loader? {loader_data0,loader_data0} : curr_dma ? dma_wrdata : {cpu_wrdata,cpu_wrdata}; // write data has to be clocked at c0 in dram.v
assign dram_bsel = next_loader? {loader_addr[0], ~loader_addr[0]} : next_dma ? 2'b11 : {cpu_wrbsel, ~cpu_wrbsel};
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;
assign dram_rnw = next_loader? 1'b0 : next_cpu ? cpu_rnw : ~next_dma | dma_rnw;
assign dram_addr = {22{next_loader}} & { 1'b1, 6'b000000, loader_addr[15:1] }
| {22{next_cpu}} & { cpu_csrom, {6{~cpu_csrom}} & cpu_addr[20:15], cpu_addr[14:0] }
| {22{next_vid}} & { 1'b0, video_addr }
| {22{next_ts }} & { 1'b0, ts_addr }
| {22{next_tm }} & { 1'b0, tm_addr }
| {22{next_dma}} & { 1'b0, dma_addr };
reg cpu_rnw_r;
always @(posedge clk) if (c3) cpu_rnw_r <= cpu_rnw;

View File

@ -1,124 +0,0 @@
//
// ddram.v
//
// DE10-nano DDR3 memory interface
//
// Copyright (c) 2017 Sorgelig
//
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ------------------------------------------
//
// 8-bit version
module ddram
(
input reset,
input DDRAM_CLK,
input DDRAM_BUSY,
output [7:0] DDRAM_BURSTCNT,
output [28:0] DDRAM_ADDR,
input [63:0] DDRAM_DOUT,
input DDRAM_DOUT_READY,
output DDRAM_RD,
output [63:0] DDRAM_DIN,
output [7:0] DDRAM_BE,
output DDRAM_WE,
input [27:0] addr, // 256MB at the end of 1GB
output [7:0] dout, // data output to cpu
input [7:0] din, // data input from cpu
input we, // cpu requests write
input rd, // cpu requests read
output ready // dout is valid. Ready to accept new read/write.
);
assign DDRAM_BURSTCNT = 1;
assign DDRAM_BE = (8'd1<<ram_address[2:0]) | {8{ram_read}};
assign DDRAM_ADDR = {4'b0011, ram_address[27:3]}; // RAM at 0x30000000
assign DDRAM_RD = ram_read;
assign DDRAM_DIN = ram_cache;
assign DDRAM_WE = ram_write;
assign dout = ram_q;
assign ready = ~busy;
reg [7:0] ram_q;
reg [27:0] ram_address;
reg ram_read;
reg [63:0] ram_cache;
reg ram_write;
reg [7:0] cached;
reg busy;
always @(posedge DDRAM_CLK)
begin
reg old_rd, old_we;
reg old_reset;
reg state;
old_reset <= reset;
if(old_reset && ~reset) begin
busy <= 0;
state <= 0;
cached <= 0;
end
if(!DDRAM_BUSY)
begin
ram_write <= 0;
ram_read <= 0;
if(state) begin
if(DDRAM_DOUT_READY) begin
ram_q <= DDRAM_DOUT[{ram_address[2:0], 3'b000} +:8];
ram_cache <= DDRAM_DOUT;
cached <= 8'hFF;
state <= 0;
busy <= 0;
end
end
else begin
old_rd <= rd;
old_we <= we;
busy <= 0;
if(~old_we && we) begin
ram_cache[{addr[2:0], 3'b000} +:8] <= din;
ram_address <= addr;
busy <= 1;
ram_write <= 1;
cached <= ((ram_address[27:3] == addr[27:3]) ? cached : 8'h00) | (8'd1<<addr[2:0]);
end
if(~old_rd && rd) begin
if((ram_address[27:3] == addr[27:3]) && (cached & (8'd1<<addr[2:0]))) begin
ram_q <= ram_cache[{addr[2:0], 3'b000} +:8];
end
else begin
ram_address <= addr;
ram_read <= 1;
state <= 1;
cached <= 0;
busy <= 1;
end
end
end
end
end
endmodule

View File

@ -56,7 +56,7 @@ defparam
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone V",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",

View File

@ -128,7 +128,7 @@ assign SDRAM_DQMH = SDRAM_A[12];
altddio_out
#(
.extend_oe_disable("OFF"),
.intended_device_family("Cyclone V"),
.intended_device_family("Cyclone III"),
.invert_output("OFF"),
.lpm_hint("UNUSED"),
.lpm_type("altddio_out"),