1
0
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:
harbaum 2014-02-20 14:43:11 +00:00
parent dedc0946f2
commit 9310d78dcb
4 changed files with 133 additions and 39 deletions

View File

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

View File

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

View File

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

View File

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