diff --git a/cores/spectrum/data_io.v b/cores/spectrum/data_io.v new file mode 100644 index 0000000..08974d6 --- /dev/null +++ b/cores/spectrum/data_io.v @@ -0,0 +1,116 @@ +// +// data_io.v +// +// io controller writable ram for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// 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 . +// + +module data_io #(parameter ADDR_WIDTH=16, START_ADDR = 0) ( + // io controller spi interface + input sck, + input ss, + input sdi, + + output downloading, // signal indicating an active download + output [ADDR_WIDTH-1:0] size, // number of bytes in input buffer + + // external ram interface + input clk, + output reg wr, + output reg [ADDR_WIDTH-1:0] a, + output [7:0] d +); + +assign d = data; +assign size = addr - START_ADDR; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg [6:0] sbuf; +reg [7:0] cmd /* synthesis noprune */; +reg [7:0] data /* synthesis noprune */; +reg [4:0] cnt /* synthesis noprune */; + +reg [ADDR_WIDTH-1:0] addr /* synthesis noprune */; +reg rclk /* synthesis noprune */; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; + +assign downloading = downloading_reg; +reg downloading_reg = 1'b0; + +// data_io has its own SPI interface to the io controller +always@(posedge sck, posedge ss) begin + if(ss == 1'b1) + cnt <= 5'd0; + else begin + rclk <= 1'b0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) + sbuf <= { sbuf[5:0], sdi}; + + // increase target address after write + if(rclk) + addr <= addr + 1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 4'd1; + else cnt <= 4'd8; + + // finished command byte + if(cnt == 7) + cmd <= {sbuf, sdi}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(sdi) begin + addr <= START_ADDR; + downloading_reg <= 1'b1; + end else + downloading_reg <= 1'b0; + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + data <= {sbuf, sdi}; + rclk <= 1'b1; + a <= addr; + end + end +end + +reg rclkD, rclkD2; +always@(posedge clk) begin + // bring rclk from spi clock domain into c64 clock domain + rclkD <= rclk; + rclkD2 <= rclkD; + wr <= 1'b0; + + if(rclkD && !rclkD2) + wr <= 1'b1; +end + +endmodule \ No newline at end of file diff --git a/cores/spectrum/sigma_delta_dac.v b/cores/spectrum/sigma_delta_dac.v new file mode 100644 index 0000000..5eb8049 --- /dev/null +++ b/cores/spectrum/sigma_delta_dac.v @@ -0,0 +1,32 @@ +module sigma_delta_dac( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +parameter MSBI = 7; + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @ (*) + DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); + +always @(*) + DeltaAdder = DACin + DeltaB; + +always @(*) + SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= 1'b0; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2]; + end +endmodule \ No newline at end of file diff --git a/cores/spectrum/tape.v b/cores/spectrum/tape.v new file mode 100644 index 0000000..dbfcd52 --- /dev/null +++ b/cores/spectrum/tape.v @@ -0,0 +1,137 @@ +// +// tape.v +// +// tape implementation for the spectrum core for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// 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 . +// +// This reads a CSW1 file as described here: +// http://ramsoft.bbk.org.omegahg.com/csw.html#CSW1FORMAT +// + +// typical header: +// 00000000 43 6f 6d 70 72 65 73 73 65 64 20 53 71 75 61 72 |Compressed Squar| +// 00000010 65 20 57 61 76 65 1a 01 01 44 ac 01 00 00 00 00 |e Wave...D......| + +module tape #(parameter ADDR_WIDTH=16) ( + input reset, + input clk, + input iocycle, + + input downloading, // signal indicating an active download + input [ADDR_WIDTH-1:0] size, // number of bytes in input buffer + + output reg audio_out, + + // external ram interface + output rd, + output [ADDR_WIDTH-1:0] a, + input [7:0] d +); + +reg downloadingD; + +reg [15:0] freq; +reg [5:0] header_cnt; +reg [31:0] clk_play_cnt; +reg [ADDR_WIDTH-1:0] payload_cnt; +reg iocycleD; + +reg [31:0] bit_cnt; +reg [2:0] reload32; + +assign rd = iocycle && ((header_cnt != 0) || (payload_cnt != 0)); +assign a = (header_cnt != 0)?(25'h20000 + 25'd32 - header_cnt): + (payload_cnt != 0)?(25'h20000 + size - payload_cnt): + 25'h12345; + +reg [7:0] din; + +// latch data at end of io cycle +always @(negedge iocycle) + din <= d; + +always @(posedge clk) begin + downloadingD <= downloading; + iocycleD <= iocycle; + + if(reset || downloading) begin + freq <= 16'd1234; + header_cnt <= 6'd0; + payload_cnt <= 25'd0; + reload32 <= 3'd0; + end else begin + + // download complete, start parsing + if(!downloading && downloadingD) + header_cnt <= 6'd32; + + // read header + if((header_cnt != 0) && !iocycle && iocycleD ) begin + + // fetch playback frequency from header + if(header_cnt == 6'h20 - 6'h19) freq[ 7:0] <= din; + if(header_cnt == 6'h20 - 6'h1a) freq[15:8] <= din; + + header_cnt <= header_cnt - 6'd1; + + // start payload transfer as soon as header has been parsed + if(header_cnt == 1) begin + payload_cnt <= size - 25'h20; + bit_cnt <= 32'd1; + end + end + + // read payload + if(payload_cnt != 0) begin + + // bit has fully neem semt or reload32 in progress + if((bit_cnt <= 1) || (reload32 != 0)) begin + + if(!iocycle && iocycleD ) begin + if(reload32 != 0) begin + bit_cnt <= { din, bit_cnt[31:8] }; + reload32 <= reload32 - 3'd1; + end else begin + if(din != 0) begin + // determine length of next bit + bit_cnt <= { 24'd0, din}; + end else + reload32 <= 3'd4; + + // output a bit ... + audio_out <= !audio_out; + end + + payload_cnt <= payload_cnt - 25'd1; + end + end else begin + // generate replay clock + clk_play_cnt <= clk_play_cnt + { 16'h0000, freq}; + // clock is 28MHz + if(clk_play_cnt > 32'd28000000) begin + clk_play_cnt <= clk_play_cnt - 32'd28000000; + + // process bit counter + bit_cnt <= bit_cnt - 32'd1; + end + end + end + end +end + +endmodule