1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

357 lines
8.9 KiB
Verilog

// Copyright 2008 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
// baeckler - 04-30-2008
module parallax_gps (
input clk,rst,
input s_din,
output s_dout,
output s_oe,
output reg [7:0] hw_version,
output reg info_valid,
output reg [3:0] sats,
output reg [23:0] gmt_time, // H, M, S
output reg [23:0] gmt_date, // M, D, Y
output reg [39:0] lattitude, // Deg, Min, Min/FFFF, 0=N,1=S
output reg [39:0] longitude, // Deg, Min, Min/FFFF, 0=E,1=W
output reg [15:0] altitude, // 1/10 M
output reg [15:0] speed, // 1/10 knots
output reg [15:0] heading, // 1/10 degrees
// diagnostic information
output [3:0] current_query,
output [3:0] timeouts
);
/////////////////////////////
// SIO regs
/////////////////////////////
reg din_r /* synthesis altera_attribute = "FAST_INPUT_REGISTER=ON" */;
reg dout_r /* synthesis altera_attribute = "FAST_OUTPUT_REGISTER=ON" */;
reg oe_r /* synthesis altera_attribute = "FAST_OUTPUT_ENABLE_REGISTER=ON" */;
wire dout_w;
reg oe_w;
assign s_dout = dout_r;
assign s_oe = oe_r;
always @(posedge clk) begin
din_r <= s_din;
dout_r <= dout_w;
oe_r <= oe_w;
end
/////////////////////////////
// 4800 N81 Uart
/////////////////////////////
reg [7:0] tx_data;
reg tx_data_valid;
wire tx_data_ack,txd;
wire [7:0] rx_data;
wire rx_data_fresh;
reg forced_idle;
assign dout_w = forced_idle | txd;
uart ur (
.clk(clk),
.rst(rst),
.tx_data(tx_data),
.tx_data_valid(tx_data_valid),
.tx_data_ack(tx_data_ack),
.txd(txd),
.rx_data(rx_data),
.rx_data_fresh(rx_data_fresh),
.rxd(din_r)
);
defparam ur .BAUD = 4800;
defparam ur .CLK_HZ = 50_000_000;
/////////////////////////////
// Insert some idle bits
// to deal with RX and TX handoff
// on the same line.
/////////////////////////////
reg [13:0] idle_timer;
reg idle_max;
always @(posedge clk) begin
if (rst) begin
idle_timer <= 0;
idle_max <= 1'b0;
end
else begin
if (forced_idle) idle_timer <= idle_timer + 1'b1;
idle_max <= &idle_timer;
end
end
/////////////////////////////
// capture read bytes
/////////////////////////////
reg [8*5-1:0] rx_history;
always @(posedge clk) begin
if (rst) rx_history <= 0;
else if (rx_data_fresh) begin
rx_history <= (rx_history << 4'h8) | rx_data;
end
end
/////////////////////////////
// commands
/////////////////////////////
reg [3:0] cmd_reg;
reg inc_cmd;
always @(posedge clk) begin
if (rst) cmd_reg <= 0;
else begin
if (inc_cmd) begin
if (cmd_reg == 4'h9) cmd_reg <= 0;
else cmd_reg <= cmd_reg + 1'b1;
end
end
end
/////////////////////////////
// reply timer
// wait until either
// the transmitter finishes 512 dummy chars
// the receiver gets the appropriate number of bytes
/////////////////////////////
reg [9:0] reply_cntr;
reg clr_reply_cntr, reply_cntr_max, prompt_complete;
reg [2:0] expected_bytes;
reg [3:0] timeout_counter;
always @(posedge clk) begin
if (rst) timeout_counter <= 0;
if (rst | clr_reply_cntr) begin
reply_cntr <= 0;
reply_cntr_max <= 0;
if ((cmd_reg == 0) ||
(cmd_reg == 1) ||
(cmd_reg == 2)) expected_bytes <= 3'd1;
else if ((cmd_reg == 3) ||
(cmd_reg == 4)) expected_bytes <= 3'd3;
else if ((cmd_reg == 5) ||
(cmd_reg == 6)) expected_bytes <= 3'd5;
else expected_bytes <= 3'd2;
prompt_complete <= 1'b0;
end
else begin
// make sure you're past the !GPSn prompt string
// before counting bytes
if (rx_history[23:8] == "PS") prompt_complete <= 1'b1;
if (tx_data_ack) reply_cntr <= reply_cntr + 1'b1;
if (rx_data_fresh & prompt_complete) expected_bytes <= expected_bytes - 1'b1;
reply_cntr_max <= 1'b0;
if (&reply_cntr) begin
reply_cntr_max <= 1'b1;
if (!reply_cntr_max) timeout_counter <= timeout_counter + 1'b1;
end
if (~|expected_bytes) begin
reply_cntr_max <= 1'b1;
end
end
end
/////////////////////////////
// Data regs
/////////////////////////////
reg grab_data;
always @(posedge clk) begin
if (rst) begin
hw_version <= 0;
info_valid <= 0;
sats <= 0;
gmt_time <= 0;
gmt_date <= 0;
lattitude <= 0;
longitude <= 0;
altitude <= 0;
speed <= 0;
heading <= 0;
end
else if (grab_data) begin
if (cmd_reg == 4'h0) hw_version <= rx_history [7:0];
if (cmd_reg == 4'h1) info_valid <= rx_history [0];
if (cmd_reg == 4'h2) sats <= rx_history [3:0];
if (cmd_reg == 4'h3) gmt_time <= rx_history [23:0];
if (cmd_reg == 4'h4) gmt_date <= rx_history [23:0];
if (cmd_reg == 4'h5) lattitude <= rx_history [39:0];
if (cmd_reg == 4'h6) longitude <= rx_history [39:0];
if (cmd_reg == 4'h7) altitude <= rx_history [15:0];
if (cmd_reg == 4'h8) speed <= rx_history [15:0];
if (cmd_reg == 4'h9) heading <= rx_history [15:0];
end
end
/////////////////////////////
// Cycle through data requests
/////////////////////////////
reg [3:0] state /* synthesis preserve */;
reg [3:0] next_state;
parameter
ST_INIT = 0,
ST_PRESEND = 1,
ST_PRESEND1 = 2,
ST_PRESEND2 = 3,
ST_PRESEND3 = 4,
ST_SEND = 5,
ST_SEND1 = 6,
ST_SEND2 = 7,
ST_SEND3 = 8,
ST_SEND4 = 9,
ST_TX_PENDING = 10,
ST_PRELISTEN = 11,
ST_LISTEN = 12,
ST_REPORT = 13,
ST_NEXT_CMD = 14;
always @(*) begin
next_state = state;
tx_data = 0;
tx_data_valid = 0;
oe_w = 1'b0;
clr_reply_cntr = 1'b0;
inc_cmd = 1'b0;
grab_data = 1'b0;
forced_idle = 1'b0;
case (state)
ST_INIT : begin
next_state = ST_PRESEND;
end
ST_PRESEND : begin
// force the line to idle for 1 char
oe_w = 1'b1;
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_PRESEND1;
end
ST_PRESEND1 : begin
// force the line to idle for 1 char
oe_w = 1'b1;
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_PRESEND2;
end
ST_PRESEND2 : begin
// force the line to idle for 1 char
oe_w = 1'b1;
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_PRESEND3;
end
ST_PRESEND3 : begin
// force the line to idle for 1 char
oe_w = 1'b1;
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_SEND;
end
ST_SEND : begin
oe_w = 1'b1;
tx_data = "!";
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_SEND1;
end
ST_SEND1 : begin
oe_w = 1'b1;
tx_data = "G";
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_SEND2;
end
ST_SEND2 : begin
oe_w = 1'b1;
tx_data = "P";
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_SEND3;
end
ST_SEND3 : begin
oe_w = 1'b1;
tx_data = "S";
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_SEND4;
end
ST_SEND4 : begin
oe_w = 1'b1;
tx_data = {4'h0,cmd_reg};
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_TX_PENDING;
end
ST_TX_PENDING : begin
// wait until the last command
// byte is done sending
oe_w = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_PRELISTEN;
end
ST_PRELISTEN : begin
// force the line to idle for 1 char
clr_reply_cntr = 1'b1;
oe_w = 1'b1;
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (tx_data_ack) next_state = ST_LISTEN;
end
ST_LISTEN : begin
// wait until reply complete or timeout
forced_idle = 1'b1;
tx_data = 0;
tx_data_valid = 1'b1;
if (reply_cntr_max) next_state = ST_REPORT;
end
ST_REPORT : begin
grab_data = 1'b1;
next_state = ST_NEXT_CMD;
end
ST_NEXT_CMD : begin
inc_cmd = 1'b1;
next_state = ST_PRESEND;
end
endcase
end
always @(posedge clk) begin
if (rst) state <= ST_INIT;
else state <= next_state;
end
// diagnostic info
assign current_query = cmd_reg;
assign timeouts = timeout_counter;
endmodule