1
0
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:
harbaum
2014-06-27 08:26:06 +00:00
parent 82b0c0f666
commit ecbe8eaa07
6 changed files with 724 additions and 45 deletions

View 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

View 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
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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