added reset logic to uart and CPU

This commit is contained in:
Alan Garfield 2018-01-28 00:23:09 +11:00
parent f081eb674f
commit 0fc84e0b37
4 changed files with 116 additions and 71 deletions

View File

@ -113,7 +113,13 @@ module apple1(
// UART
wire [7:0] uart_dout;
uart my_uart (
uart #(
25000000, 115200, 8
// FIXME:
// If simulated, need to reduce baud rate etc down
// else the UARTs don't work.
// 100, 10, 2
)my_uart (
.clk(clk25),
.reset(reset),

View File

@ -18,7 +18,8 @@
* on the output pads if external memory is required.
*/
`define SIM
// FIXME - Need to make this flag reach out to test bench
//`define SIM
module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );

View File

@ -24,7 +24,7 @@ module async_transmitter(
////////////////////////////////
wire BitTick;
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .enable(TxD_busy), .tick(BitTick));
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .reset(reset), .enable(TxD_busy), .tick(BitTick));
reg [3:0] TxD_state;
reg [7:0] TxD_shift;
@ -72,6 +72,7 @@ endmodule
////////////////////////////////////////////////////////
module async_receiver(
input clk,
input reset,
input RxD,
output reg RxD_data_ready,
output reg [7:0] RxD_data, // data received, valid only (for one clock cycle) when RxD_data_ready is asserted
@ -94,24 +95,38 @@ module async_receiver(
reg [3:0] RxD_state;
wire OversamplingTick;
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .enable(1'b1), .tick(OversamplingTick));
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .reset(reset), .enable(1'b1), .tick(OversamplingTick));
// synchronize RxD to our clk domain
reg [1:0] RxD_sync; // 2'b11
always @(posedge clk) if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};
always @(posedge clk or posedge reset)
begin
if (reset)
RxD_sync <= 2'b11;
else
if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};
end
// and filter it
reg [1:0] Filter_cnt; // 2'b11
reg RxD_bit; // 1'b1
always @(posedge clk)
if(OversamplingTick)
always @(posedge clk or posedge reset)
begin
if (reset)
begin
if(RxD_sync[1]==1'b1 && Filter_cnt!=2'b11) Filter_cnt <= Filter_cnt + 1'd1;
else if(RxD_sync[1]==1'b0 && Filter_cnt!=2'b00) Filter_cnt <= Filter_cnt - 1'd1;
if(Filter_cnt==2'b11) RxD_bit <= 1'b1;
else if(Filter_cnt==2'b00) RxD_bit <= 1'b0;
Filter_cnt <= 2'b11;
RxD_bit <= 1'b1;
end
else
if(OversamplingTick)
begin
if(RxD_sync[1]==1'b1 && Filter_cnt!=2'b11) Filter_cnt <= Filter_cnt + 1'd1;
else if(RxD_sync[1]==1'b0 && Filter_cnt!=2'b00) Filter_cnt <= Filter_cnt - 1'd1;
if(Filter_cnt==2'b11) RxD_bit <= 1'b1;
else if(Filter_cnt==2'b00) RxD_bit <= 1'b0;
end
end
// and decide when is the good time to sample the RxD line
function integer log2(input integer v);
@ -131,30 +146,51 @@ module async_receiver(
wire sampleNow = OversamplingTick && (OversamplingCnt==Oversampling/2-1);
// now we can accumulate the RxD bits in a shift-register
always @(posedge clk)
case(RxD_state)
4'b0000: if(~RxD_bit) RxD_state <= 4'b0001; // start bit found?
4'b0001: if(sampleNow) RxD_state <= 4'b1000; // sync start bit to sampleNow
4'b1000: if(sampleNow) RxD_state <= 4'b1001; // bit 0
4'b1001: if(sampleNow) RxD_state <= 4'b1010; // bit 1
4'b1010: if(sampleNow) RxD_state <= 4'b1011; // bit 2
4'b1011: if(sampleNow) RxD_state <= 4'b1100; // bit 3
4'b1100: if(sampleNow) RxD_state <= 4'b1101; // bit 4
4'b1101: if(sampleNow) RxD_state <= 4'b1110; // bit 5
4'b1110: if(sampleNow) RxD_state <= 4'b1111; // bit 6
4'b1111: if(sampleNow) RxD_state <= 4'b0010; // bit 7
4'b0010: if(sampleNow) RxD_state <= 4'b0000; // stop bit
default: RxD_state <= 4'b0000;
endcase
always @(posedge clk or posedge reset)
begin
if (reset)
RxD_state <= 0;
else
case(RxD_state)
4'b0000: if(~RxD_bit) RxD_state <= 4'b0001; // start bit found?
4'b0001: if(sampleNow) RxD_state <= 4'b1000; // sync start bit to sampleNow
4'b1000: if(sampleNow) RxD_state <= 4'b1001; // bit 0
4'b1001: if(sampleNow) RxD_state <= 4'b1010; // bit 1
4'b1010: if(sampleNow) RxD_state <= 4'b1011; // bit 2
4'b1011: if(sampleNow) RxD_state <= 4'b1100; // bit 3
4'b1100: if(sampleNow) RxD_state <= 4'b1101; // bit 4
4'b1101: if(sampleNow) RxD_state <= 4'b1110; // bit 5
4'b1110: if(sampleNow) RxD_state <= 4'b1111; // bit 6
4'b1111: if(sampleNow) RxD_state <= 4'b0010; // bit 7
4'b0010: if(sampleNow) RxD_state <= 4'b0000; // stop bit
default: RxD_state <= 4'b0000;
endcase
end
always @(posedge clk)
if (sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};
always @(posedge clk)
RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit); // make sure a stop bit is received
always @(posedge clk or posedge reset)
begin
if (reset)
RxD_data <= 0;
else
if (sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};
end
always @(posedge clk or posedge reset)
begin
if (reset)
RxD_data_ready <= 0;
else
RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit); // make sure a stop bit is received
end
reg [l2o+1:0] GapCnt;
always @(posedge clk)
if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1]) GapCnt <= GapCnt + 1'h1;
always @(posedge clk or posedge reset)
begin
if (reset)
GapCnt <= 0;
else
if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1]) GapCnt <= GapCnt + 1'h1;
end
assign RxD_idle = GapCnt[l2o+1];
always @(posedge clk)
@ -164,7 +200,7 @@ endmodule
////////////////////////////////////////////////////////
module BaudTickGen(
input clk, enable,
input clk, reset, enable,
output tick // generate a tick at the specified baud rate * oversampling
);
@ -179,7 +215,13 @@ module BaudTickGen(
localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth)); // this makes sure Inc calculation doesn't overflow
localparam Inc = ((Baud*Oversampling << (AccWidth-ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);
always @(posedge clk) if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];
always @(posedge clk)
begin
if (reset)
Acc <= 0;
else
if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];
end
assign tick = Acc[AccWidth];
endmodule

View File

@ -43,6 +43,7 @@ module uart(
async_receiver #(ClkFrequency, Baud, Oversampling) my_rx(
.clk(clk),
.reset(reset),
.RxD(uart_rx),
.RxD_data_ready(uart_rx_stb),
.RxD_data(rx_data),
@ -96,49 +97,44 @@ module uart(
uart_tx_stb <= 0;
uart_rx_ack <= 0;
if (enable)
case (address)
UART_TX:
begin
case (address)
// UART TX - 0xD012
dout <= {uart_tx_status, 7'd0};
UART_TX:
if (w_en)
begin
// UART TX - 0xD012
dout <= {uart_tx_status, 7'd0};
if (w_en)
// Apple 1 terminal only uses 7 bits, MSB indicates
// terminal has ack'd RX
if (~uart_tx_status && uart_tx_init)
begin
// Apple 1 terminal only uses 7 bits, MSB indicates
// terminal has ack'd RX
if (~uart_tx_status && uart_tx_init)
begin
uart_tx_byte <= {1'b0, din[6:0]};
uart_tx_stb <= 1;
end
else
uart_tx_init <= 1;
uart_tx_byte <= {1'b0, din[6:0]};
uart_tx_stb <= 1;
end
else
uart_tx_init <= 1;
end
UART_RXCR:
begin
// UART RX CR - 0xD011
dout <= {uart_rx_status, 7'b0};
end
UART_RX:
begin
// UART RX - 0xD010
dout <= {uart_rx_status, uart_rx_byte[6:0]};
if (~w_en)
uart_rx_ack <= 1'b1;
end
default:
dout <= 8'b0;
endcase
end
else
dout <= 8'b0;
UART_RXCR:
begin
// UART RX CR - 0xD011
dout <= {uart_rx_status, 7'b0};
end
UART_RX:
begin
// UART RX - 0xD010
dout <= {uart_rx_status, uart_rx_byte[6:0]};
if (~w_en && ~uart_rx_ack && enable)
uart_rx_ack <= 1'b1;
end
default:
dout <= 8'b0;
endcase
end
end
endmodule