mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-01-28 20:40:43 +00:00
Generic 8 bit file upload
This commit is contained in:
122
cores/zxgate/zx/zx01/data_io.v
Normal file
122
cores/zxgate/zx/zx01/data_io.v
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// data_io.v
|
||||
//
|
||||
// io controller writable ram for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
module data_io (
|
||||
// io controller spi interface
|
||||
input sck,
|
||||
input ss,
|
||||
input sdi,
|
||||
|
||||
output downloading, // signal indicating an active download
|
||||
output [15:0] size, // number of bytes in input buffer
|
||||
|
||||
// cpu ram interface
|
||||
input clk,
|
||||
input we,
|
||||
input [10:0] a,
|
||||
input [8:0] din,
|
||||
output [8:0] dout
|
||||
);
|
||||
|
||||
parameter START_ADDR = 16'h0000;
|
||||
|
||||
assign size = 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 [15: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 + 16'd1;
|
||||
|
||||
// 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;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// include the embedded dual port ram
|
||||
data_io_ram data_io_ram (
|
||||
// wire up cpu port
|
||||
.address_a ( a ),
|
||||
.clock_a ( clk ),
|
||||
.data_a ( din ),
|
||||
.wren_a ( we ),
|
||||
.q_a ( dout ),
|
||||
|
||||
// io controller port
|
||||
.address_b ( addr[10:0] ),
|
||||
.clock_b ( rclk ),
|
||||
.data_b ( {sbuf, sdi} ),
|
||||
.wren_b ( (cmd == UIO_FILE_TX_DAT) && !ss )
|
||||
);
|
||||
|
||||
endmodule
|
||||
244
cores/zxgate/zx/zx01/data_io_ram.v
Normal file
244
cores/zxgate/zx/zx01/data_io_ram.v
Normal file
@@ -0,0 +1,244 @@
|
||||
// megafunction wizard: %RAM: 2-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: data_io_ram.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module data_io_ram (
|
||||
address_a,
|
||||
address_b,
|
||||
clock_a,
|
||||
clock_b,
|
||||
data_a,
|
||||
data_b,
|
||||
wren_a,
|
||||
wren_b,
|
||||
q_a,
|
||||
q_b);
|
||||
|
||||
input [10:0] address_a;
|
||||
input [10:0] address_b;
|
||||
input clock_a;
|
||||
input clock_b;
|
||||
input [7:0] data_a;
|
||||
input [7:0] data_b;
|
||||
input wren_a;
|
||||
input wren_b;
|
||||
output [7:0] q_a;
|
||||
output [7:0] q_b;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clock_a;
|
||||
tri0 wren_a;
|
||||
tri0 wren_b;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] sub_wire1;
|
||||
wire [7:0] q_a = sub_wire0[7:0];
|
||||
wire [7:0] q_b = sub_wire1[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.clock0 (clock_a),
|
||||
.wren_a (wren_a),
|
||||
.address_b (address_b),
|
||||
.clock1 (clock_b),
|
||||
.data_b (data_b),
|
||||
.wren_b (wren_b),
|
||||
.address_a (address_a),
|
||||
.data_a (data_a),
|
||||
.q_a (sub_wire0),
|
||||
.q_b (sub_wire1),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.eccstatus (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1));
|
||||
defparam
|
||||
altsyncram_component.address_reg_b = "CLOCK1",
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_input_b = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_b = "BYPASS",
|
||||
altsyncram_component.indata_reg_b = "CLOCK1",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 2048,
|
||||
altsyncram_component.numwords_b = 2048,
|
||||
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_aclr_b = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "UNREGISTERED",
|
||||
altsyncram_component.outdata_reg_b = "UNREGISTERED",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 11,
|
||||
altsyncram_component.widthad_b = 11,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_b = 8,
|
||||
altsyncram_component.width_byteena_a = 1,
|
||||
altsyncram_component.width_byteena_b = 1,
|
||||
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRdata NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRq NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRrren NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLRwren NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clock NUMERIC "5"
|
||||
// Retrieval info: PRIVATE: Clock_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clock_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "16384"
|
||||
// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING ""
|
||||
// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: REGdata NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: REGq NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: REGrren NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: REGwren NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: VarWidth NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: enable NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "2048"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
|
||||
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "11"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_B NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
|
||||
// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1"
|
||||
// Retrieval info: USED_PORT: address_a 0 0 11 0 INPUT NODEFVAL "address_a[10..0]"
|
||||
// Retrieval info: USED_PORT: address_b 0 0 11 0 INPUT NODEFVAL "address_b[10..0]"
|
||||
// Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT VCC "clock_a"
|
||||
// Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL "clock_b"
|
||||
// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..0]"
|
||||
// Retrieval info: USED_PORT: data_b 0 0 8 0 INPUT NODEFVAL "data_b[7..0]"
|
||||
// Retrieval info: USED_PORT: q_a 0 0 8 0 OUTPUT NODEFVAL "q_a[7..0]"
|
||||
// Retrieval info: USED_PORT: q_b 0 0 8 0 OUTPUT NODEFVAL "q_b[7..0]"
|
||||
// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a"
|
||||
// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 11 0 address_a 0 0 11 0
|
||||
// Retrieval info: CONNECT: @address_b 0 0 11 0 address_b 0 0 11 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0
|
||||
// Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0
|
||||
// Retrieval info: CONNECT: @data_b 0 0 8 0 data_b 0 0 8 0
|
||||
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
|
||||
// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
|
||||
// Retrieval info: CONNECT: q_a 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: CONNECT: q_b 0 0 8 0 @q_b 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL data_io_ram_bb.v TRUE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
212
cores/zxgate/zx/zx01/tape.v
Normal file
212
cores/zxgate/zx/zx01/tape.v
Normal file
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// tape.v
|
||||
//
|
||||
// ZX81 tape implementation for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
module tape(
|
||||
input sck,
|
||||
input ss,
|
||||
input sdi,
|
||||
|
||||
input clk, // 500kHz
|
||||
input play, // "press play on tape"
|
||||
output reg tape_out
|
||||
);
|
||||
|
||||
// create clock to be used for signaltap
|
||||
reg [7:0] tape_clk /* synthesis noprune */;
|
||||
always @(posedge clk)
|
||||
tape_clk <= tape_clk + 8'd1;
|
||||
|
||||
// tape bit timing
|
||||
// 0 bit = /\/\/\/\_________ (4* 150us H + 150us L + 1300us L)
|
||||
// 1 bit = /\/\/\/\/\/\/\/\/\_____________
|
||||
|
||||
// 0 = idle, 1 = 1300us low, 2/4/6/../18 = 150us high, 3/5/7/../19 = 150us L
|
||||
reg [4:0] pulse_state;
|
||||
|
||||
// 150us = 75 cycles @ 500kHz
|
||||
// 1300us = 650 cycles @ 500kHz
|
||||
reg [9:0] pulse_cnt; // 10 bit = 1024 max range
|
||||
|
||||
reg bit_done;
|
||||
|
||||
// generate bit timing
|
||||
always @(posedge clk) begin
|
||||
bit_done <= 1'b0;
|
||||
|
||||
if(pulse_cnt == 0) begin
|
||||
// end of idle state, start new bit
|
||||
if(pulse_state == 0) begin
|
||||
if(bit_start) begin
|
||||
tape_out <= 1'b1;
|
||||
pulse_state <= bit?5'd19:5'd9;
|
||||
pulse_cnt <= 10'd74;
|
||||
end
|
||||
end
|
||||
|
||||
// end of 1300us seperator phase
|
||||
else if(pulse_state == 1) begin
|
||||
tape_out <= 1'b0;
|
||||
pulse_state <= 5'd0;
|
||||
pulse_cnt <= 10'd0;
|
||||
bit_done <= 1'b1;
|
||||
end
|
||||
|
||||
// end of last high phase
|
||||
else if(pulse_state == 2) begin
|
||||
tape_out <= 1'b0;
|
||||
pulse_state <= 5'd1;
|
||||
pulse_cnt <= 10'd649;
|
||||
end
|
||||
|
||||
// end of normal pulse hi/lo phase
|
||||
else if(pulse_state > 2) begin
|
||||
// tape level is 1 when coming from state 4,6,8,...
|
||||
tape_out <= !pulse_state[0];
|
||||
pulse_state <= pulse_state - 5'd1;
|
||||
pulse_cnt <= 10'd74;
|
||||
end
|
||||
|
||||
end else
|
||||
pulse_cnt <= pulse_cnt - 10'd1;
|
||||
end
|
||||
|
||||
// bring play signal into local clock domain and
|
||||
// generate start signal from it
|
||||
reg start;
|
||||
reg playD, playD2;
|
||||
always @(posedge clk) begin
|
||||
start <= 1'b0;
|
||||
playD <= play;
|
||||
playD2 <= playD;
|
||||
|
||||
if(playD && !playD2)
|
||||
start <= 1'b1;
|
||||
end
|
||||
|
||||
// byte transmitter
|
||||
wire bit = byte[bit_cnt];
|
||||
|
||||
// reg [7:0] byte = 8'h55 /* synthesis noprune */;
|
||||
reg [2:0] bit_cnt;
|
||||
reg byte_tx_running = 1'b0;
|
||||
reg bit_in_progress;
|
||||
reg bit_start;
|
||||
|
||||
reg byte_done;
|
||||
|
||||
always @(posedge clk) begin
|
||||
bit_start <= 1'b0;
|
||||
byte_done <= 1'b0;
|
||||
|
||||
// start signal starts a new byte transmission
|
||||
if(!byte_tx_running) begin
|
||||
if(byte_start) begin
|
||||
byte_tx_running <= 1'b1;
|
||||
bit_in_progress <= 1'b0;
|
||||
bit_cnt <= 3'd7;
|
||||
end
|
||||
end else begin
|
||||
// byte transmission in progress
|
||||
|
||||
if(!bit_in_progress) begin
|
||||
// start new bit
|
||||
bit_start <= 1'b1;
|
||||
bit_in_progress <= 1'b1;
|
||||
end else begin
|
||||
// wait for bit transmission to finish
|
||||
if(bit_done) begin
|
||||
bit_in_progress <= 1'b0;
|
||||
|
||||
if(bit_cnt != 0)
|
||||
bit_cnt <= bit_cnt - 3'd1;
|
||||
else begin
|
||||
byte_tx_running <= 1'b0;
|
||||
byte_done <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// byte tx engine
|
||||
reg [15:0] byte_count;
|
||||
|
||||
// 0=idle, 1=filename, 2=file
|
||||
reg [1:0] byte_state = 2'd0;
|
||||
|
||||
reg byte_start;
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
byte_start <= 1'b0;
|
||||
|
||||
if(byte_state == 0) begin
|
||||
// start transmission if user presses "play". don't do anything if
|
||||
// there's no tape data in the buffer
|
||||
if(start && (file_size != 0)) begin
|
||||
byte_state <= 2'd1;
|
||||
|
||||
// transmit the "file name"
|
||||
byte_start <= 1'b1;
|
||||
end
|
||||
end else if(byte_state == 1) begin
|
||||
if(byte_done) begin
|
||||
byte_state <= 2'd2;
|
||||
byte_start <= 1'b1;
|
||||
byte_count <= 16'h0000;
|
||||
end
|
||||
|
||||
end else if(byte_state == 2) begin
|
||||
if(byte_done) begin
|
||||
if(byte_count != file_size - 16'd1) begin
|
||||
byte_count <= byte_count + 16'd1;
|
||||
byte_start <= 1'b1;
|
||||
end else
|
||||
byte_state <= 2'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [7:0] filename = { 1'b1, 7'h3f}; // 'Z' with end flag
|
||||
wire [7:0] byte = (byte_state == 1)?filename:ram_data_out;
|
||||
wire [7:0] ram_data_out;
|
||||
|
||||
wire [15:0] file_size;
|
||||
|
||||
// include the io controller connected ram
|
||||
data_io data_io (
|
||||
.sck ( sck ),
|
||||
.ss ( ss ),
|
||||
.sdi ( sdi ),
|
||||
|
||||
.downloading ( ),
|
||||
.size ( file_size ),
|
||||
|
||||
// ram interface
|
||||
.clk ( clk ),
|
||||
.we ( 1'b0 ),
|
||||
.a ( byte_count[10:0] ),
|
||||
.din ( 8'h00 ),
|
||||
.dout ( ram_data_out )
|
||||
);
|
||||
|
||||
endmodule
|
||||
@@ -1,4 +1,24 @@
|
||||
// MiST user_io
|
||||
//
|
||||
// user_io.v
|
||||
//
|
||||
// user_io for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
module user_io(
|
||||
input SPI_CLK,
|
||||
@@ -6,21 +26,27 @@ module user_io(
|
||||
output reg SPI_MISO,
|
||||
input SPI_MOSI,
|
||||
|
||||
input [7:0] CORE_TYPE,
|
||||
|
||||
output [5:0] JOY0,
|
||||
output [5:0] JOY1,
|
||||
output [1:0] BUTTONS,
|
||||
output [1:0] SWITCHES,
|
||||
|
||||
output reg [7:0] status,
|
||||
|
||||
input clk,
|
||||
output ps2_clk,
|
||||
output reg ps2_data
|
||||
);
|
||||
|
||||
// config string, it is assumed that any core returning a string here
|
||||
// also supports the OSD
|
||||
// 0123456789abcdef
|
||||
wire [127:0] name = "ZX01;P; ";
|
||||
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [4:0] cnt;
|
||||
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||||
reg [5:0] byte_cnt; // counts bytes
|
||||
reg [5:0] joystick0;
|
||||
reg [5:0] joystick1;
|
||||
reg [3:0] but_sw;
|
||||
@@ -29,16 +55,28 @@ assign JOY0 = joystick0;
|
||||
assign JOY1 = joystick1;
|
||||
assign BUTTONS = but_sw[1:0];
|
||||
assign SWITCHES = but_sw[3:2];
|
||||
|
||||
|
||||
// this variant of user_io is for 8 bit cores (type == a4) only
|
||||
wire [7:0] core_type = 8'ha4;
|
||||
|
||||
// drive MISO only when transmitting core id
|
||||
always@(negedge SPI_CLK or posedge SPI_SS_IO) begin
|
||||
if(SPI_SS_IO == 1) begin
|
||||
SPI_MISO <= 1'bZ;
|
||||
end else begin
|
||||
if(cnt < 8) begin
|
||||
SPI_MISO <= CORE_TYPE[7-cnt];
|
||||
// first byte returned is always core type, further bytes are
|
||||
// command dependent
|
||||
if(byte_cnt == 0) begin
|
||||
SPI_MISO <= core_type[~bit_cnt];
|
||||
end else begin
|
||||
SPI_MISO <= 1'bZ;
|
||||
// reading config string
|
||||
if(cmd == 8'h14) begin
|
||||
// returning a byte from string
|
||||
if(byte_cnt < 6'd17)
|
||||
SPI_MISO <= name[{~(byte_cnt-6'd1),~bit_cnt}];
|
||||
else
|
||||
SPI_MISO <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -56,7 +94,6 @@ reg ps2_parity;
|
||||
|
||||
assign ps2_clk = clk || (ps2_tx_state == 0);
|
||||
|
||||
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_r_inc;
|
||||
@@ -111,42 +148,42 @@ always@(posedge clk) begin
|
||||
end
|
||||
|
||||
// SPI receiver
|
||||
//reg ps2_w_inc;
|
||||
always@(posedge SPI_CLK or posedge SPI_SS_IO) begin
|
||||
// ps2_w_inc <= 1'b0;
|
||||
// if(ps2_w_inc)
|
||||
// ps2_wptr <= ps2_wptr + 1;
|
||||
|
||||
if(SPI_SS_IO == 1) begin
|
||||
cnt <= 1'b0;
|
||||
bit_cnt <= 3'd0;
|
||||
byte_cnt <= 5'd0;
|
||||
end else begin
|
||||
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
|
||||
// counter counts 0-7, 8-15, 8-15 ...
|
||||
// 0-7 is command, 8-15 is payload
|
||||
if(cnt != 15) cnt <= cnt + 4'd1;
|
||||
else cnt <= 4'd8;
|
||||
bit_cnt <= bit_cnt + 3'd1;
|
||||
if(bit_cnt == 7) byte_cnt <= byte_cnt + 5'd1;
|
||||
|
||||
// finished reading command byte
|
||||
if(cnt == 7)
|
||||
cmd <= { sbuf, SPI_MOSI};
|
||||
if(bit_cnt == 7) begin
|
||||
if(byte_cnt == 0)
|
||||
cmd <= { sbuf, SPI_MOSI};
|
||||
|
||||
if(cnt == 15) begin
|
||||
if(cmd == 1)
|
||||
but_sw <= { sbuf[2:0], SPI_MOSI };
|
||||
if(byte_cnt != 0) begin
|
||||
if(cmd == 8'h01)
|
||||
but_sw <= { sbuf[2:0], SPI_MOSI };
|
||||
|
||||
if(cmd == 2)
|
||||
joystick0 <= { sbuf[4:0], SPI_MOSI };
|
||||
if(cmd == 8'h02)
|
||||
joystick0 <= { sbuf[4:0], SPI_MOSI };
|
||||
|
||||
if(cmd == 3)
|
||||
joystick1 <= { sbuf[4:0], SPI_MOSI };
|
||||
if(cmd == 8'h03)
|
||||
joystick1 <= { sbuf[4:0], SPI_MOSI };
|
||||
|
||||
if(cmd == 5) begin
|
||||
// store incoming keyboard bytes in
|
||||
ps2_fifo[ps2_wptr] <= { sbuf, SPI_MOSI };
|
||||
ps2_wptr <= ps2_wptr + 1;
|
||||
end
|
||||
if(cmd == 8'h05) begin
|
||||
// store incoming keyboard bytes in
|
||||
ps2_fifo[ps2_wptr] <= { sbuf, SPI_MOSI };
|
||||
ps2_wptr <= ps2_wptr + 1;
|
||||
end
|
||||
|
||||
end
|
||||
if(cmd == 8'h15) begin
|
||||
status <= { sbuf[4:0], SPI_MOSI };
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -287,8 +287,11 @@ set_global_assignment -name ENABLE_NCE_PIN OFF
|
||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name ENABLE_SIGNALTAP ON
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE stp1.stp
|
||||
set_global_assignment -name VERILOG_FILE tape.v
|
||||
set_global_assignment -name VERILOG_FILE data_io_ram.v
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
set_global_assignment -name VERILOG_FILE osd.v
|
||||
set_global_assignment -name VERILOG_FILE user_io.v
|
||||
set_global_assignment -name QIP_FILE clock.qip
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
|
||||
|
||||
// Changes done to zx01/zx97 code:
|
||||
// - removed open state from video in zx01.vhd
|
||||
// - Use rom megafunction for zx81 rom (replaced rom81XXXX.vhd by single rom81.vhd)
|
||||
//
|
||||
// zx01_mist.v
|
||||
//
|
||||
// zx01/zx81 toplevel for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
module zx01_mist (
|
||||
// clock inputsxque
|
||||
@@ -48,13 +64,13 @@ assign SDRAM_nCS = 1'b1; // disable ram
|
||||
// reset geenration
|
||||
reg [7:0] reset_cnt;
|
||||
always @(posedge clk) begin
|
||||
if(!pll_locked)
|
||||
if(!pll_locked || status[0])
|
||||
reset_cnt <= 8'h0;
|
||||
else if(reset_cnt != 8'd255)
|
||||
reset_cnt <= reset_cnt + 8'd1;
|
||||
end
|
||||
|
||||
wire reset = reset_cnt != 8'd255;
|
||||
wire reset = (reset_cnt != 8'd255);
|
||||
|
||||
// pll to generate appropriate clock
|
||||
wire clk13;
|
||||
@@ -86,6 +102,8 @@ always @(posedge clk)
|
||||
wire ps2_clk;
|
||||
wire ps2_data;
|
||||
|
||||
wire [7:0] status;
|
||||
|
||||
user_io user_io(
|
||||
// the spi interface
|
||||
.SPI_CLK (SPI_SCK ),
|
||||
@@ -96,11 +114,17 @@ user_io user_io(
|
||||
.SWITCHES (switches ),
|
||||
.BUTTONS (buttons ),
|
||||
|
||||
// two joysticks supports
|
||||
.JOY0 ( ),
|
||||
.JOY1 ( ),
|
||||
|
||||
// status byte (bit 0 = io controller reset)
|
||||
.status ( status ),
|
||||
|
||||
// ps2 keyboard interface
|
||||
.clk (clk_12k ), // should be 10-16kHz for ps2 clock
|
||||
.ps2_data (ps2_data ),
|
||||
.ps2_clk (ps2_clk ),
|
||||
|
||||
.CORE_TYPE (8'ha4 ) // 8 bit core id
|
||||
.ps2_clk (ps2_clk )
|
||||
);
|
||||
|
||||
// ----------------------- Quick'n dirty scan doubler ---------------------------
|
||||
@@ -244,6 +268,8 @@ always @(posedge clk13) begin
|
||||
sd_video <= line_buffer[{!sd_toggle, sd_col}];
|
||||
end
|
||||
|
||||
wire tape_data;
|
||||
|
||||
zx01 zx01 (
|
||||
.n_reset (~reset ),
|
||||
.clock (clk ),
|
||||
@@ -252,7 +278,7 @@ zx01 zx01 (
|
||||
.v_inv (switches[1] ),
|
||||
.usa_uk (1'b0 ),
|
||||
.video (video ),
|
||||
.tape_in (1'b0 ),
|
||||
.tape_in (tape_data ),
|
||||
.tape_out (csync ),
|
||||
|
||||
// ignore LCD interface
|
||||
@@ -262,4 +288,39 @@ zx01 zx01 (
|
||||
.cp2 ( )
|
||||
);
|
||||
|
||||
// create 500kHz from 13 Mhz
|
||||
reg [4:0] clk_cnt;
|
||||
wire clk_500k = clk_cnt < 13;
|
||||
always @(posedge clk13) begin
|
||||
clk_cnt <= clk_cnt + 5'd1;
|
||||
if(clk_cnt == 5'd25)
|
||||
clk_cnt <= 5'd0;
|
||||
end
|
||||
|
||||
// tape transfers distort video, so we need a different kind
|
||||
// of feedback
|
||||
// we thus route type_data to led and to audio
|
||||
assign LED = !tape_data;
|
||||
|
||||
// use a pwm to reduce audio output volume
|
||||
reg [7:0] aclk;
|
||||
always @(posedge clk13)
|
||||
aclk <= aclk + 8'd1;
|
||||
|
||||
// limit volume to 1/8 => pwm < 32
|
||||
wire tape_audio = tape_data && (aclk < 32);
|
||||
assign AUDIO_L = tape_audio;
|
||||
assign AUDIO_R = tape_audio;
|
||||
|
||||
tape tape (
|
||||
// spi interface to io controller
|
||||
.sdi ( SPI_DI ),
|
||||
.sck ( SPI_SCK ),
|
||||
.ss ( SPI_SS2 ),
|
||||
|
||||
.clk ( clk_500k ),
|
||||
.play ( buttons[1] ),
|
||||
.tape_out ( tape_data )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user