A2PDP11 (14) バスサイクルの調整
メモリ読み出し時の、バスサイクル延長を修正し、8 サイクルで完了するように修正します。
バスサイクルの延長は、T4 の立ち下がり時に CONT をアサートすることで終了します。
元の回路では、PDP-11/HACK を参考に、SCTL と CONT を直結しているので、CONT がアサートされるタイミングは、1 回目の T4 の立ち下がり時に間に合いません。そのため、T4 が 2 サイクル分追加されます。
下図の、赤マーカーが T4 の立ち上がり、白マーカー部が CONT が検出される T4 の立ち下がりです。
CONT を GND に接続し、常にアサート状態にします。
このままでは、メモリ読み出しが追いつかないので、メモリクロックを 165 MHz に変更します。
DAL HI/LO 切り替え用のクロックを、36MHz から 54MHz にします。
ram.sv を修正します。
`default_nettype none
// DCJ11 TangNano interface by nanja.info
// PSRAM interface module
// TEST8 2024.08.31 4MB RAM
// TEST9 2024.09.03 Byte Data Write
// TEST10 2024.09.13 Add rst_n and init interface
// TEST11 2024.09.20 Modify read timing
module ram (
output wire [1:0] O_psram_ck,
output wire [1:0] O_psram_ck_n,
inout wire [15:0] IO_psram_dq,
inout wire [1:0] IO_psram_rwds,
output wire [1:0] O_psram_cs_n,
output wire [1:0] O_psram_reset_n,
input wire ram_read,
input wire ram_write,
input wire ram_byte,
input wire [21:0] ram_addr,
output reg [15:0] ram_rdata,
input wire [15:0] ram_wdata,
input wire mclk,
input wire rst_n,
output wire init
);
assign init = init_calib0; // for debug
Gowin_rPLL_ram pll_ram(
.clkout(memory_clk), //output clkout
.lock(pll_lock), //output lock
.clkoutp(memory_clk_p), //output clkoutp
.clkoutd(clk_d), //output clkoutd
.clkin(mclk) //input clkin
);
logic clk_d;
logic memory_clk;
logic memory_clk_p;
logic pll_lock;
logic init_calib0;
logic init_calib1;
logic clk_out;
logic cmd0;
logic cmd1;
logic cmd_en0;
logic cmd_en1;
logic [20:0] addr0;
logic [20:0] addr1;
logic [31:0] wr_data0;
logic [31:0] wr_data1;
logic [31:0] rd_data0;
logic [31:0] rd_data1;
logic rd_data_valid0;
logic rd_data_valid1;
logic [3:0] data_mask0;
logic [3:0] data_mask1;
//assign rst_n = 1'b1;
assign cmd1 = 1'b0;
assign cmd_en1 = 1'b0;
assign addr1 = 21'b0;
assign wr_data1 = 32'b0;
assign data_mask1 = 4'b0;
PSRAM_Memory_Interface_HS_2CH_V2_Top psram(
.clk_d(clk_d), //input clk_d
.rst_n(rst_n), //input rst_n
.memory_clk(memory_clk), //input memory_clk
.memory_clk_p(memory_clk_p), //input memory_clk_p
.pll_lock(pll_lock), //input pll_lock
.O_psram_ck(O_psram_ck), //output [1:0] O_psram_ck
.O_psram_ck_n(O_psram_ck_n), //output [1:0] O_psram_ck_n
.IO_psram_rwds(IO_psram_rwds), //inout [1:0] IO_psram_rwds
.O_psram_reset_n(O_psram_reset_n), //output [1:0] O_psram_reset_n
.IO_psram_dq(IO_psram_dq), //inout [15:0] IO_psram_dq
.O_psram_cs_n(O_psram_cs_n), //output [1:0] O_psram_cs_n
.init_calib0(init_calib0), //output init_calib0
.init_calib1(init_calib1), //output init_calib1
.clk_out(clk_out), //output clk_out
.cmd0(cmd0), //input cmd0
.cmd1(cmd1), //input cmd1
.cmd_en0(cmd_en0), //input cmd_en0
.cmd_en1(cmd_en1), //input cmd_en1
.addr0(addr0), //input [20:0] addr0
.addr1(addr1), //input [20:0] addr1
.wr_data0(wr_data0), //input [31:0] wr_data0
.wr_data1(wr_data1), //input [31:0] wr_data1
.rd_data0(rd_data0), //output [31:0] rd_data0
.rd_data1(rd_data1), //output [31:0] rd_data1
.rd_data_valid0(rd_data_valid0), //output rd_data_valid0
.rd_data_valid1(rd_data_valid1), //output rd_data_valid1
.data_mask0(data_mask0), //input [3:0] data_mask0
.data_mask1(data_mask1) //input [3:0] data_mask1
);
logic rd0;
logic rd1;
logic wr0;
logic wr1;
always_ff@(posedge clk_out) begin
rd0 <= ram_read;
rd1 <= rd0;
wr0 <= ram_write;
wr1 <= wr0;
end
logic [5:0] mcycle;
always_ff@(posedge clk_out or negedge rst_n) begin
if (!rst_n) begin
mcycle <= 0;
wr_data0 <= 32'b0;
cmd_en0 <= 0;
data_mask0 <= 4'b1111;
end else if (init_calib0) begin
if (mcycle == 0) begin
if (rd1) begin
addr0 <= ram_addr[21:1];
cmd0 <= 0; // READ
cmd_en0 <= 1;
mcycle <= 1;
end else if (wr1) begin
if (ram_byte) begin
data_mask0 <= {!ram_addr[0], ram_addr[0], 2'b11};
end else begin
data_mask0 <= 4'b0011;
end
wr_data0[31:16] <= ram_wdata;
addr0 <= ram_addr[21:1];
cmd0 <= 1; // WRITE
cmd_en0 <= 1;
mcycle <= 15;
end
end else if (mcycle == 1) begin
cmd_en0 <= 0;
mcycle <= 2;
end else if (mcycle < 14) begin
mcycle <= mcycle + 1'b1;
end else if (mcycle == 14) begin
if (!rd1) begin
mcycle <= 0;
end
end else if (mcycle == 15) begin
cmd_en0 <= 0;
data_mask0 <= 4'b1111;
mcycle <= 16;
end else if (mcycle < 28) begin
mcycle <= mcycle + 1'b1;
end else if (mcycle == 28) begin
if (!wr1) begin
mcycle <= 0;
end
end
end
end
logic [1:0] rcycle;
always_ff@(negedge clk_out) begin
if (mcycle == 1) begin
rcycle <= 0;
end else if (rd_data_valid0) begin
if (rcycle == 1'b0) begin
ram_rdata <= rd_data0[31:16];
end
rcycle <= rcycle + 1'b1;
end
end
endmodule
`default_nettype wire
top.sv を変更します。
`default_nettype none
// DCJ11 TangNano interface by nanja.info
// TEST2 2024.07.28 Bus read
// TSET3 2024.08.03 Start-Up config
// TEST4 2024.08.07 NXM abort signal
// TEST5 2024.08.12 Console ODT output
// TEST6 2024.08.25 Console ODT input
// TEST7 2024.08.26 2KB RAM
// TEST8 2024.08.31 4MB RAM
// TEST9 2024.09.03 Byte Data Write
// TEST10 2024.09.13 Paper Tape Reader/Punch dummy response
// TEST11 2024.09.21 Modify read timing
module top (
inout wire [15:0] dal, // DAL<21:0>, BS<1:0>
input wire [3:0] aio, // AIO<3:0>
input wire bufctl_n,
input wire ale_n,
output wire nxm_n,
input wire sctl_n,
input wire clk,
output reg dv,
output reg miss_n,
output reg dallo_oe_n,
output reg dalhi_oe_n,
input wire rrdy, // Ready to read from DCJ11's ODT data
output reg rstb, // Strobe for read from DCJ11's ODT data
input wire wrdy, // Ready to write to DCJ11's ODT data
output reg wstb, // Strobe for write to DCJ11's ODT data
inout wire [7:0] ad, // ODT data
output wire [1:0] O_psram_ck,
output wire [1:0] O_psram_ck_n,
inout wire [15:0] IO_psram_dq,
inout wire [1:0] IO_psram_rwds,
output wire [1:0] O_psram_cs_n,
output wire [1:0] O_psram_reset_n,
input wire mclk,
input wire rst_n,
output wire led1
);
// AIO CODE
parameter NIO = 4'b1111; // internal operation only, no I/O
parameter GP_READ = 4'b1110; // General-Purpose read
parameter INTERRUPT_ACK = 4'b1101; // Interrupt acknowledge, vector read
parameter REQUEST_READ = 4'b1100; // Instruction-stream request read
parameter RMW_NOLOCK = 4'b1011; // Read/Modify/Write - no bus lock
parameter RMW_BUSLOCK = 4'b1010; // Read/Modify/Write - bus lock
parameter DATA_READ = 4'b1001; // Data-stream read
parameter DEMAND_READ = 4'b1000; // Instruction-stream demand read
parameter GP_WRITE = 4'b0101; // General-Purpose word write
parameter BYTE_WRITE = 4'b0011; // Bus byte write
parameter WORD_WRITE = 4'b0001; // Bus word write
// BANK SELECT
parameter BS_MEM = 2'b00; // Memory
parameter BS_SYS = 2'b01; // System register
parameter BS_EXT = 2'b10; // Extarnal I/O
parameter BS_INT = 2'b11; // Internal register
// GP CODE
parameter POWER_UP0 = 8'o000; // Reads the power-up mode
parameter POWER_UP2 = 8'o002; // Reads the power-up mode, clears the FPA’s FPS
// DLART
parameter DLART = 19'o1777756; // DLART registers
parameter RCSR = 22'o17777560; // Receiver Control and Status Register
parameter RBUF = 22'o17777562; // Receiver Buffer Register
parameter XCSR = 22'o17777564; // Transmitter Control And Status Register
parameter XBUF = 22'o17777566; // Transmitter Buffer Register
// PC11 Paper Tape Reader/Punch
parameter PC11 = 19'o1777755; // PC11 registers
parameter PRS = 22'o17777550; // Paper Tape Reader Status Register
parameter PRB = 22'o17777552; // Paper Tape Reader Buffer Register
parameter PPS = 22'o17777554; // Paper Tape Punch Status Register
parameter PPB = 22'o17777556; // Paper Tape Punch Buffer Register
parameter HIMEM = 22'o17757777; // End of RAM
logic sclk;
Gowin_OSC osc(
.oscout(sclk) //output oscout
);
logic clk_x3; // clk x 3 = 54MHz
Gowin_rPLL rpll(
.clkout(clk_x3), //output clkout
.clkin(clk) //input clkin
);
logic [7:0] count;
logic [15:0] mdallo;
logic [21:0] mdal;
logic [3:0] maio;
logic [1:0] mbs;
logic [7:0] gp_code;
always_ff@(posedge clk_x3) begin
if (ale_n) begin
count <= 0;
end else begin
if (count == 8'd0) begin
dallo_oe_n <= 1'b1;
dalhi_oe_n <= 1'b0;
if ((aio == GP_READ) || (aio == GP_WRITE)) begin
gp_code <= dal[7:0];
end else begin
gp_code <= 8'b11111111;
end
mdallo <= dal;
end else if (count == 8'd1) begin
maio <= aio;
mbs[0] <= dal[6];
mbs[1] <= dal[7];
mdal[21] <= dal[8];
mdal[20] <= dal[0];
mdal[19] <= dal[9];
mdal[18] <= dal[10];
mdal[17] <= dal[11];
mdal[16] <= dal[12];
mdal[15:0] <= mdallo;
dallo_oe_n <= 1'b0;
dalhi_oe_n <= 1'b1;
end
count <= count + 1'b1;
end
end
assign nxm_n = sctl_n ? 1'b1 :
((maio[2] == 0) && (mbs == BS_MEM) && (mdal > HIMEM)) ? 1'b0 :
((maio[2] == 0) && (mbs == BS_EXT) && ((mdal[21:3] != DLART) && (mdal[21:3] != PC11))) ? 1'b0 :
1'b1;
logic rxrdy;
logic rrdy1;
logic rrdy0;
logic [7:0] rdata;
always_ff@(negedge clk) begin
rrdy0 <= rrdy;
rrdy1 <= rrdy0;
end
always_ff@(negedge clk) begin
if ((sctl_n == 0) && (mdal == XBUF)) begin
rstb <= 1'b1;
rxrdy <= 1'b0;
rdata <= dal[7:0];
end else if (!rrdy1) begin
rstb <= 1'b0;
end else if (!rstb) begin
rxrdy <= 1'b1;
end
if (gp_code == 8'o014) begin
rxrdy <= 1'b1;
rstb <= 1'b0;
end
end
assign ad = rstb ? rdata : 8'bz;
logic wxrdy;
logic wrdy1;
logic wrdy0;
logic [7:0] wdata;
always_ff@(negedge clk) begin
wrdy0 <= wrdy;
wrdy1 <= wrdy0;
end
always_ff@(negedge clk) begin
if (wrdy1) begin
wstb <= 1'b1;
end else if (wstb) begin
wdata <= ad;
wstb <= 1'b0;
wxrdy <= 1'b1;
end else if ((mdal == RBUF) && (!sctl_n)) begin
wxrdy <= 1'b0;
end
if (gp_code == 8'o014) begin
wxrdy <= 1'b0;
wstb <= 1'b0;
end
end
assign dal = bufctl_n ? 16'bz :
(mdal == RCSR) ? {8'b0, wxrdy, 7'b0} :
(mdal == XCSR) ? {8'b0, rxrdy, 7'b0} :
(mdal == RBUF) ? wdata :
(mdal == PRS) ? 16'b1000_0000_0000_0000 :
(mdal == PRB) ? 16'b0 :
(mdal == PPS) ? 16'b0000_0000_1000_0000 :
(gp_code == POWER_UP0) ? 16'b0000000_0_0000_0_01_1 :
(gp_code == POWER_UP2) ? 16'b0000000_0_0000_0_01_1 :
(mdal <= HIMEM) ? ram_rdata : 16'bz;
logic init;
assign led1 = init;
ram u_ram(
.*
);
assign dv = 1'b1;
logic [21:0] ram_addr;
logic [15:0] ram_rdata;
logic [15:0] ram_wdata;
logic ram_read;
logic ram_write;
logic ram_byte;
always_ff@(posedge clk_x3) begin
if ((mbs == BS_MEM) && (count == 2)) begin
ram_addr <= mdal;
if ((maio[3:2] == 2'b10) || (maio == REQUEST_READ)) begin
miss_n <= 1'b0;
ram_read <= 1'b1;
end
end else if (count == 0) begin
miss_n <= 1'b1;
ram_read <= 1'b0;
end
end
always_ff@(posedge clk) begin
if ((mbs == BS_MEM) && (maio[3:2] == 2'b00) && (!sctl_n)) begin
if (maio == BYTE_WRITE) begin
ram_byte <= 1'b1;
end
ram_write <= 1'b1;
ram_wdata <= dal[15:0];
end else begin
ram_write <= 1'b0;
ram_byte <= 1'b0;
end
end
endmodule
`default_nettype wire
メモリ読み出し時の信号を確認します。
下図、左端の赤マーカーがクロック T0、白マーカーがクロック T4、オレンジマーカーが次の T0 です。8 クロックで読み出しが完了しているのが分かります。
ASCIIART の実行は、2 割弱改善し、11分38秒になりました。
参考文献
DCJ11 Microprocessor User's Guide, 3.5 BUS READ CYCLE, 1983
この記事が気に入ったらサポートをしてみませんか?