mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-01-24 19:12:17 +00:00
RS232 redirection and DMA bus error fix
This commit is contained in:
parent
dedc0946f2
commit
9310d78dcb
@ -52,9 +52,13 @@ assign addr = (cmd==2)?(addrR[22:0]-23'd1):addrR[22:0];
|
||||
|
||||
// latch bus cycle to have it stable at the end of the cycle (rising edge of clk8)
|
||||
reg [1:0] bus_cycle_L;
|
||||
always @(negedge clk_8)
|
||||
always @(negedge clk_8) begin
|
||||
bus_cycle_L <= bus_cycle;
|
||||
|
||||
if(bus_cycle == 0)
|
||||
br <= brI;
|
||||
end
|
||||
|
||||
// generate state signals required to control the sdram host interface
|
||||
always @(posedge clk_8) begin
|
||||
// start io transfers clock cycles after bus_cycle 0
|
||||
@ -64,8 +68,6 @@ always @(posedge clk_8) begin
|
||||
readD <= readCmd && ((bus_cycle_L == 3) || readD);
|
||||
readD2 <= readD;
|
||||
|
||||
br <= brI;
|
||||
|
||||
// at the end of a read cycle latch the incoming ram data for later spi transmission
|
||||
if(read) ram_data <= data_in;
|
||||
|
||||
|
||||
@ -18,6 +18,10 @@ module mfp (
|
||||
input serial_strobe_out,
|
||||
output [7:0] serial_data_out,
|
||||
|
||||
// serial rs223 connection from io controller
|
||||
input serial_strobe_in,
|
||||
input [7:0] serial_data_in,
|
||||
|
||||
// inputs
|
||||
input clk_ext, // external 2.457MHz
|
||||
input [1:0] t_i, // timer input
|
||||
@ -27,17 +31,55 @@ module mfp (
|
||||
localparam FIFO_ADDR_BITS = 4;
|
||||
localparam FIFO_DEPTH = (1 << FIFO_ADDR_BITS);
|
||||
|
||||
//
|
||||
// fifo for data from mfp to io controller
|
||||
reg [7:0] fifoOut [FIFO_DEPTH-1:0];
|
||||
reg [FIFO_ADDR_BITS-1:0] writePout, readPout;
|
||||
|
||||
// fifo for data from io-controller to mfp
|
||||
reg [7:0] fifoIn [FIFO_DEPTH-1:0];
|
||||
reg [FIFO_ADDR_BITS-1:0] writePin, readPin;
|
||||
|
||||
assign serial_data_out_available = (readPout != writePout);
|
||||
assign serial_data_out = fifoOut[readPout];
|
||||
|
||||
wire serial_data_in_available = (readPin != writePin) /* synthesis keep */;
|
||||
wire [7:0] serial_data_in_cpu = serial_data_in_available?fifoIn[readPin]:fifoIn[readPin-4'd1];
|
||||
|
||||
// signal "fifo is full" via uart config bit
|
||||
wire serial_data_out_fifo_full = (readPout === (writePout + 4'd1));
|
||||
|
||||
// ---------------- send mfp uart data to io controller ------------
|
||||
// ---------------- mfp uart data to/from io controller ------------
|
||||
reg serial_strobe_inD, serial_strobe_inD2;
|
||||
reg serial_cpu_data_read;
|
||||
|
||||
always @(negedge clk) begin
|
||||
serial_strobe_inD <= serial_strobe_in;
|
||||
serial_strobe_inD2 <= serial_strobe_inD;
|
||||
|
||||
// read on uart data register
|
||||
serial_cpu_data_read <= 1'b0;
|
||||
if(sel && ~ds && rw && (addr == 5'h17))
|
||||
serial_cpu_data_read <= 1'b1;
|
||||
|
||||
if(reset) begin
|
||||
// reset read and write counters
|
||||
readPin <= 4'd0;
|
||||
writePin <= 4'd0;
|
||||
end else begin
|
||||
// store bytes received from IO controller via SPI
|
||||
if(serial_strobe_inD && !serial_strobe_inD2) begin
|
||||
// store data in fifo
|
||||
fifoIn[writePin] <= serial_data_in;
|
||||
writePin <= writePin + 4'd1;
|
||||
end
|
||||
|
||||
// advance read pointer on every cpu read
|
||||
if(serial_cpu_data_read && serial_data_in_available)
|
||||
readPin <= readPin + 4'd1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
reg serial_strobe_outD, serial_strobe_outD2;
|
||||
always @(posedge clk) begin
|
||||
serial_strobe_outD <= serial_strobe_out;
|
||||
@ -184,6 +226,10 @@ wire [3:0] highest_irq_pending =
|
||||
// gpip as output to the cpu (ddr bit == 1 -> gpip pin is output)
|
||||
wire [7:0] gpip_cpu_out = (i & ~ddr) | (gpip & ddr);
|
||||
|
||||
// cpu controllable uart control bits
|
||||
reg [1:0] uart_rx_ctrl;
|
||||
reg [3:0] uart_tx_ctrl;
|
||||
|
||||
// cpu read interface
|
||||
always @(iack, sel, ds, rw, addr, gpip_cpu_out, aer, ddr, ier, ipr, isr, imr,
|
||||
vr, serial_data_out_fifo_full, timera_dat_o, timerb_dat_o,
|
||||
@ -216,7 +262,9 @@ always @(iack, sel, ds, rw, addr, gpip_cpu_out, aer, ddr, ier, ipr, isr, imr,
|
||||
if(addr == 5'h12) dout = timerd_dat_o;
|
||||
|
||||
// uart: report "tx buffer empty" if fifo is not full
|
||||
if(addr == 5'h16) dout = serial_data_out_fifo_full?8'h00:8'h80;
|
||||
if(addr == 5'h15) dout = { serial_data_in_available, 5'b00000 , uart_rx_ctrl};
|
||||
if(addr == 5'h16) dout = { !serial_data_out_fifo_full, 3'b000 , uart_tx_ctrl};
|
||||
if(addr == 5'h17) dout = serial_data_in_cpu;
|
||||
|
||||
end else if(iack) begin
|
||||
dout = irq_vec;
|
||||
@ -234,6 +282,8 @@ reg iackD;
|
||||
// latch to keep irq vector stable during irq ack cycle
|
||||
reg [7:0] irq_vec;
|
||||
|
||||
reg [1:0] usart_irqD;
|
||||
|
||||
always @(negedge clk) begin
|
||||
iackD <= iack;
|
||||
|
||||
@ -246,6 +296,10 @@ always @(negedge clk) begin
|
||||
iD <= aer ^ ((i & ~ti_irq_mask) | (ti_irq & ti_irq_mask));
|
||||
iD2 <= iD;
|
||||
|
||||
// delay usart states to react on changes
|
||||
usart_irqD[0] <= !serial_data_out_fifo_full;
|
||||
usart_irqD[1] <= serial_data_in_available;
|
||||
|
||||
if(reset) begin
|
||||
ipr <= 16'h0000; ier <= 16'h0000;
|
||||
imr <= 16'h0000; isr <= 16'h0000;
|
||||
@ -274,6 +328,10 @@ always @(negedge clk) begin
|
||||
if(!iD[5] && iD2[5] && ier[ 7]) ipr[ 7] <= 1'b1; // dma
|
||||
if(!iD[7] && iD2[7] && ier[15]) ipr[15] <= 1'b1; // mono detect
|
||||
|
||||
// output fifo just became "not full" or input fifo became "not empty"
|
||||
if(!usart_irqD[0] && !serial_data_out_fifo_full && ier[10]) ipr[10] <= 1'b1;
|
||||
if(!usart_irqD[1] && serial_data_in_available && ier[12]) ipr[12] <= 1'b1;
|
||||
|
||||
if(sel && ~ds && ~rw) begin
|
||||
if(addr == 5'h00) gpip <= din;
|
||||
if(addr == 5'h01) aer <= din;
|
||||
@ -298,6 +356,10 @@ always @(negedge clk) begin
|
||||
|
||||
if(addr == 5'h0a) imr[7:0] <= din;
|
||||
if(addr == 5'h0b) vr <= din;
|
||||
|
||||
// ------- uart ------------
|
||||
if(addr == 5'h15) uart_rx_ctrl <= din[1:0];
|
||||
if(addr == 5'h16) uart_tx_ctrl <= din[3:0];
|
||||
|
||||
if(addr == 5'h17) begin
|
||||
fifoOut[writePout] <= din;
|
||||
|
||||
@ -111,9 +111,9 @@ always @(posedge clk_8) begin
|
||||
dtack_timeout <= dtack_timeout + 4'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// no tristate busses exist inside the FPGA. so bus request doesn't do
|
||||
// much more than halting the cpu by suppressing dtack
|
||||
`define BRWIRE
|
||||
@ -305,11 +305,13 @@ mfp mfp (
|
||||
.irq (mfp_irq ),
|
||||
.iack (mfp_iack ),
|
||||
|
||||
// serial/rs232 interface
|
||||
// serial/rs232 interface io-controller<->mfp
|
||||
.serial_data_out_available (serial_data_from_mfp_available),
|
||||
.serial_strobe_out (serial_strobe_from_mfp),
|
||||
.serial_data_out (serial_data_from_mfp),
|
||||
|
||||
.serial_strobe_in (serial_strobe_to_mfp),
|
||||
.serial_data_in (serial_data_to_mfp),
|
||||
|
||||
// input signals
|
||||
.clk_ext (clk_mfp ), // 2.457MHz clock
|
||||
.t_i (mfp_timer_in ), // timer a/b inputs
|
||||
@ -545,7 +547,7 @@ wire clk_8;
|
||||
wire clk_32;
|
||||
wire clk_128;
|
||||
wire clk_mfp;
|
||||
|
||||
|
||||
// use pll
|
||||
clock clock (
|
||||
.areset (1'b0 ), // async reset input
|
||||
@ -667,32 +669,17 @@ wire tg68_uds_S;
|
||||
wire tg68_lds_S;
|
||||
wire tg68_rw_S;
|
||||
reg tg68_as;
|
||||
reg cpu_fast_cycle; // signal indicating that the cpu runs from cache
|
||||
|
||||
always @(posedge clk_8) begin
|
||||
// tg68 core does not provide a as signal, so we generate it
|
||||
tg68_as <= (tg68_busstate != 2'b01) && !br;
|
||||
|
||||
// all other output signals are simply latched to make sure
|
||||
// they don't change within a 8Mhz cycle even if the CPU
|
||||
// advances. This would be a problem if e.g. The CPU would try
|
||||
// to start a bus cycle while the 8Mhz cycle is in progress
|
||||
tg68_dat_out <= tg68_dat_out_S;
|
||||
tg68_adr <= tg68_adr_S;
|
||||
tg68_uds <= tg68_uds_S;
|
||||
tg68_lds <= tg68_lds_S;
|
||||
tg68_rw <= tg68_rw_S;
|
||||
tg68_fc <= tg68_fc_S;
|
||||
end
|
||||
reg cpu_fast_cycle; // signal indicating that the cpu runs from cache, used to calm berr
|
||||
|
||||
// the CPU throttle counter limits the CPU speed to a rate the tg68 core can
|
||||
// handle. With a throttle of "4" the core will run effectively at 32MHz which
|
||||
// is equivalent to ~64MHz on a real 68000. This speed will never be achieved
|
||||
// since memory and peripheral access slows the cpu further
|
||||
localparam CPU_THROTTLE = 4'd5;
|
||||
localparam CPU_THROTTLE = 4'd6;
|
||||
reg [3:0] clkcnt;
|
||||
|
||||
|
||||
reg trigger /* synthesis noprune */;
|
||||
reg panic /* synthesis noprune */;
|
||||
|
||||
always @(posedge clk_128) begin
|
||||
// count 0..15 within a 8MHz cycle
|
||||
@ -707,11 +694,30 @@ always @(posedge clk_128) begin
|
||||
dCacheStore <= 1'b0;
|
||||
cacheUpdate <= 1'b0;
|
||||
trigger <= 1'b0;
|
||||
panic <= 1'b0;
|
||||
|
||||
if(clkcnt == 15) begin
|
||||
// 8Mhz cycle must not start directly after the cpu has been clocked
|
||||
// as the address may not be stable then
|
||||
|
||||
// cpuDoes8MhzCycle has same timing as tg68_as
|
||||
if(!clkena && !br) cpuDoes8MhzCycle <= 1'b1;
|
||||
|
||||
// cpuDoes8MhzCycle has same timing as tg68_as
|
||||
if(clkcnt == 15) begin
|
||||
cpuDoes8MhzCycle <= 1'b1;
|
||||
cpu_fast_cycle <= 1'b0;
|
||||
|
||||
// tg68 core does not provide a as signal, so we generate it
|
||||
tg68_as <= !clkena && (tg68_busstate != 2'b01) && !br;
|
||||
|
||||
// all other output signals are simply latched to make sure
|
||||
// they don't change within a 8Mhz cycle even if the CPU
|
||||
// advances. This would be a problem if e.g. The CPU would try
|
||||
// to start a bus cycle while the 8Mhz cycle is in progress
|
||||
tg68_dat_out <= tg68_dat_out_S;
|
||||
tg68_adr <= tg68_adr_S;
|
||||
tg68_uds <= tg68_uds_S;
|
||||
tg68_lds <= tg68_lds_S;
|
||||
tg68_rw <= tg68_rw_S;
|
||||
tg68_fc <= tg68_fc_S;
|
||||
end
|
||||
|
||||
// evaluate cache one cycle before cpu is allowed to access the bus again
|
||||
@ -731,6 +737,11 @@ always @(posedge clk_128) begin
|
||||
// cpu wants to read and the requested data is available from the cache -> run immediately
|
||||
if((tg68_busstate == 2'b01) || cacheRead) begin
|
||||
clkena <= 1'b1;
|
||||
|
||||
// cpu must never try to fetch instructions from non-mem
|
||||
if((tg68_busstate == 2'b00) && !cpu2mem)
|
||||
panic <= 1'b1;
|
||||
|
||||
cpu_throttle <= CPU_THROTTLE;
|
||||
cpuDoes8MhzCycle <= 1'b0;
|
||||
cpu_fast_cycle <= 1'b1;
|
||||
@ -747,6 +758,10 @@ always @(posedge clk_128) begin
|
||||
cpu_throttle <= CPU_THROTTLE;
|
||||
cpuDoes8MhzCycle <= 1'b0;
|
||||
|
||||
// cpu must never try to fetch instructions from non-mem
|
||||
if((tg68_busstate == 2'b00) && !cpu2mem)
|
||||
panic <= 1'b1;
|
||||
|
||||
// ---------- cache debugging ---------------
|
||||
// if the cache reports a hit, it should be the same data that's also
|
||||
// returned by ram. Otherwise the cache is broken
|
||||
@ -1023,6 +1038,8 @@ wire ikbd_data_from_acia_available;
|
||||
wire [7:0] serial_data_from_mfp;
|
||||
wire serial_strobe_from_mfp;
|
||||
wire serial_data_from_mfp_available;
|
||||
wire [7:0] serial_data_to_mfp;
|
||||
wire serial_strobe_to_mfp;
|
||||
|
||||
//// user io has an extra spi channel outside minimig core ////
|
||||
user_io user_io(
|
||||
@ -1043,6 +1060,8 @@ user_io user_io(
|
||||
.serial_strobe_out(serial_strobe_from_mfp),
|
||||
.serial_data_out(serial_data_from_mfp),
|
||||
.serial_data_out_available(serial_data_from_mfp_available),
|
||||
.serial_strobe_in(serial_strobe_to_mfp),
|
||||
.serial_data_in(serial_data_to_mfp),
|
||||
|
||||
.CORE_TYPE(8'ha3) // mist core id
|
||||
);
|
||||
|
||||
@ -17,10 +17,14 @@ module user_io(
|
||||
// serial data from mfp to io controller
|
||||
output reg serial_strobe_out,
|
||||
input serial_data_out_available,
|
||||
input [7:0] serial_data_out,
|
||||
input [7:0] serial_data_out,
|
||||
|
||||
// serial data from io controller to mfp
|
||||
output reg serial_strobe_in,
|
||||
output reg [7:0] serial_data_in,
|
||||
|
||||
output [1:0] BUTTONS,
|
||||
output [1:0] SWITCHES
|
||||
output [1:0] BUTTONS,
|
||||
output [1:0] SWITCHES
|
||||
);
|
||||
|
||||
reg toggle;
|
||||
@ -82,6 +86,7 @@ module user_io(
|
||||
if(cnt == 9) begin
|
||||
ikbd_strobe_in <= 1'b0;
|
||||
ikbd_strobe_out <= 1'b0;
|
||||
serial_strobe_in <= 1'b0;
|
||||
serial_strobe_out <= 1'b0;
|
||||
end
|
||||
|
||||
@ -92,12 +97,18 @@ module user_io(
|
||||
but_sw[0] <= SPI_MOSI;
|
||||
end
|
||||
|
||||
// send ikbd byte to acia
|
||||
if(cmd == 2) begin
|
||||
ikbd_data_in[7:1] <= sbuf;
|
||||
ikbd_data_in[0] <= SPI_MOSI;
|
||||
ikbd_data_in <= { sbuf, SPI_MOSI };
|
||||
ikbd_strobe_in <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// send serial byte to mfp
|
||||
if(cmd == 4) begin
|
||||
serial_data_in <= { sbuf, SPI_MOSI };
|
||||
serial_strobe_in <= 1'b1;
|
||||
end
|
||||
|
||||
// give strobe after second ikbd byte (toggle ==1)
|
||||
if((cmd == 3) && toggle)
|
||||
ikbd_strobe_out <= 1'b1;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user