mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 14:51:25 +03:00
Adjust the clocks and interrupts.
This commit is contained in:
@ -120,7 +120,7 @@ localparam CONF_STR = {
|
||||
"O8,CPU Cache,On,Off;",
|
||||
"O9A,#7FFD span,128K,128K Auto,1024K,512K;",
|
||||
"OLN,ZX Palette,Default,B.black,Light,Pale,Dark,Grayscale,Custom;",
|
||||
"OPR,INT Offset,1,2,3,4,5,6,7,0;",
|
||||
"OPR,INT Offset,0,1,2,3,4,5,6,7;",
|
||||
"-;",
|
||||
"OBD,F11 Reset,boot.$C,sys.rom,ROM;",
|
||||
"OEF, bank,TR-DOS,Basic 48,Basic 128,SYS;",
|
||||
@ -145,7 +145,7 @@ assign CMOSCfg[18:16]= (status[18:16]) ? status[18:16] + 3'd2 : 3'd0;
|
||||
assign CMOSCfg[20:19]= status[20:19] + 2'd2;
|
||||
assign CMOSCfg[23:21]= status[23:21];
|
||||
assign CMOSCfg[24] = 0;
|
||||
assign CMOSCfg[27:25]= status[27:25] + 3'd1;
|
||||
assign CMOSCfg[27:25]= status[27:25];
|
||||
|
||||
|
||||
//////////////////// CLOCKS ///////////////////
|
||||
|
18
src/clock.v
18
src/clock.v
@ -1,16 +1,16 @@
|
||||
// This module receives 28 MHz as input clock
|
||||
// and strobes strobes for all clocked parts
|
||||
|
||||
// clk|<EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD><EFBFBD>__<EFBFBD>| period = 28 duty = 50% phase = 0
|
||||
// clk|-__--__--__--__-| period = 28 duty = 50% phase = 0
|
||||
// cnt|< 0>< 1>< 2>< 3>|
|
||||
// f0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____| period = 14 duty = 50% phase = 0
|
||||
// f1 |____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 14 duty = 50% phase = 180
|
||||
// h0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>________| period = 7 duty = 50% phase = 0
|
||||
// h1 |________<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 7 duty = 50% phase = 180
|
||||
// c0 |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____________| period = 7 duty = 25% phase = 0
|
||||
// c1 |____<EFBFBD><EFBFBD><EFBFBD><EFBFBD>________| period = 7 duty = 25% phase = 90
|
||||
// c2 |________<EFBFBD><EFBFBD><EFBFBD><EFBFBD>____| period = 7 duty = 25% phase = 180
|
||||
// c3 |____________<EFBFBD><EFBFBD><EFBFBD><EFBFBD>| period = 7 duty = 25% phase = 270
|
||||
// f0 |----____----____| period = 14 duty = 50% phase = 0
|
||||
// f1 |____----____----| period = 14 duty = 50% phase = 180
|
||||
// h0 |--------________| period = 7 duty = 50% phase = 0
|
||||
// h1 |________--------| period = 7 duty = 50% phase = 180
|
||||
// c0 |----____________| period = 7 duty = 25% phase = 0
|
||||
// c1 |____----________| period = 7 duty = 25% phase = 90
|
||||
// c2 |________----____| period = 7 duty = 25% phase = 180
|
||||
// c3 |____________----| period = 7 duty = 25% phase = 270
|
||||
|
||||
module clock
|
||||
(
|
||||
|
150
src/cpu/zclock.v
150
src/cpu/zclock.v
@ -1,3 +1,4 @@
|
||||
|
||||
// PentEvo project (c) NedoPC 2008-2011
|
||||
//
|
||||
// Z80 clocking module, also contains some wait-stating when 14MHz
|
||||
@ -21,118 +22,85 @@
|
||||
// 2. do fallback on 7mhz for external IO accesses
|
||||
// 3. clock switch 14-7-3.5 only at RFSH
|
||||
|
||||
module zclock(
|
||||
module zclock
|
||||
(
|
||||
input clk,
|
||||
output zclk_out,
|
||||
input c0, c2, f0, f1,
|
||||
|
||||
input clk,
|
||||
//output reg zclk_out, // generated Z80 clock - passed through inverter externally!
|
||||
output wire zclk_out,
|
||||
input c1, c3, c14Mhz,
|
||||
input iorq_s,
|
||||
input external_port,
|
||||
|
||||
input wire iorq_s,
|
||||
input wire external_port,
|
||||
output reg zpos,
|
||||
output reg zneg,
|
||||
|
||||
output reg zpos,
|
||||
output reg zneg,
|
||||
output wire dos_stall_o,
|
||||
|
||||
// stall enables and triggers
|
||||
input wire cpu_stall,
|
||||
input wire ide_stall,
|
||||
input wire dos_on,
|
||||
input wire vdos_off,
|
||||
// stall enables and triggers
|
||||
input cpu_stall,
|
||||
input ide_stall,
|
||||
input dos_on,
|
||||
input vdos_off,
|
||||
|
||||
input [1:0] turbo // 2'b00 - 3.5 MHz
|
||||
// 2'b01 - 7.0 MHz
|
||||
// 2'b1x - 14.0 MHz
|
||||
// 2'b01 - 7.0 MHz
|
||||
// 2'b1x - 14.0 MHz
|
||||
);
|
||||
reg zclk_o;
|
||||
assign zclk_out = ~zclk_o;
|
||||
assign dos_stall_o = !stall_count_end || dos_on;
|
||||
//`ifdef SIMULATE
|
||||
// initial // simulation...
|
||||
// begin
|
||||
// c2_cnt = 1'b0;
|
||||
// turbo = 2'b00;
|
||||
// old_rfsh_n = 1'b1;
|
||||
// clk14_src = 1'b0;
|
||||
//
|
||||
// zclk_out = 1'b0;
|
||||
// end
|
||||
//`endif
|
||||
|
||||
|
||||
|
||||
assign zclk_out = ~zclk_o;
|
||||
reg zclk_o;
|
||||
|
||||
wire [1:0] turbo_int = turbo;
|
||||
|
||||
// wait generator
|
||||
wire dos_io_stall = stall_start || !stall_count_end;
|
||||
wire stall_start = dos_stall || io_stall;
|
||||
wire dos_stall = dos_on || vdos_off;
|
||||
wire io_stall = iorq_s && external_port && turbo[1]; //- NOT WORK
|
||||
wire stall_count_end = stall_count[3];
|
||||
|
||||
reg [3:0] stall_count;
|
||||
always @(posedge clk)
|
||||
if (stall_start)
|
||||
begin
|
||||
if (dos_stall)
|
||||
stall_count <= 4'd4; // 4 tacts 28MHz (1 tact 7MHz)
|
||||
else if (io_stall)
|
||||
stall_count <= 4'd0; // 8 tacts 28MHz (1 tact 3.5MHz)
|
||||
end
|
||||
else if (!stall_count_end)
|
||||
stall_count <= stall_count + 3'd1;
|
||||
wire dos_io_stall = stall_start || !stall_count_end;
|
||||
wire stall_start = dos_stall || io_stall;
|
||||
wire dos_stall = dos_on || vdos_off;
|
||||
wire io_stall = iorq_s && external_port && turbo_int[1];
|
||||
wire stall_count_end = stall_count[3];
|
||||
|
||||
reg [3:0] stall_count;
|
||||
always @(posedge clk) begin
|
||||
if (stall_start) begin
|
||||
if (dos_stall) stall_count <= 4; // 4 tacts 28MHz (1 tact 7MHz)
|
||||
else if (io_stall) stall_count <= 0; // 8 tacts 28MHz (1 tact 3.5MHz)
|
||||
end
|
||||
else if (!stall_count_end) stall_count <= stall_count + 3'd1;
|
||||
end
|
||||
|
||||
// Z80 clocking pre-strobes
|
||||
wire pre_zpos = turbo[1] ? pre_zpos_140 : ( turbo[0] ? pre_zpos_70 : pre_zpos_35 );
|
||||
wire pre_zneg = turbo[1] ? pre_zneg_140 : ( turbo[0] ? pre_zneg_70 : pre_zneg_35 );
|
||||
wire pre_zpos = turbo_int[1] ? pre_zpos_140 : (turbo_int[0] ? pre_zpos_70 : pre_zpos_35);
|
||||
wire pre_zneg = turbo_int[1] ? pre_zneg_140 : (turbo_int[0] ? pre_zneg_70 : pre_zneg_35);
|
||||
|
||||
reg clk14_src; // source for 14MHz clock
|
||||
always @(posedge clk)
|
||||
if (!stall && !(c14Mhz == 1'b1 && !clk14_src)) // c14Mhz =c1
|
||||
//if (!stall)
|
||||
clk14_src <= ~clk14_src;
|
||||
wire pre_zpos_140 = f1;
|
||||
wire pre_zneg_140 = f0;
|
||||
|
||||
wire pre_zpos_140 = clk14_src;
|
||||
wire pre_zneg_140 = ~clk14_src;
|
||||
wire pre_zpos_70 = c2;
|
||||
wire pre_zneg_70 = c0;
|
||||
|
||||
wire pre_zpos_70 = c1;
|
||||
wire pre_zneg_70 = c3;
|
||||
wire pre_zpos_35 = c2_cnt && c2;
|
||||
wire pre_zneg_35 = !c2_cnt && c2;
|
||||
|
||||
wire pre_zpos_35 = c1_cnt && c1;
|
||||
wire pre_zneg_35 = !c1_cnt && c1;
|
||||
reg c2_cnt;
|
||||
always @(posedge clk) if (c2) c2_cnt <= ~c2_cnt;
|
||||
|
||||
reg c1_cnt;
|
||||
always @(posedge clk) if (c1)
|
||||
c1_cnt <= ~c1_cnt;
|
||||
|
||||
|
||||
// Z80 clocking strobes
|
||||
//---------------INPUT----count generator- NO
|
||||
wire stall = cpu_stall || dos_io_stall || ide_stall;
|
||||
wire stall = cpu_stall || dos_io_stall || ide_stall;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
zpos <= !stall && pre_zpos && zclk_o;
|
||||
zneg <= !stall && pre_zneg && !zclk_o;
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
zpos <= !stall && pre_zpos && zclk_o;
|
||||
zneg <= !stall && pre_zneg && !zclk_o;
|
||||
end
|
||||
|
||||
|
||||
// make Z80 clock: account for external inversion and make some leading of clock
|
||||
// 9.5 ns propagation delay: from clk posedge to zclk returned back any edge
|
||||
// (1/28)/2=17.9ns half a clock lead
|
||||
// 2.6ns lag because of non-output register emitting of zclk_out
|
||||
// total: 5.8 ns lead of any edge of zclk relative to posedge of clk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
|
||||
|
||||
// Z80 clocking
|
||||
always @(negedge clk)
|
||||
begin
|
||||
if (zpos)
|
||||
zclk_o <= 1'b0;
|
||||
|
||||
if (zneg)
|
||||
zclk_o <= 1'b1;
|
||||
end
|
||||
// make Z80 clock: account for external inversion and make some leading of clock
|
||||
// 9.5 ns propagation delay: from clk posedge to zclk returned back any edge
|
||||
// (1/28)/2=17.9ns half a clock lead
|
||||
// 2.6ns lag because of non-output register emitting of zclk_o
|
||||
// total: 5.8 ns lead of any edge of zclk relative to posedge of clk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
|
||||
|
||||
// Z80 clocking
|
||||
always @(negedge clk) begin
|
||||
if (zpos) zclk_o <= 0;
|
||||
if (zneg) zclk_o <= 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
178
src/cpu/zint.v
178
src/cpu/zint.v
@ -1,123 +1,85 @@
|
||||
|
||||
module zint
|
||||
(
|
||||
input wire clk,
|
||||
input wire zclk,
|
||||
input wire res,
|
||||
input wire int_start_frm,
|
||||
input wire int_start_lin,
|
||||
input wire int_start_dma,
|
||||
input wire vdos,
|
||||
input wire intack,
|
||||
|
||||
//input wire [2:0] im2v_frm,
|
||||
//input wire [2:0] im2v_lin,
|
||||
//input wire [2:0] im2v_dma,
|
||||
input wire [7:0] intmask,
|
||||
output wire [7:0] im2vect,
|
||||
|
||||
output wire int_n
|
||||
input wire clk,
|
||||
input wire zpos,
|
||||
input wire res,
|
||||
input wire int_start_frm,
|
||||
input wire int_start_lin,
|
||||
input wire int_start_dma,
|
||||
input wire vdos,
|
||||
input wire intack,
|
||||
input wire [7:0] intmask,
|
||||
output wire [7:0] im2vect,
|
||||
output wire int_n
|
||||
);
|
||||
|
||||
// In VDOS INTs are focibly disabled.
|
||||
// For Frame, Line INT its generation is blocked, it will be lost.
|
||||
// For DMA INT only its output is blocked, so DMA ISR will will be processed as soon as returned from VDOS.
|
||||
|
||||
// IM2 Vector priority ============ OLD
|
||||
//assign im2vect = {vect[int_sel], 1'b1};
|
||||
//wire [6:0] vect [0:3];
|
||||
//assign vect[INTFRM] = {4'b1111, im2v_frm};
|
||||
//assign vect[INTLIN] = {4'b1110, im2v_lin};
|
||||
//assign vect[INTDMA] = {4'b1101, im2v_dma};
|
||||
//assign vect[INTDUM] = {4'b1101, im2v_dma};
|
||||
|
||||
//================================== NEW
|
||||
assign im2vect = {vect[int_sel]};
|
||||
// In VDOS INTs are focibly disabled.
|
||||
// For Frame, Line INT its generation is blocked, it will be lost.
|
||||
// For DMA INT only its output is blocked, so DMA ISR will will be processed as soon as returned from VDOS.
|
||||
|
||||
wire [7:0] vect [0:3];
|
||||
assign vect[INTFRM] = 8'hFF;
|
||||
assign vect[INTLIN] = 8'hFD;
|
||||
assign vect[INTDMA] = 8'hFB;
|
||||
assign vect[INTDUM] = 8'hFF;
|
||||
assign im2vect = {vect[int_sel]};
|
||||
|
||||
assign int_n = int_all ? 1'b0 : 1'b1;
|
||||
wire int_all = int_frm || int_lin || (int_dma && !vdos);
|
||||
|
||||
//===========================================================
|
||||
wire dis_int_frm = !intmask[0];
|
||||
wire dis_int_lin = !intmask[1];
|
||||
wire dis_int_dma = !intmask[2];
|
||||
|
||||
// ~INT source latch
|
||||
wire intack_s = intack && !intack_r;
|
||||
|
||||
reg intack_r;
|
||||
always @(posedge clk)
|
||||
intack_r <= intack;
|
||||
|
||||
localparam INTFRM = 2'b00;
|
||||
localparam INTLIN = 2'b01;
|
||||
localparam INTDMA = 2'b10;
|
||||
localparam INTDUM = 2'b11;
|
||||
|
||||
reg [1:0] int_sel;
|
||||
always @(posedge clk)
|
||||
if (intack_s)
|
||||
begin
|
||||
if (int_frm)
|
||||
int_sel <= INTFRM; // priority 0
|
||||
else if (int_lin)
|
||||
int_sel <= INTLIN; // priority 1
|
||||
else if (int_dma)
|
||||
int_sel <= INTDMA; // priority 2
|
||||
end
|
||||
// ~INT source latch
|
||||
localparam INTFRM = 2'd0;
|
||||
localparam INTLIN = 2'd1;
|
||||
localparam INTDMA = 2'd2;
|
||||
localparam INTWTP = 2'd3;
|
||||
|
||||
wire [7:0] vect [0:3];
|
||||
assign vect[INTFRM] = 8'hFF;
|
||||
assign vect[INTLIN] = 8'hFD;
|
||||
assign vect[INTDMA] = 8'hFB;
|
||||
assign vect[INTWTP] = 8'hFF;
|
||||
|
||||
assign int_n = ~((int_frm || int_lin || int_dma) && !vdos);
|
||||
|
||||
wire dis_int_frm = !intmask[0];
|
||||
wire dis_int_lin = !intmask[1];
|
||||
wire dis_int_dma = !intmask[2];
|
||||
|
||||
wire intack_s = intack && !intack_r;
|
||||
reg intack_r;
|
||||
always @(posedge clk) intack_r <= intack;
|
||||
|
||||
reg [1:0] int_sel;
|
||||
always @(posedge clk) begin
|
||||
if (intack_s) begin
|
||||
if (int_frm) int_sel <= INTFRM; // priority 0
|
||||
else if (int_lin) int_sel <= INTLIN; // priority 1
|
||||
else if (int_dma) int_sel <= INTDMA; // priority 2
|
||||
end
|
||||
end
|
||||
|
||||
// ~INT generating
|
||||
reg int_frm;
|
||||
always @(posedge clk)
|
||||
if (res || dis_int_frm || vdos)
|
||||
int_frm <= 1'b0;
|
||||
else if (int_start_frm)
|
||||
int_frm <= 1'b1;
|
||||
// else if (intctr_fin || intack_s) // priority 0
|
||||
else if (intctr_fin) // MVV 01.11.2014
|
||||
int_frm <= 1'b0;
|
||||
reg int_frm;
|
||||
always @(posedge clk) begin
|
||||
if (res || dis_int_frm) int_frm <= 0;
|
||||
else if (int_start_frm) int_frm <= 1;
|
||||
else if (intack_s || intctr_fin) int_frm <= 0; // priority 0
|
||||
end
|
||||
|
||||
reg int_lin;
|
||||
always @(posedge clk)
|
||||
if (res || dis_int_lin || vdos)
|
||||
int_lin <= 1'b0;
|
||||
else if (int_start_lin)
|
||||
int_lin <= 1'b1;
|
||||
else if (intack_s && !int_frm) // priority 1
|
||||
int_lin <= 1'b0;
|
||||
reg int_lin;
|
||||
always @(posedge clk) begin
|
||||
if (res || dis_int_lin) int_lin <= 0;
|
||||
else if (int_start_lin) int_lin <= 1;
|
||||
else if (intack_s && !int_frm) int_lin <= 0; // priority 1
|
||||
end
|
||||
|
||||
reg int_dma;
|
||||
always @(posedge clk)
|
||||
if (res || dis_int_dma)
|
||||
int_dma <= 1'b0;
|
||||
else if (int_start_dma)
|
||||
int_dma <= 1'b1;
|
||||
else if (intack_s && !int_frm && !int_lin) // priority 2
|
||||
int_dma <= 1'b0;
|
||||
reg int_dma;
|
||||
always @(posedge clk) begin
|
||||
if (res || dis_int_dma) int_dma <= 0;
|
||||
else if (int_start_dma) int_dma <= 1;
|
||||
else if (intack_s && !int_frm && !int_lin) int_dma <= 0; // priority 2
|
||||
end
|
||||
|
||||
|
||||
// INT counter
|
||||
// reg [4:0] intctr;
|
||||
// wire intctr_fin = &intctr; // 32 clks
|
||||
// ~INT counter
|
||||
reg [5:0] intctr;
|
||||
wire intctr_fin = intctr[5]; // 32 clks
|
||||
reg [5:0] intctr;
|
||||
wire intctr_fin = intctr[4]; // 32 clks
|
||||
|
||||
always @(posedge clk, posedge int_start_frm) begin
|
||||
if (int_start_frm) intctr <= 0;
|
||||
else if (zpos && !intctr_fin && !vdos) intctr <= intctr + 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// always @(posedge zclk, posedge int_start_lin)
|
||||
always @(posedge zclk, posedge int_start_frm) // MVV 31.10.2014
|
||||
begin
|
||||
// if (int_start_lin)
|
||||
if (int_start_frm) // MVV 31.10.2014
|
||||
intctr <= 6'b000000;
|
||||
else if (!intctr_fin)
|
||||
intctr <= intctr + 6'b000001;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -3,14 +3,13 @@
|
||||
//
|
||||
|
||||
|
||||
module zmem(
|
||||
|
||||
module zmem
|
||||
(
|
||||
input wire clk,
|
||||
input wire c0, c1, c2, c3,
|
||||
input wire zneg, // strobes which show positive and negative edges of zclk
|
||||
input wire zpos,
|
||||
|
||||
// Z80
|
||||
// Z80
|
||||
input wire rst,
|
||||
input wire [15:0] za,
|
||||
output wire [ 7:0] zd_out, // output to Z80 bus
|
||||
@ -19,13 +18,13 @@ module zmem(
|
||||
input wire opfetch,
|
||||
input wire opfetch_s,
|
||||
input wire mreq,
|
||||
input wire memrd,
|
||||
input wire memwr,
|
||||
input wire memrd,
|
||||
input wire memwr,
|
||||
input wire memwr_s,
|
||||
|
||||
input wire [ 1:0] turbo, // 2'b00 - 3.5,
|
||||
// 2'b01 - 7.0,
|
||||
// 2'b1x - 14.0
|
||||
// 2'b01 - 7.0,
|
||||
// 2'b1x - 14.0
|
||||
input wire [3:0] cache_en,
|
||||
input wire [3:0] memconf,
|
||||
input wire [31:0] xt_page,
|
||||
@ -35,19 +34,19 @@ module zmem(
|
||||
output wire csrom,
|
||||
output wire romoe_n,
|
||||
output wire romwe_n,
|
||||
|
||||
|
||||
output wire csvrom,
|
||||
output wire dos,
|
||||
output wire dos_on,
|
||||
output wire dos_on,
|
||||
output wire dos_off,
|
||||
output wire dos_change,
|
||||
|
||||
|
||||
output wire vdos,
|
||||
output reg pre_vdos,
|
||||
input wire vdos_on,
|
||||
input wire vdos_off,
|
||||
|
||||
// DRAM
|
||||
// DRAM
|
||||
output wire cpu_req,
|
||||
output wire [20:0] cpu_addr,
|
||||
output wire cpu_wrbsel,
|
||||
@ -56,13 +55,12 @@ module zmem(
|
||||
input wire cpu_strobe,
|
||||
input wire cpu_latch,
|
||||
output wire cpu_stall, // for zclock
|
||||
|
||||
|
||||
input wire loader,
|
||||
|
||||
input wire testkey, // DEBUG!!!
|
||||
input wire intt, // DEBUG!!!
|
||||
output wire [3:0] tst
|
||||
|
||||
);
|
||||
|
||||
assign tst[0] = memwr && win0;
|
||||
@ -204,14 +202,11 @@ module zmem(
|
||||
//wire stall14 = stall14_ini || stall14_cyc || stall14_fin; //- not work
|
||||
wire stall14 = stall14_ini || stall14_cyc; //WORK
|
||||
|
||||
//wire dram_beg = (!cache_hit_en || ramwr) && zpos && ramreq_s_n; //modif N1
|
||||
wire dram_beg = (!cache_hit_en && ( memconf[3] ? 1'b1 : ramrd ) || ramwr) && zpos && ramreq_s_n; //-- N2
|
||||
//if BANK0-RAM, WR enable all time for 14 MHz
|
||||
wire ramreq_s_n = ramreq_r_n && ramreq;
|
||||
reg ramreq_r_n;
|
||||
//always @(posedge clk) if (zneg)
|
||||
always @(posedge clk) if (zpos)
|
||||
ramreq_r_n <= !mreq;
|
||||
always @(posedge clk) if (zpos) ramreq_r_n <= !mreq;
|
||||
|
||||
reg pending_cpu_req;
|
||||
always @(posedge clk)
|
||||
|
217
src/cpu/zports.v
217
src/cpu/zports.v
@ -1,9 +1,8 @@
|
||||
|
||||
// PentEvo project (c) NedoPC 2008-2010
|
||||
|
||||
module zports(
|
||||
|
||||
input wire zclk, // z80 clock
|
||||
module zports
|
||||
(
|
||||
input wire clk,
|
||||
|
||||
input wire [ 7:0] din,
|
||||
@ -31,55 +30,52 @@ module zports(
|
||||
output wire porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus
|
||||
output wire external_port, // asserts for AY and VG93 accesses
|
||||
|
||||
output wire zborder_wr ,
|
||||
output wire border_wr ,
|
||||
output wire zvpage_wr ,
|
||||
output wire vpage_wr ,
|
||||
output wire vconf_wr ,
|
||||
output wire gx_offsl_wr ,
|
||||
output wire gx_offsh_wr ,
|
||||
output wire gy_offsl_wr ,
|
||||
output wire gy_offsh_wr ,
|
||||
output wire t0x_offsl_wr,
|
||||
output wire t0x_offsh_wr,
|
||||
output wire t0y_offsl_wr,
|
||||
output wire t0y_offsh_wr,
|
||||
output wire t1x_offsl_wr,
|
||||
output wire t1x_offsh_wr,
|
||||
output wire t1y_offsl_wr,
|
||||
output wire t1y_offsh_wr,
|
||||
output wire tsconf_wr ,
|
||||
output wire palsel_wr ,
|
||||
output wire tmpage_wr ,
|
||||
output wire t0gpage_wr ,
|
||||
output wire t1gpage_wr ,
|
||||
output wire sgpage_wr ,
|
||||
output wire hint_beg_wr ,
|
||||
output wire vint_begl_wr,
|
||||
output wire vint_begh_wr,
|
||||
output wire zborder_wr,
|
||||
output wire border_wr,
|
||||
output wire zvpage_wr,
|
||||
output wire vpage_wr,
|
||||
output wire vconf_wr,
|
||||
output wire gx_offsl_wr,
|
||||
output wire gx_offsh_wr,
|
||||
output wire gy_offsl_wr,
|
||||
output wire gy_offsh_wr,
|
||||
output wire t0x_offsl_wr,
|
||||
output wire t0x_offsh_wr,
|
||||
output wire t0y_offsl_wr,
|
||||
output wire t0y_offsh_wr,
|
||||
output wire t1x_offsl_wr,
|
||||
output wire t1x_offsh_wr,
|
||||
output wire t1y_offsl_wr,
|
||||
output wire t1y_offsh_wr,
|
||||
output wire tsconf_wr,
|
||||
output wire palsel_wr,
|
||||
output wire tmpage_wr,
|
||||
output wire t0gpage_wr,
|
||||
output wire t1gpage_wr,
|
||||
output wire sgpage_wr,
|
||||
output wire hint_beg_wr,
|
||||
output wire vint_begl_wr,
|
||||
output wire vint_begh_wr,
|
||||
|
||||
output wire [31:0] xt_page,
|
||||
|
||||
output reg [4:0] fmaddr,
|
||||
output reg [4:0] fmaddr,
|
||||
//----Conf-----------------
|
||||
output reg [7:0] sysconf,
|
||||
output reg [7:0] memconf,
|
||||
output reg [3:0] cacheconf,
|
||||
output reg [7:0] sysconf,
|
||||
output reg [7:0] memconf,
|
||||
output reg [3:0] cacheconf,
|
||||
//-------------------------
|
||||
output reg [3:0] fddvirt,
|
||||
|
||||
//output reg [2:0] im2v_frm,
|
||||
//output reg [2:0] im2v_lin,
|
||||
//output reg [2:0] im2v_dma,
|
||||
output reg [7:0] intmask,
|
||||
output reg [3:0] fddvirt,
|
||||
|
||||
output wire [8:0] dmaport_wr,
|
||||
input wire dma_act,
|
||||
output reg [7:0] intmask,
|
||||
|
||||
output wire [8:0] dmaport_wr,
|
||||
input wire dma_act,
|
||||
|
||||
input wire dos,
|
||||
input wire vdos,
|
||||
output wire vdos_on,
|
||||
output wire vdos_off,
|
||||
output wire vdos_on,
|
||||
output wire vdos_off,
|
||||
|
||||
output wire ay_bdir,
|
||||
output wire ay_bc1,
|
||||
@ -89,16 +85,6 @@ module zports(
|
||||
input wire [ 1:0] rstrom,
|
||||
input wire tape_read,
|
||||
|
||||
// IDE interface
|
||||
// input wire [15:0] ide_in,
|
||||
// output wire [15:0] ide_out,
|
||||
// output wire ide_cs0_n,
|
||||
// output wire ide_cs1_n,
|
||||
// output wire ide_req,
|
||||
// input wire ide_stb,
|
||||
// input wire ide_ready,
|
||||
// output reg ide_stall,
|
||||
|
||||
input wire [ 4:0] keys_in, // keys (port FE)
|
||||
input wire [ 7:0] mus_in, // mouse (xxDF)
|
||||
input wire [ 5:0] kj_in,
|
||||
@ -107,15 +93,15 @@ module zports(
|
||||
input wire vg_drq, // from vg93 module - drq + irq read
|
||||
output wire vg_cs_n,
|
||||
output wire vg_wrFF,
|
||||
output reg [1:0] drive_sel, // disk drive selection
|
||||
output reg [1:0] drive_sel, // disk drive selection
|
||||
|
||||
// SPI
|
||||
// SPI
|
||||
output reg sdcs_n,
|
||||
output wire sd_start,
|
||||
output wire [ 7:0] sd_datain,
|
||||
input wire [ 7:0] sd_dataout,
|
||||
|
||||
// WAIT-ports related
|
||||
// WAIT-ports related
|
||||
output reg [ 7:0] gluclock_addr,
|
||||
output reg [ 2:0] comport_addr,
|
||||
output wire wait_start_gluclock, // begin wait from some ports
|
||||
@ -125,10 +111,9 @@ module zports(
|
||||
//---COM PORT------------------------
|
||||
input wire [ 7:0] com_data_rx,
|
||||
input wire [ 7:0] com_status,
|
||||
//------------------------------
|
||||
//------------------------------
|
||||
output wire [ 7:0] TST,
|
||||
input wire lock_conf
|
||||
|
||||
);
|
||||
|
||||
assign TST = 7'h00|sd_start;
|
||||
@ -223,13 +208,12 @@ module zports(
|
||||
assign dataout = porthit & iord & (~external_port);
|
||||
|
||||
|
||||
// zclk-synchronous strobes
|
||||
reg iowr_reg;
|
||||
reg iord_reg;
|
||||
reg port_wr;
|
||||
reg port_rd;
|
||||
|
||||
always @(posedge zclk)
|
||||
always @(posedge clk)
|
||||
begin
|
||||
iowr_reg <= iowr;
|
||||
iord_reg <= iord;
|
||||
@ -252,7 +236,7 @@ module zports(
|
||||
// reading ports
|
||||
always @*
|
||||
begin
|
||||
dout = 8'hFF;
|
||||
dout = 8'hFF;
|
||||
case (loa)
|
||||
PORTFE:
|
||||
// dout = {1'b1, tape_read, 1'b0, keys_in};
|
||||
@ -577,17 +561,17 @@ module zports(
|
||||
// gluclock ports
|
||||
wire gluclock_on = peff7[7] || dos; // in dos mode EEF7 is not accessible, gluclock access is ON in dos mode.
|
||||
|
||||
always @(posedge zclk)
|
||||
always @(posedge clk) begin
|
||||
if (gluclock_on && portf7_wr) // gluclocks on
|
||||
if( !a[13] ) // $DFF7 - addr reg
|
||||
gluclock_addr <= din;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
// write to wait registers
|
||||
always @(posedge zclk)
|
||||
begin
|
||||
always @(posedge clk) begin
|
||||
// gluclocks
|
||||
if (gluclock_on && portf7_wr && !a[14]) // $BFF7 - data reg
|
||||
wait_write <= din;
|
||||
@ -601,9 +585,10 @@ module zports(
|
||||
wire comport_wr = ((loa==COMPORT) && port_wr);
|
||||
wire comport_rd = ((loa==COMPORT) && port_rd);
|
||||
|
||||
always @(posedge zclk)
|
||||
always @(posedge clk) begin
|
||||
if (comport_wr || comport_rd)
|
||||
comport_addr <= a[10:8];
|
||||
end
|
||||
|
||||
|
||||
// wait from wait registers
|
||||
@ -611,106 +596,4 @@ module zports(
|
||||
assign wait_start_gluclock = (gluclock_on && !a[14] && (portf7_rd || portf7_wr)); // $BFF7 - gluclock r/w
|
||||
assign wait_start_comport = (comport_rd || comport_wr);
|
||||
|
||||
// IDE ports
|
||||
// do NOT generate IDE write, if neither of ide_wrhi|lo latches set and writing to NIDE10
|
||||
// wire ide_cs0 = ide_even && !ide_portc8;
|
||||
// wire ide_cs1 = ide_portc8;
|
||||
// wire ide_rd = rd && !(ide_rd_latch && ide_port10);
|
||||
// wire ide_wr = wr && !(!ide_wrlo_latch && !ide_wrhi_latch && ide_port10);
|
||||
// assign ide_req = iorq_s && ide_even && (ide_rd || ide_wr);
|
||||
// assign ide_cs0_n = !ide_cs0;
|
||||
// assign ide_cs1_n = !ide_cs1;
|
||||
|
||||
|
||||
// always @(posedge clk)
|
||||
// if (ide_req)
|
||||
// ide_stall <= 1'b1;
|
||||
// else if (ide_ready)
|
||||
// ide_stall <= 1'b0;
|
||||
|
||||
|
||||
// control read & write triggers, which allow nemo-divide mod to work.
|
||||
// read trigger:
|
||||
// reg ide_rd_trig; // nemo-divide read trigger
|
||||
// always @(posedge zclk)
|
||||
// begin
|
||||
// if (ide_port10 && port_rd && !ide_rd_trig)
|
||||
// ide_rd_trig <= 1'b1;
|
||||
// else if (ide_all && (port_rd || port_wr))
|
||||
// ide_rd_trig <= 1'b0;
|
||||
// end
|
||||
|
||||
|
||||
// two triggers for write sequence
|
||||
// reg ide_wrlo_trig, ide_wrhi_trig; // nemo-divide write triggers
|
||||
// always @(posedge zclk)
|
||||
// if (ide_all && (port_rd || port_wr))
|
||||
// begin
|
||||
// if (ide_port11 && port_wr)
|
||||
// ide_wrhi_trig <= 1'b1;
|
||||
// else
|
||||
// ide_wrhi_trig <= 1'b0;
|
||||
//
|
||||
// if (ide_port10 && port_wr && !ide_wrhi_trig && !ide_wrlo_trig)
|
||||
// ide_wrlo_trig <= 1'b1;
|
||||
// else
|
||||
// ide_wrlo_trig <= 1'b0;
|
||||
// end
|
||||
|
||||
|
||||
// normal read: #10(low), #11(high)
|
||||
// divide read: #10(low), #10(high)
|
||||
//
|
||||
// normal write: #11(high), #10(low)
|
||||
// divide write: #10(low), #10(high)
|
||||
|
||||
// reg [15:0] idewrreg; // write register, either low or high part is pre-written here,
|
||||
// while other part is out directly from Z80 bus
|
||||
// always @(posedge zclk)
|
||||
// begin
|
||||
// if (port_wr && ide_port11)
|
||||
// idewrreg[15:8] <= din;
|
||||
|
||||
// if (port_wr && ide_port10 && !ide_wrlo_trig)
|
||||
// idewrreg[ 7:0] <= din;
|
||||
// end
|
||||
|
||||
|
||||
// generate read cycles for IDE as usual, except for reading #10
|
||||
// instead of #11 for high byte (nemo-divide). I use additional latch
|
||||
// since 'ide_rd_trig' clears during second Z80 IO read cycle to #10
|
||||
// reg ide_rd_latch; // to save state of trigger during read cycle
|
||||
// always @*
|
||||
// if (!rd)
|
||||
// ide_rd_latch <= ide_rd_trig;
|
||||
|
||||
// reg ide_wrlo_latch, ide_wrhi_latch; // save state during write cycles
|
||||
// always @*
|
||||
// if (!wr)
|
||||
// begin
|
||||
// ide_wrlo_latch <= ide_wrlo_trig; // same for write triggers
|
||||
// ide_wrhi_latch <= ide_wrhi_trig;
|
||||
// end
|
||||
|
||||
|
||||
// data read by Z80 from IDE
|
||||
// wire idein_lo_rd = port_rd && ide_port10 && (!ide_rd_trig); // while high part is remembered here
|
||||
// wire [7:0] iderdodd = iderdreg[15:8]; // read data from "odd" port (#11)
|
||||
// wire [7:0] iderdeven = (ide_rd_latch && ide_port10) ? iderdreg[15:8] : iderdreg[7:0]; // to control read data from "even" ide ports (all except #11)
|
||||
// wire [7:0] iderdeven = (ide_rd_latch && ide_port10) ? idehiin[7:0] : ide_in[7:0]; // to control read data from "even" ide ports (all except #11)
|
||||
|
||||
// reg [15:0] iderdreg;
|
||||
// reg [7:0] idehiin; // IDE high part read register: low part is read directly to Z80 bus,
|
||||
// always @(posedge clk)
|
||||
// if (ide_stb)
|
||||
// iderdreg <= ide_in;
|
||||
// if (idein_lo_rd)
|
||||
// idehiin <= ide_in[15:8];
|
||||
|
||||
|
||||
// data written to IDE from Z80
|
||||
// wire [7:0] ideout1 = ide_wrhi_latch ? idewrreg[15:8] : din[ 7:0];
|
||||
// wire [7:0] ideout0 = ide_wrlo_latch ? idewrreg[ 7:0] : din[ 7:0];
|
||||
// assign ide_out = {ideout1, ideout0};
|
||||
|
||||
endmodule
|
||||
|
@ -1,13 +1,12 @@
|
||||
|
||||
// Decoding and strobing of z80 signals
|
||||
|
||||
module zsignals(
|
||||
|
||||
// clocks
|
||||
module zsignals
|
||||
(
|
||||
// clocks
|
||||
input wire clk,
|
||||
input wire zpos,
|
||||
|
||||
// z80 interface input
|
||||
// z80 interface input
|
||||
input wire iorq_n,
|
||||
input wire mreq_n,
|
||||
input wire m1_n,
|
||||
@ -15,7 +14,7 @@ module zsignals(
|
||||
input wire rd_n,
|
||||
input wire wr_n,
|
||||
|
||||
// Z80 signals
|
||||
// Z80 signals
|
||||
output wire m1,
|
||||
output wire rfsh,
|
||||
output wire rd,
|
||||
@ -32,7 +31,7 @@ module zsignals(
|
||||
output wire opfetch,
|
||||
output wire intack,
|
||||
|
||||
// Z80 signals strobes, at fclk
|
||||
// Z80 signals strobes, at fclk
|
||||
output wire iorq_s,
|
||||
output wire mreq_s,
|
||||
output wire iord_s,
|
||||
@ -45,50 +44,42 @@ module zsignals(
|
||||
);
|
||||
|
||||
// invertors
|
||||
assign m1 = !m1_n;
|
||||
assign rfsh = !rfsh_n;
|
||||
assign rd = !rd_n;
|
||||
assign wr = !wr_n;
|
||||
assign m1 = !m1_n;
|
||||
assign rfsh = !rfsh_n;
|
||||
assign rd = !rd_n;
|
||||
assign wr = !wr_n;
|
||||
|
||||
// requests
|
||||
assign iorq = !iorq_n && m1_n; // this is masked by ~M1 to avoid port decoding on INT ack
|
||||
assign mreq = !mreq_n && rfsh_n; // this is masked by ~RFSH to ignore refresh cycles as memory requests
|
||||
assign iorq = !iorq_n && m1_n; // this is masked by ~M1 to avoid port decoding on INT ack
|
||||
assign mreq = !mreq_n && rfsh_n; // this is masked by ~RFSH to ignore refresh cycles as memory requests
|
||||
|
||||
// combined
|
||||
assign rdwr = rd || wr;
|
||||
assign iord = iorq && rd;
|
||||
assign iowr = iorq && wr;
|
||||
assign iorw = iorq && rdwr;
|
||||
assign memrd = mreq && rd;
|
||||
assign memwr = mreq && !rd;
|
||||
assign memrw = mreq && rdwr;
|
||||
assign opfetch = memrd && m1;
|
||||
assign intack = !iorq_n && m1; // NOT masked by M1
|
||||
assign rdwr = rd || wr;
|
||||
assign iord = iorq && rd;
|
||||
assign iowr = iorq && wr;
|
||||
assign iorw = iorq && rdwr;
|
||||
assign memrd = mreq && rd;
|
||||
assign memwr = mreq && !rd;
|
||||
assign memrw = mreq && rdwr;
|
||||
assign opfetch = memrd && m1;
|
||||
assign intack = !iorq_n && m1; // NOT masked by M1
|
||||
|
||||
// strobed
|
||||
assign iorq_s = iorq_r[0] && !iorq_r[1];
|
||||
assign mreq_s = mreq_r[0] && !mreq_r[1];
|
||||
assign iord_s = iorq_s && rd;
|
||||
assign iowr_s = iorq_s && wr;
|
||||
assign iorw_s = iorq_s && rdwr;
|
||||
assign memrd_s = mreq_s && rd;
|
||||
assign memwr_s = mreq_s && !rd;
|
||||
assign memrw_s = mreq_s && rdwr;
|
||||
assign opfetch_s = memrd_s && m1;
|
||||
assign iorq_s = iorq_r[0] && !iorq_r[1];
|
||||
assign mreq_s = mreq_r[0] && !mreq_r[1];
|
||||
assign iord_s = iorq_s && rd;
|
||||
assign iowr_s = iorq_s && wr;
|
||||
assign iorw_s = iorq_s && rdwr;
|
||||
assign memrd_s = mreq_s && rd;
|
||||
assign memwr_s = mreq_s && !rd;
|
||||
assign memrw_s = mreq_s && rdwr;
|
||||
assign opfetch_s = memrd_s && m1;
|
||||
|
||||
// latch inputs on FPGA clock
|
||||
reg [1:0] iorq_r, mreq_r;
|
||||
always @(posedge clk) if (zpos)
|
||||
begin
|
||||
iorq_r[0] <= iorq;
|
||||
mreq_r[0] <= mreq;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
iorq_r[1] <= iorq_r[0];
|
||||
mreq_r[1] <= mreq_r[0];
|
||||
end
|
||||
|
||||
reg [1:0] iorq_r, mreq_r;
|
||||
always @(posedge clk) begin
|
||||
iorq_r <= {iorq_r[0], iorq};
|
||||
mreq_r <= {mreq_r[0], mreq};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
46
src/tsconf.v
46
src/tsconf.v
@ -162,18 +162,6 @@ wire dos;
|
||||
|
||||
wire [7:0] gluclock_addr;
|
||||
|
||||
// clock
|
||||
wire f0;
|
||||
wire f1;
|
||||
wire h0;
|
||||
wire h1;
|
||||
wire c0;
|
||||
wire c1;
|
||||
wire c2;
|
||||
wire c3;
|
||||
wire zclk;
|
||||
wire zpos;
|
||||
wire zneg;
|
||||
wire vdos;
|
||||
wire pre_vdos;
|
||||
wire vdos_off;
|
||||
@ -295,6 +283,11 @@ wire [7:0] spi_dout;
|
||||
wire [7:0] mouse_do;
|
||||
|
||||
|
||||
// clock
|
||||
wire f0,f1;
|
||||
wire h0,h1;
|
||||
wire c0,c1,c2,c3;
|
||||
|
||||
clock TS01
|
||||
(
|
||||
.clk(clk_28mhz),
|
||||
@ -307,16 +300,18 @@ clock TS01
|
||||
.c2(c2),
|
||||
.c3(c3)
|
||||
);
|
||||
|
||||
|
||||
wire zclk;
|
||||
wire zpos;
|
||||
zclock TS02
|
||||
(
|
||||
.clk(clk_28mhz),
|
||||
.c1(c1),
|
||||
.c3(c3),
|
||||
.c14Mhz(c1),
|
||||
.c0(c0),
|
||||
.c2(c2),
|
||||
.f0(f0),
|
||||
.f1(f1),
|
||||
.zclk_out(zclk),
|
||||
.zpos(zpos),
|
||||
.zneg(zneg),
|
||||
.iorq_s(iorq_s),
|
||||
.dos_on(dos_change),
|
||||
.vdos_off(vdos_off),
|
||||
@ -325,11 +320,12 @@ zclock TS02
|
||||
.external_port(0),
|
||||
.turbo(turbo)
|
||||
);
|
||||
|
||||
|
||||
T80s CPU
|
||||
(
|
||||
.RESET_n(~reset),
|
||||
.CLK_n(zclk),
|
||||
.CLK_n(zclk), //clk_28mhz),
|
||||
//.CEN(zpos),
|
||||
.INT_n(cpu_int_n_TS),
|
||||
.M1_n(cpu_m1_n),
|
||||
.MREQ_n(cpu_mreq_n),
|
||||
@ -346,7 +342,6 @@ T80s CPU
|
||||
zsignals TS04
|
||||
(
|
||||
.clk(clk_28mhz),
|
||||
.zpos(zpos),
|
||||
.iorq_n(cpu_iorq_n),
|
||||
.mreq_n(cpu_mreq_n),
|
||||
.m1_n(cpu_m1_n),
|
||||
@ -375,7 +370,6 @@ zsignals TS04
|
||||
|
||||
zports TS05
|
||||
(
|
||||
.zclk(zclk),
|
||||
.clk(clk_28mhz),
|
||||
.din(cpu_do_bus),
|
||||
.dout(dout_ports),
|
||||
@ -460,7 +454,6 @@ zmem TS06
|
||||
.c1(c1),
|
||||
.c2(c2),
|
||||
.c3(c3),
|
||||
.zneg(zneg),
|
||||
.zpos(zpos),
|
||||
.rst(reset), // PLL locked
|
||||
.za(cpu_a_bus), // from CPU
|
||||
@ -672,7 +665,7 @@ spi TS11
|
||||
zint TS13
|
||||
(
|
||||
.clk(clk_28mhz),
|
||||
.zclk(zclk),
|
||||
.zpos(zpos),
|
||||
.res(reset),
|
||||
.int_start_frm(int_start_frm), //< N1 VIDEO
|
||||
.int_start_lin(int_start_lin), //< N2 VIDEO
|
||||
@ -808,15 +801,12 @@ soundrive SE10
|
||||
);
|
||||
|
||||
// Turbosound FM
|
||||
reg ce_ym, ce_cpu;
|
||||
reg ce_ym;
|
||||
always @(posedge clk_28mhz) begin
|
||||
reg [1:0] div;
|
||||
|
||||
div <= div + 1'd1;
|
||||
ce_ym <= !div;
|
||||
|
||||
ce_cpu <= zclk;
|
||||
if(ce_cpu) ce_cpu <= 0;
|
||||
end
|
||||
|
||||
wire ts_enable = ~cpu_iorq_n & cpu_a_bus[0] & cpu_a_bus[15] & ~cpu_a_bus[1];
|
||||
@ -830,7 +820,7 @@ turbosound SE12
|
||||
.RESET(reset),
|
||||
|
||||
.CLK(clk_28mhz),
|
||||
.CE_CPU(ce_cpu),
|
||||
.CE_CPU(zpos),
|
||||
.CE_YM(ce_ym),
|
||||
.BDIR(ts_we),
|
||||
.BC(cpu_a_bus[14]),
|
||||
|
@ -171,12 +171,12 @@ wire [8:0] vp_beg[0:3];
|
||||
wire [8:0] vp_end[0:3];
|
||||
wire [5:0] x_tile[0:3];
|
||||
|
||||
assign hp_beg[0] = 9'd136; // 256 (88-52-256-52)
|
||||
assign hp_beg[0] = 9'd134; // 256 (88-52-256-52)
|
||||
assign hp_beg[1] = 9'd108; // 320 (88-20-320-20)
|
||||
assign hp_beg[2] = 9'd108; // 320 (88-20-320-20)
|
||||
assign hp_beg[3] = 9'd88; // 360 (88-0-360-0)
|
||||
|
||||
assign hp_end[0] = 9'd392; // 256
|
||||
assign hp_end[0] = 9'd390; // 256
|
||||
assign hp_end[1] = 9'd428; // 320
|
||||
assign hp_end[2] = 9'd428; // 320
|
||||
assign hp_end[3] = 9'd448; // 360
|
||||
|
Reference in New Issue
Block a user