From 76ca22dbbc7c75e84b548332e7a1053f4202c563 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 22 Aug 2018 06:03:52 +0800 Subject: [PATCH] Update DMA and SPI to latest versions. --- src/memory/arbiter.v | 1 - src/memory/dma.v | 491 +++++++++++++++++++++++-------------------- src/spi.v | 139 ++++-------- src/tsconf.v | 13 +- 4 files changed, 302 insertions(+), 342 deletions(-) diff --git a/src/memory/arbiter.v b/src/memory/arbiter.v index 17c4f97..97c3fda 100644 --- a/src/memory/arbiter.v +++ b/src/memory/arbiter.v @@ -89,7 +89,6 @@ module arbiter( input wire [23:0] dma_addr, input wire [15:0] dma_wrdata, input wire dma_req, - input wire dma_z80_lp, input wire dma_rnw, output wire dma_next, diff --git a/src/memory/dma.v b/src/memory/dma.v index c46dda0..a7e6e5b 100644 --- a/src/memory/dma.v +++ b/src/memory/dma.v @@ -3,308 +3,335 @@ // to do // - probably add the extra 8 bit counter for number of bursts -module dma ( - -// clocks +module dma +( + // clocks input wire clk, input wire c2, input wire reset, -// interface + // interface input wire [8:0] dmaport_wr, output wire dma_act, output reg [15:0] data, output wire [ 7:0] wraddr, output wire int_start, -// Z80 + // Z80 input wire [7:0] zdata, -// DRAM interface + // DRAM interface output wire [20:0] dram_addr, input wire [15:0] dram_rddata, output wire [15:0] dram_wrdata, - output wire dram_req, - output reg dma_z80_lp, - output wire dram_rnw, - input wire dram_next, + output wire dram_req, + output wire dram_rnw, + input wire dram_next, -// SPI interface - input wire [7:0] spi_rddata, - output wire [7:0] spi_wrdata, - output wire spi_req, - input wire spi_stb, - input wire spi_start, + // SPI interface + input wire [7:0] spi_rddata, + output wire [7:0] spi_wrdata, + output wire spi_req, + input wire spi_stb, -// IDE interface + // IDE interface input wire [15:0] ide_in, output wire [15:0] ide_out, - output wire ide_req, - output wire ide_rnw, - input wire ide_stb, + output wire ide_req, + output wire ide_rnw, + input wire ide_stb, -// CRAM interface - output wire cram_we, + // CRAM interface + output wire cram_we, -// SFILE interface - output wire sfile_we, - //--------------------- - output wire [3:0] TST + // SFILE interface + output wire sfile_we ); - - assign TST[0] = dma_act; - assign TST[1] = dma_len; - assign TST[2] = b_len[7]; - assign TST[3] = b_ctr[7]; + // mode: // 0 - device to RAM (read from device) // 1 - RAM to device (write to device) - assign wraddr = d_addr[7:0]; - // wire [8:0] dma_wr = dmaport_wr & {9{!dma_act}}; // blocking of DMA regs write strobes while DMA active - wire [8:0] dma_wr = dmaport_wr; + assign wraddr = d_addr[7:0]; - wire dma_saddrl = dma_wr[0]; - wire dma_saddrh = dma_wr[1]; - wire dma_saddrx = dma_wr[2]; - wire dma_daddrl = dma_wr[3]; - wire dma_daddrh = dma_wr[4]; - wire dma_daddrx = dma_wr[5]; - wire dma_len = dma_wr[6]; - wire dma_launch = dma_wr[7]; - wire dma_num = dma_wr[8]; + wire dma_saddrl = dmaport_wr[0]; + wire dma_saddrh = dmaport_wr[1]; + wire dma_saddrx = dmaport_wr[2]; + wire dma_daddrl = dmaport_wr[3]; + wire dma_daddrh = dmaport_wr[4]; + wire dma_daddrx = dmaport_wr[5]; + wire dma_len = dmaport_wr[6]; + wire dma_launch = dmaport_wr[7]; + wire dma_num = dmaport_wr[8]; // DRAM - assign dram_addr = state_rd ? ((!dv_blt || !phase_blt) ? s_addr : d_addr) : d_addr; - assign dram_wrdata = data; - assign dram_req = dma_act && state_mem; - assign dram_rnw = state_rd; + assign dram_addr = state_rd ? ((!dv_blt || !phase_blt) ? s_addr : d_addr) : d_addr; + assign dram_wrdata = data; + assign dram_req = dma_act && state_mem; + assign dram_rnw = state_rd; // devices - wire [3:0] devsel = {dma_wnr, device}; - wire dv_ram = (device == 3'b001) || (devsel == 4'b0100); - wire dv_blt = (devsel == 4'b1001); - wire dv_fil = (devsel == 4'b0100); - wire dv_spi = (device == 3'b010); - wire dv_ide = (device == 3'b011); - wire dv_crm = (devsel == 4'b1100); - wire dv_sfl = (devsel == 4'b1101); + localparam DEV_RAM = 3'b0001; + localparam DEV_BLT1 = 4'b1001; + localparam DEV_BLT2 = 4'b0110; + localparam DEV_FIL = 4'b0100; + localparam DEV_SPI = 3'b010; + localparam DEV_IDE = 3'b011; + localparam DEV_CRM = 4'b1100; + localparam DEV_SFL = 4'b1101; + localparam DEV_FDD = 4'b0101; - wire dev_req = dma_act && state_dev; - wire dev_stb = cram_we || sfile_we || ide_int_stb || (spi_int_stb && bsel); + wire [2:0] dev_bid = device[2:0]; // bidirectional + wire [3:0] dev_uni = device[3:0]; // unidirectional + wire dma_wnr = device[3]; // 0 - device to RAM / 1 - RAM to device + + wire dv_ram = (dev_uni == DEV_RAM) || (dev_uni == DEV_BLT1) || (dev_uni == DEV_BLT2) || (dev_uni == DEV_FIL); + wire dv_blt = (dev_uni == DEV_BLT1) || (dev_uni == DEV_BLT2); + wire dv_fil = (dev_uni == DEV_FIL); + wire dv_spi = (dev_bid == DEV_SPI); + wire dv_ide = (dev_bid == DEV_IDE); + wire dv_crm = (dev_uni == DEV_CRM); + wire dv_sfl = (dev_uni == DEV_SFL); - wire spi_int_stb = dv_spi && spi_stb; - wire spi_int_start = dv_spi && spi_start; - wire ide_int_stb = dv_ide && ide_stb; - assign cram_we = dev_req && dv_crm && state_wr; - assign sfile_we = dev_req && dv_sfl && state_wr; + wire dev_req = dma_act && state_dev; + wire dev_stb = cram_we || sfile_we || ide_int_stb || (spi_int_stb && bsel && dma_act); + + assign cram_we = dev_req && dv_crm && state_wr; + assign sfile_we = dev_req && dv_sfl && state_wr; - // SPI - assign spi_wrdata = {8{state_rd}} | (bsel ? data[15:8] : data[7:0]); // send FF on read cycles - assign spi_req = dev_req && dv_spi; + // SPI + wire spi_int_stb = dv_spi && spi_stb; + assign spi_wrdata = {8{state_rd}} | (bsel ? data[15:8] : data[7:0]); // send FF on read cycles + assign spi_req = dev_req && dv_spi; + + // IDE + wire ide_int_stb = dv_ide && ide_stb; + assign ide_out = data; + assign ide_req = dev_req && dv_ide; + assign ide_rnw = state_rd; - // IDE - assign ide_out = data; - assign ide_req = dev_req && dv_ide; - assign ide_rnw = state_rd; - - // blitter - wire [15:0] blt_rddata = {blt_data_h, blt_data_l}; - wire [7:0] blt_data_h = dma_asz ? blt_data32 : {blt_data3, blt_data2}; - wire [7:0] blt_data_l = dma_asz ? blt_data10 : {blt_data1, blt_data0}; - wire [7:0] blt_data32 = |data[15:8] ? data[15:8] : dram_rddata[15:8]; - wire [7:0] blt_data10 = |data[7:0] ? data[7:0] : dram_rddata[7:0]; - wire [3:0] blt_data3 = |data[15:12] ? data[15:12] : dram_rddata[15:12]; - wire [3:0] blt_data2 = |data[11:8] ? data[11:8] : dram_rddata[11:8]; - wire [3:0] blt_data1 = |data[7:4] ? data[7:4] : dram_rddata[7:4]; - wire [3:0] blt_data0 = |data[3:0] ? data[3:0] : dram_rddata[3:0]; + // blitter + wire [15:0] blt_rddata = (dev_uni == DEV_BLT1) ? blt1_rddata : blt2_rddata; + + // Mode 1 + wire [15:0] blt1_rddata = {blt1_data_h, blt1_data_l}; + wire [7:0] blt1_data_h = dma_asz ? blt1_data32 : {blt1_data3, blt1_data2}; + wire [7:0] blt1_data_l = dma_asz ? blt1_data10 : {blt1_data1, blt1_data0}; + wire [7:0] blt1_data32 = |data[15:8] ? data[15:8] : dram_rddata[15:8]; + wire [7:0] blt1_data10 = |data[7:0] ? data[7:0] : dram_rddata[7:0]; + wire [3:0] blt1_data3 = |data[15:12] ? data[15:12] : dram_rddata[15:12]; + wire [3:0] blt1_data2 = |data[11:8] ? data[11:8] : dram_rddata[11:8]; + wire [3:0] blt1_data1 = |data[7:4] ? data[7:4] : dram_rddata[7:4]; + wire [3:0] blt1_data0 = |data[3:0] ? data[3:0] : dram_rddata[3:0]; + + // Mode 2 + wire [15:0] blt2_rddata = {blt2_data_1, blt2_data_0}; + wire [7:0] blt2_data_1 = dma_asz ? blt2_8_data1 : {blt2_4_data3, blt2_4_data2}; + wire [7:0] blt2_data_0 = dma_asz ? blt2_8_data0 : {blt2_4_data1, blt2_4_data0}; + + localparam msk = 8'd255; + + wire [8:0] sum80 = data[7:0] + dram_rddata[7:0]; + wire [8:0] sum81 = data[15:8] + dram_rddata[15:8]; + + wire [4:0] sum40 = data[3:0] + dram_rddata[3:0]; + wire [4:0] sum41 = data[7:4] + dram_rddata[7:4]; + wire [4:0] sum42 = data[11:8] + dram_rddata[11:8]; + wire [4:0] sum43 = data[15:12] + dram_rddata[15:12]; + + wire [7:0] blt2_8_data0 = ((sum80 > msk) && dma_opt) ? msk : sum80[7:0]; + wire [7:0] blt2_8_data1 = ((sum81 > msk) && dma_opt) ? msk : sum81[7:0]; + + wire [3:0] blt2_4_data0 = ((sum40 > msk[3:0]) && dma_opt) ? msk[3:0] : sum40[3:0]; + wire [3:0] blt2_4_data1 = ((sum41 > msk[3:0]) && dma_opt) ? msk[3:0] : sum41[3:0]; + wire [3:0] blt2_4_data2 = ((sum42 > msk[3:0]) && dma_opt) ? msk[3:0] : sum42[3:0]; + wire [3:0] blt2_4_data3 = ((sum43 > msk[3:0]) && dma_opt) ? msk[3:0] : sum43[3:0]; // data aquiring - always @(posedge clk) - if (state_rd) - begin - if (dram_next) - data <= (dv_blt && phase_blt) ? blt_rddata : dram_rddata; + always @(posedge clk) + if (state_rd) + begin + if (dram_next) + data <= (dv_blt && phase_blt) ? blt_rddata : dram_rddata; - if (ide_int_stb) - data <= ide_in; + if (ide_int_stb) + data <= ide_in; - if (spi_int_start) // data that is already read from SPI, just get it - begin - if (bsel) - data[15:8] <= spi_rddata; - else - data[7:0] <= spi_rddata; - end - end + if (spi_int_stb) + begin + if (bsel) + data[15:8] <= spi_rddata; + else + data[7:0] <= spi_rddata; + end + + end // states - wire state_rd = ~phase; - wire state_wr = phase; - wire state_dev = !dv_ram && (dma_wnr ^ !phase); - wire state_mem = dv_ram || (dma_wnr ^ phase); - + wire state_rd = ~phase; + wire state_wr = phase; + wire state_dev = !dv_ram && (dma_wnr ^ !phase); + wire state_mem = dv_ram || (dma_wnr ^ phase); + // states processing - wire phase_end = phase_end_ram || phase_end_dev; - wire phase_end_ram = state_mem && dram_next && !blt_hook; - wire phase_end_dev = state_dev && dev_stb; - wire blt_hook = dv_blt && !phase_blt && !phase; - wire fil_hook = dv_fil && phase; - wire phase_blt_end = state_mem && dram_next && !phase; + wire phase_end = phase_end_ram || phase_end_dev; + wire phase_end_ram = state_mem && dram_next && !blt_hook; + wire phase_end_dev = state_dev && dev_stb; + wire blt_hook = dv_blt && !phase_blt && !phase; + wire fil_hook = dv_fil && phase; + wire phase_blt_end = state_mem && dram_next && !phase; - // blitter cycles: - // phase phase_blt blt_hook activity - // 0 0 1 read src - // 0 1 0 read dst - // 1 1 0 write dst - - reg [2:0] device; - reg dma_wnr; // 0 - device to RAM / 1 - RAM to device - reg dma_salgn; - reg dma_dalgn; - reg dma_asz; - reg phase; // 0 - read / 1 - write - reg phase_blt; // 0 - source / 1 - destination - reg bsel; // 0 - lsb / 1 - msb + // blitter cycles: + // phase phase_blt blt_hook activity + // 0 0 1 read src + // 0 1 0 read dst + // 1 1 0 write dst - always @(posedge clk) - if (dma_launch) // write to DMACtrl - launch of DMA burst - begin - dma_wnr <= zdata[7]; - dma_z80_lp <= zdata[6]; - dma_salgn <= zdata[5]; - dma_dalgn <= zdata[4]; - dma_asz <= zdata[3]; - device <= zdata[2:0]; - phase <= 1'b0; - phase_blt <= 1'b0; - bsel <= 1'b0; - end + reg [3:0] device; + reg dma_salgn; + reg dma_dalgn; + reg dma_asz; + reg phase; // 0 - read / 1 - write + reg phase_blt; // 0 - source / 1 - destination + reg bsel; // 0 - lsb / 1 - msb + reg dma_opt; - else - begin - if (phase_end && !fil_hook) - phase <= ~phase; - if (phase_blt_end) - phase_blt <= ~phase_blt; - if (spi_int_stb) - bsel <= ~bsel; - end + always @(posedge clk) + if (dma_launch) // write to DMACtrl - launch of DMA burst + begin + dma_opt <= zdata[6]; + dma_salgn <= zdata[5]; + dma_dalgn <= zdata[4]; + dma_asz <= zdata[3]; + device <= {zdata[7], zdata[2:0]}; + phase <= 1'b0; + phase_blt <= 1'b0; + bsel <= 1'b0; + end + + else + begin + if (phase_end && !fil_hook) + phase <= ~phase; + if (phase_blt_end) + phase_blt <= ~phase_blt; + if (spi_int_stb) + bsel <= ~bsel; + end // counter processing - reg [7:0] b_len; // length of burst - reg [7:0] b_num; // number of bursts - reg [7:0] b_ctr; // counter for cycles in burst - reg [8:0] n_ctr; // counter for bursts + reg [7:0] b_len; // length of burst + reg [7:0] b_num; // number of bursts + reg [8:0] n_ctr; // counter for bursts + wire [8:0] n_ctr_dec = n_ctr - next_burst; + assign dma_act = !n_ctr[8]; + reg [7:0] b_ctr; // counter for cycles in burst - assign dma_act = ~n_ctr[8]; - wire [7:0] b_ctr_next = next_burst ? b_len : b_ctr_dec[7:0]; - wire [8:0] b_ctr_dec = {1'b0, b_ctr[7:0]} - 9'b1; - wire [8:0] n_ctr_dec = n_ctr - next_burst; - wire next_burst = b_ctr_dec[8]; + wire [7:0] b_ctr_next = next_burst ? b_len : b_ctr_dec[7:0]; + wire [8:0] b_ctr_dec = {1'b0, b_ctr[7:0]} - 9'b1; + wire next_burst = b_ctr_dec[8]; - always @(posedge clk) - if (reset) - n_ctr[8] <= 1'b1; // disable DMA on RESET + always @(posedge clk) + if (reset) + n_ctr[8] <= 1'b1; - else - if (dma_launch) // launch of DMA burst - begin - b_ctr <= b_len; - n_ctr <= {1'b0, b_num}; - end + else if (dma_launch) + begin + b_ctr <= b_len; + n_ctr <= {1'b0, b_num}; + end - else if (phase && phase_end) // cycle processed - begin - b_ctr <= b_ctr_next; - n_ctr <= n_ctr_dec; - end + else if (phase && phase_end) // cycle processed + begin + b_ctr <= b_ctr_next; + n_ctr <= n_ctr_dec; + end // loading of burst parameters - always @(posedge clk) - begin - if (dma_len) - b_len <= zdata; + always @(posedge clk) + begin + if (dma_len) + b_len <= zdata; - if (dma_num) - b_num <= zdata; - end + if (dma_num) + b_num <= zdata; + end // address processing - // source - wire [20:0] s_addr_next = {s_addr_next_h[13:1], s_addr_next_m, s_addr_next_l[6:0]}; - wire [13:0] s_addr_next_h = s_addr[20:7] + s_addr_add_h; - wire [1:0] s_addr_add_h = dma_salgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {s_addr_inc_l[8], 1'b0}; - wire s_addr_next_m = dma_salgn ? (dma_asz ? s_addr_next_l[7] : s_addr_next_h[0]) : s_addr_inc_l[7]; - wire [7:0] s_addr_next_l = (dma_salgn && next_burst) ? s_addr_r : s_addr_inc_l[7:0]; - wire [8:0] s_addr_inc_l = {1'b0, s_addr[7:0]} + 9'b1; + // source + wire [20:0] s_addr_next = {s_addr_next_h[13:1], s_addr_next_m, s_addr_next_l[6:0]}; + wire [13:0] s_addr_next_h = s_addr[20:7] + s_addr_add_h; + wire [1:0] s_addr_add_h = dma_salgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {s_addr_inc_l[8], 1'b0}; + wire s_addr_next_m = dma_salgn ? (dma_asz ? s_addr_next_l[7] : s_addr_next_h[0]) : s_addr_inc_l[7]; + wire [7:0] s_addr_next_l = (dma_salgn && next_burst) ? s_addr_r : s_addr_inc_l[7:0]; + wire [8:0] s_addr_inc_l = {1'b0, s_addr[7:0]} + 9'b1; - reg [20:0] s_addr; // current source address - reg [7:0] s_addr_r; // source lower address + reg [20:0] s_addr; // current source address + reg [7:0] s_addr_r; // source lower address - always @(posedge clk) - if ((dram_next || dev_stb) && state_rd && (!dv_blt || !phase_blt)) // increment RAM source addr - s_addr <= s_addr_next; + always @(posedge clk) + if ((dram_next || dev_stb) && state_rd && (!dv_blt || !phase_blt)) // increment RAM source addr + s_addr <= s_addr_next; - else - begin - if (dma_saddrl) - begin - s_addr[6:0] <= zdata[7:1]; - s_addr_r[6:0] <= zdata[7:1]; - end + else + begin + if (dma_saddrl) + begin + s_addr[6:0] <= zdata[7:1]; + s_addr_r[6:0] <= zdata[7:1]; + end - if (dma_saddrh) - begin - s_addr[12:7] <= zdata[5:0]; - s_addr_r[7] <= zdata[0]; - end + if (dma_saddrh) + begin + s_addr[12:7] <= zdata[5:0]; + s_addr_r[7] <= zdata[0]; + end - if (dma_saddrx) - s_addr[20:13] <= zdata; - end + if (dma_saddrx) + s_addr[20:13] <= zdata; + end - // destination - wire [20:0] d_addr_next = {d_addr_next_h[13:1], d_addr_next_m, d_addr_next_l[6:0]}; - wire [13:0] d_addr_next_h = d_addr[20:7] + d_addr_add_h; - wire [1:0] d_addr_add_h = dma_dalgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {d_addr_inc_l[8], 1'b0}; - wire d_addr_next_m = dma_dalgn ? (dma_asz ? d_addr_next_l[7] : d_addr_next_h[0]) : d_addr_inc_l[7]; - wire [7:0] d_addr_next_l = (dma_dalgn && next_burst) ? d_addr_r : d_addr_inc_l[7:0]; - wire [8:0] d_addr_inc_l = {1'b0, d_addr[7:0]} + 9'b1; + // destination + wire [20:0] d_addr_next = {d_addr_next_h[13:1], d_addr_next_m, d_addr_next_l[6:0]}; + wire [13:0] d_addr_next_h = d_addr[20:7] + d_addr_add_h; + wire [1:0] d_addr_add_h = dma_dalgn ? {next_burst && dma_asz, next_burst && !dma_asz} : {d_addr_inc_l[8], 1'b0}; + wire d_addr_next_m = dma_dalgn ? (dma_asz ? d_addr_next_l[7] : d_addr_next_h[0]) : d_addr_inc_l[7]; + wire [7:0] d_addr_next_l = (dma_dalgn && next_burst) ? d_addr_r : d_addr_inc_l[7:0]; + wire [8:0] d_addr_inc_l = {1'b0, d_addr[7:0]} + 9'b1; - reg [20:0] d_addr; // current dest address - reg [7:0] d_addr_r; // dest lower address + reg [20:0] d_addr; // current dest address + reg [7:0] d_addr_r; // dest lower address - always @(posedge clk) - if ((dram_next || dev_stb) && state_wr) // increment RAM dest addr - d_addr <= d_addr_next; - else - begin - if (dma_daddrl) - begin - d_addr[6:0] <= zdata[7:1]; - d_addr_r[6:0] <= zdata[7:1]; - end + always @(posedge clk) + if ((dram_next || dev_stb) && state_wr) // increment RAM dest addr + d_addr <= d_addr_next; + else + begin + if (dma_daddrl) + begin + d_addr[6:0] <= zdata[7:1]; + d_addr_r[6:0] <= zdata[7:1]; + end - if (dma_daddrh) - begin - d_addr[12:7] <= zdata[5:0]; - d_addr_r[7] <= zdata[0]; - end + if (dma_daddrh) + begin + d_addr[12:7] <= zdata[5:0]; + d_addr_r[7] <= zdata[0]; + end - if (dma_daddrx) - d_addr[20:13] <= zdata; - end + if (dma_daddrx) + d_addr[20:13] <= zdata; + end - // INT generation - reg dma_act_r; - always @(posedge clk) - dma_act_r <= dma_act; + // INT generation + reg dma_act_r; + always @(posedge clk) + dma_act_r <= dma_act && ~reset; + + assign int_start = !dma_act && dma_act_r; - assign int_start = !dma_act && dma_act_r; - endmodule diff --git a/src/spi.v b/src/spi.v index 152c44e..6101191 100644 --- a/src/spi.v +++ b/src/spi.v @@ -20,8 +20,6 @@ // data from sdi is latched by master on positive edge of sck, while slave changes it on falling edge. // WARNING: slave must emit valid di7 bit BEFORE first pulse on sck! // -// bsync is 1 while do7 is outting, otherwise it is 0 -// // start is synchronous pulse, which starts all transfer and also latches din data on the same clk edge // as it is registered high. start can be given anytime (only when speed=0), // so it is functioning then as synchronous reset. when speed!=0, there is global enable for majority of @@ -31,117 +29,60 @@ // latching last bit on sdi. // // sdo emits last bit shifted out after the transfer end -// -// when speed=0, data transfer rate could be as fast as one byte every 16 clk pulses. To achieve that, -// start must be pulsed high simultaneously with the last high pulse of sck -// -// speed[1:0] determines Fclk/Fspi -// -// speed | Fclk/Fspi -// ------+---------- -// 2'b00 | 2 -// 2'b01 | 4 -// 2'b10 | 8 -// 2'b11 | 16 -// -// for speed=0 you can start new transfer as fast as every 16 clks -// for speed=1 - every 34 clks. -// alternatively, you can check rdy output: it goes to 0 after start pulse and when it goes back to 1, you can -// issue another start at the next clk cycle. See spi2_modelled.png and .zip (modelsim project) -// -// warning: if using rdy-driven transfers and speed=0, new transfer will be started every 18 clks. -// it is recommended to use rdy-driven transfers when speed!=0 -// -// warning: this module does not contain asynchronous reset. Provided clk is stable, start=0 -// and speed=0, module returns to initial ready state after maximum of 18+8=26 clks. To reset module -// to the known state from any operational state, set speed=0 and start=1 for 8 clks -// (that starts Fclk/Fspi=2 speed transfer for sure), then remain start=0, speed=0 for at least 18 clks. -module spi +module spi ( -// SPI wires - input wire clk, // system clk - output wire sck, // SPI bus pins... - output wire sdo, // - input wire sdi, // + // SPI wires + input clk, // system clock + output sck, // SCK + output reg sdo, // MOSI + input sdi, // MISO -// controls - output wire stb, // ready strobe, 1 clock length - output wire start, // start strobe, 1 clock length - output reg bsync, // for vs1001 + // DMA interface + input dma_req, + input [7:0] dma_din, -// DMA interface - input wire dma_req, - input wire [7:0] dma_din, + // Z80 interface + input cpu_req, + input [7:0] cpu_din, -// Z80 interface - input wire cpu_req, - input wire [7:0] cpu_din, - output reg [7:0] dout, - -// configuration - input wire [1:0] speed // =0 - sck full speed (1/2 of clk), =1 - half (1/4 of clk), =2 - one fourth (1/8 of clk), =3 - one eighth (1/16 of clk) + // output + output start, // start strobe, 1 clock length + output reg [7:0] dout ); -wire req = cpu_req || dma_req; -wire [7:0] din = dma_req ? dma_din : cpu_din; - -// sdo is high bit of shiftout -assign sdo = shiftout[7]; -wire ena_shout_load = (start || sck) & g_ena; // enable load of shiftout register assign sck = counter[0]; -wire rdy = counter[4]; // =0 when transmission in progress -assign stb = stb_r && !rdy; assign start = req && rdy; -reg [6:0] shiftin; // shifting in data from sdi before emitting it on dout -reg [4:0] counter; // handles transmission -reg stb_r; +wire [7:0] din = dma_req ? dma_din : cpu_din; +wire rdy = counter[4]; // 0 - transmission in progress +wire req = cpu_req || dma_req; + +reg [4:0] counter; always @(posedge clk) begin - if (g_ena) begin - if (start) begin - counter <= 5'b0; // rdy = 0; sck = 0; - bsync <= 1'b1; // begin bsync pulse - stb_r <= 1'b0; + reg [7:0] shift; + + if (start) begin + counter <= 5'b0; + sdo <= din[7]; + shift[7:1] <= din[6:0]; + end + else if (!rdy) begin + counter <= counter + 5'd1; + + // shift in (rising edge of SCK) + if (!sck) begin + shift[0] <= sdi; + + if (&counter[3:1]) dout <= {shift[7:1], sdi}; end - else begin - if (!sck) begin // on the rising edge of sck - shiftin[6:0] <= {shiftin[5:0], sdi}; - if (&counter[3:1] && !rdy) begin - dout <= {shiftin[6:0], sdi}; // update dout at the last sck rising edge - stb_r <= 1'b1; - end - end - else begin // on the falling edge of sck - bsync <= 1'b0; - end - if (!rdy) counter <= counter + 5'd1; + + // shift out (falling edge of sck) + if (sck) begin + sdo <= shift[7]; + shift[7:1] <= shift[6:0]; // last bit remains after end of exchange end end end - -// shiftout treatment is done so just to save LCELLs in acex1k -reg [7:0] shiftout; // shifting out data to the sdo -always @(posedge clk) begin - if (ena_shout_load) begin - if (start) shiftout <= din; - else shiftout[7:0] <= {shiftout[6:0], shiftout[0]}; // last bit remains after end of exchange - end -end - -// slow speeds - controlled by g_ena -reg [2:0] wcnt; -always @(posedge clk) begin - if (|speed) begin - if (start) wcnt <= 1; - else if (rdy) wcnt <= 0; - else wcnt <= wcnt + 1'd1; - end - else wcnt <= 0; -end - -wire [3:0] g_en = {~|wcnt[2:0], ~|wcnt[1:0], ~|wcnt[0], 1'b1}; -wire g_ena = g_en[speed]; - endmodule diff --git a/src/tsconf.v b/src/tsconf.v index 2a5bd8a..c4788a0 100644 --- a/src/tsconf.v +++ b/src/tsconf.v @@ -273,7 +273,6 @@ wire tm_next; // DMA wire dma_rnw; wire dma_req; -wire dma_z80_lp; wire [15:0] dma_wrdata; wire [20:0] dma_addr; wire dma_next; @@ -286,7 +285,6 @@ wire [15:0] dma_data; wire [7:0] dma_wraddr; wire int_start_dma; // SPI -wire spi_stb; wire spi_start; wire dma_spi_req; wire [7:0] dma_spi_din; @@ -529,7 +527,6 @@ arbiter TS07 .dma_addr({3'b000, dma_addr}), .dma_wrdata(dma_wrdata), .dma_req(dma_req), - .dma_z80_lp(dma_z80_lp), .dma_rnw(dma_rnw), .dma_next(dma_next), .ts_addr({3'b000, ts_addr}), @@ -629,14 +626,12 @@ dma TS09 .dram_rddata(sdr_do_bus_16), .dram_wrdata(dma_wrdata), .dram_req(dma_req), - .dma_z80_lp(dma_z80_lp), .dram_rnw(dma_rnw), .dram_next(dma_next), .spi_rddata(spi_dout), .spi_wrdata(dma_spi_din), .spi_req(dma_spi_req), - .spi_stb(spi_stb), - .spi_start(spi_start), + .spi_stb(spi_start), .ide_in(0), .ide_stb(0), .cram_we(dma_cram_we), @@ -666,14 +661,12 @@ spi TS11 .sck(SD_CLK), .sdo(SD_SI), .sdi(SD_SO), - .stb(spi_stb), - .start(spi_start), .dma_req(dma_spi_req), .dma_din(dma_spi_din), .cpu_req(cpu_spi_req), .cpu_din(cpu_spi_din), - .dout(spi_dout), - .speed(0) + .start(spi_start), + .dout(spi_dout) ); zint TS13