URL
https://opencores.org/ocsvn/rs232_syscon/rs232_syscon/trunk
Subversion Repositories rs232_syscon
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/tags/V001/rs232_syscon.v
File deleted
/tags/V001/rs232_syscon.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
tags/V001/rs232_syscon.doc
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: tags/V001/b13c_environment.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/V001/b13c_environment.zip
===================================================================
--- tags/V001/b13c_environment.zip (revision 3)
+++ tags/V001/b13c_environment.zip (nonexistent)
tags/V001/b13c_environment.zip
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/rs232_syscon.v
===================================================================
--- trunk/rs232_syscon.v (revision 3)
+++ trunk/rs232_syscon.v (nonexistent)
@@ -1,1168 +0,0 @@
-//-------------------------------------------------------------------------------------
-//
-// Author: John Clayton
-// Date : June 25, 2001
-// Update: 6/25/01 copied this file from ps2_mouse.v (pared down).
-// Update: 6/07/01 Finished initial coding efforts.
-// Update: 7/19/01 First compilation. Added master_br_o and master_bg_i;
-// Update: 7/25/01 Testing. Eliminated msg_active signal. Changed serial.v
-// to reflect new handshaking (i.e. "load_request" is now a
-// periodic pulse of tx_clk_1x from rs232_tx...)
-// Update: 7/30/01 Began coding m2 state machine. Defined response codes.
-// Update: 8/01/01 After some testing with m2, merged m2 into m1. Eliminated
-// response codes.
-// Update: 8/02/01 Tested & measured the single "combined" state machine's
-// performance, and "it was found wanting." (The 49.152MHz
-// clock frequency was too fast for it...) Created clk_s
-// at 49.152/2 MHz, and this worked.
-// Update: 8/03/01 Added counter loop to "execute" and "bus_granted" states
-// so that multiple bus cycles are generated, at sequential
-// addresses. However, the qty field is not cleared before
-// being loaded with new characters, which causes problems.
-// Update: 8/07/01 Finished debugging. The read print formatting is now
-// correct, and the unit appears to operate correctly.
-// Many hours were spent puzzling over how to make this work.
-// Removed port "debug".
-// Update: 8/24/01 Added "master_stb_i" and "master_we_i" inputs and logic.
-// Update: 12/13/01 For memory_sizer.v, I lowered the frequency of clk_s down
-// to 49.152/4 MHz, so I changed the CLOCK_FACTOR from 8 to 4
-// on the rs232 transciever, and this worked fine.
-// Update: 9/09/02 Incorporated the "autobaud_with_tracking" module so that
-// the serial clock is generated automatically, no matter
-// what frequency clk_i is used. The user simply needs to
-// press "enter" from the terminal program to synchronize
-// the baud rate generator. Changing BAUD rates on the fly
-// is also permitted, simply change to a new BAUD rate in the
-// terminal program and hit enter.
-// Update:11/26/02 Changed the string constants to binary representation
-// (Just to eliminate warnings in XST.)
-//
-//
-//
-//
-//
-// Description
-//-------------------------------------------------------------------------------------
-// This is a state-machine driven rs232 serial port interface to a "Wishbone"
-// type of bus. It is intended to be used as a "Wishbone system controller"
-// for debugging purposes. Specifically, the unit allows the user to send
-// text commands to the "rs232_syscon" unit, in order to generate read and
-// write cycles on the Wishbone compatible bus. The command structure is
-// quite terse and spartan in nature, this is for the sake of the logic itself.
-// Because the menu-driven command structure is supported without the use of
-// dedicated memory blocks (in order to maintain cross-platform portability
-// as much as possible) the menus and command responses were kept as small
-// as possible. In most cases, the responses from the unit to the user
-// consist of a "newline" and one or two visible characters. The command
-// structure consists of the following commands and responses:
-//
-// Command Syntax Purpose
-// --------------- ---------------------------------------
-// w aaaa dddd xx Write data "dddd" starting at address "aaaa"
-// perform this "xx" times at sequential addresses.
-// (The quantity field is optional, default is 1).
-// r aaaa xx Read data starting from address "aaaa."
-// Perform this "xx" times at sequential addresses.
-// (The quantity field is optional, default is 1).
-// i Send a reset pulse to the system. (initialize).
-//
-// Response from rs232_syscon Meaning
-// -------------------------- ---------------------------------------
-// OK Command received and performed. No errors.
-// ? Command buffer full, without receiving "enter."
-// C? Command not recognized.
-// A? Address field syntax error.
-// D? Data field syntax error.
-// Q? Quantity field syntax error.
-// ! No "ack_i", or else "err_i" received from bus.
-// B! No "bg_i" received from master.
-//
-// NOTES on the operation of this unit:
-//
-// - The unit generates a command prompt which is "-> ".
-// - Capitalization is not important.
-// - Each command is terminated by the "enter" key (0x0d character).
-// Commands are executed as soon as "enter" is received.
-// - Trailing parameters need not be re-entered. Their values will
-// remain the same as their previous settings.
-// - Use of the backspace key is supported, so mistakes can be corrected.
-// - The length of the command line is limited to a fixed number of
-// characters, as configured by parameter.
-// - Fields are separated by white space, including "tab" and/or "space"
-// - All numerical fields are interpreted as hexadecimal numbers.
-// Decimal is not supported.
-// - Numerical field values are retained between commands. If a "r" is issued
-// without any fields following it, the previous values will be used. A
-// set of "quantity" reads will take place at sequential addresses.
-// If a "w" is issued without any fields following it, the previous data
-// value will be written "quantity" times at sequential addresses, starting
-// from the next location beyond where the last command ended.
-// - If the user does not wish to use "ack" functionality, simply tie the
-// "ack_i" input to 1b'1, and then the ! response will never be generated.
-// - The data which is read in by the "r" command is displayed using lines
-// which begin with the address, followed by the data fields. The number
-// of data fields displayed per line (following the address) is adjustable
-// by setting a parameter. No other display format adjustments can be made.
-// - There is currently only a single watchdog timer. It begins to count at
-// the time a user hits "enter" to execute a command. If the bus is granted
-// and the ack is received before the expiration of the timer, then the
-// cycle will complete normally. Therefore, the watchdog timeout value
-// needs to include time for the request and granting of the bus, in
-// addition to the time needed for the actual bus cycle to complete.
-//
-//
-// Currently, there is only a single indicator (stb_o) generated during bus
-// output cycles which are generated from this unit.
-// The user can easily implement decoding logic based upon adr_o and stb_o
-// which would serve as multiple "stb_o" type signals for different cores
-// which would be sharing the same bus.
-//
-// The dat_io bus supported by this module is a tri-state type of bus. The
-// Wishbone spec. allows for this type of bus (see Wishbone spec. pg. 66).
-// However, if separate dat_o and dat_i busses are desired, they can be added
-// to the module without too much trouble. Supposedly the only difference
-// between the two forms of data bus is that one of them avoids using tri-state
-// at the cost of doubling the number of interconnects used to carry data back
-// and forth... Some people say that tri-state should be avoided for use
-// in internal busses in ASICs. Maybe they are right.
-// But in FPGAs tri-state seems to work pretty well, even for internal busses.
-//
-// Parameters are provided to configure the width of the different command
-// fields. To simplify the logic for binary to hexadecimal conversion, these
-// parameters allow adjustment in units of 1 hex digit, not anything smaller.
-// If your bus has 10 bits, for instance, simply set the address width to 3
-// which produces 12 bits, and then just don't use the 2 msbs of address
-// output.
-//
-// No support for the optional Wishbone "retry" (rty_i) input is provided at
-// this time.
-// No support for "tagn_o" bits is provided at this time, although a register
-// might be added external to this module in order to implement to tag bits.
-// No BLOCK or RMW cycles are supported currently, so cyc_o is equivalent to
-// stb_o...
-// The output busses are not tri-stated. The user may add tri-state buffers
-// external to the module, using "stb_o" to enable the buffer outputs.
-//
-//-------------------------------------------------------------------------------------
-
-
-`define NIBBLE_SIZE 4 // Number of bits in one nibble
-
-// The command register has these values
-`define CMD_0 0 // Unused command
-`define CMD_I 1 // Initialize (or reset)
-`define CMD_R 2 // Read
-`define CMD_W 3 // Write
-
-module rs232_syscon (
- clk_i,
- reset_i,
- ack_i,
- err_i,
- master_bg_i,
- master_adr_i,
- master_stb_i,
- master_we_i,
- rs232_rxd_i,
- dat_io,
- rst_o,
- master_br_o,
- stb_o,
- cyc_o,
- adr_o,
- we_o,
- rs232_txd_o
- );
-
-
-// Parameters
-
-// The timer value can be from [0 to (2^WATCHDOG_TIMER_BITS_PP)-1] inclusive.
-// RD_FIELDS_PP can be from [0 to (2^RD_FIELD_CTR_BITS_PP)-1] inclusive.
-// Ensure that (2^CHAR_COUNT_BITS_PP) >= CMD_BUFFER_SIZE_PP.
-// The setting of CMD_BUFFER_SIZE_PP should be large enough to hold the
-// largest command, obviously.
-// Ensure that (2^RD_DIGIT_COUNT_BITS_PP) is greater than or equal to the
-// larger of {ADR_DIGITS_PP,DAT_DIGITS_PP}.
-parameter ADR_DIGITS_PP = 4; // # of hex digits for address.
-parameter DAT_DIGITS_PP = 4; // # of hex digits for data.
-parameter QTY_DIGITS_PP = 2; // # of hex digits for quantity.
-parameter CMD_BUFFER_SIZE_PP = 32; // # of chars in the command buffer.
-parameter CMD_PTR_BITS_PP = 4; // # of Bits in command buffer ptr.
-parameter WATCHDOG_TIMER_VALUE_PP = 200; // # of sys_clks before ack expected.
-parameter WATCHDOG_TIMER_BITS_PP = 8; // # of bits needed for timer.
-parameter RD_FIELDS_PP = 8; // # of fields/line (when qty > 1).
-parameter RD_FIELD_COUNT_BITS_PP = 3; // # of bits in the fields counter.
-parameter RD_DIGIT_COUNT_BITS_PP = 2; // # of bits in the digits counter.
-
-
-// State encodings, provided as parameters
-// for flexibility to the one instantiating the module.
-// In general, the default values need not be changed.
-
-// There is one state machines: m1.
-// "default" state upon power-up and configuration is:
-// "m1_initial_state"
-
-parameter m1_initial_state = 5'h00;
-parameter m1_send_ok = 5'h01; // Sends OK
-parameter m1_send_prompt = 5'h02; // Sends "-> "
-parameter m1_check_received_char = 5'h03;
-parameter m1_send_crlf = 5'h04; // Sends cr,lf
-parameter m1_parse_error_indicator_crlf = 5'h05; // Sends cr,lf
-parameter m1_parse_error_indicator = 5'h06; // Sends ?
-parameter m1_ack_error_indicator = 5'h07; // Sends !
-parameter m1_bg_error_indicator = 5'h08; // Sends B!
-parameter m1_cmd_error_indicator = 5'h09; // Sends C?
-parameter m1_adr_error_indicator = 5'h0a; // Sends A?
-parameter m1_dat_error_indicator = 5'h0b; // Sends D?
-parameter m1_qty_error_indicator = 5'h0c; // Sends Q?
-parameter m1_scan_command = 5'h10;
-parameter m1_scan_adr_whitespace = 5'h11;
-parameter m1_get_adr_field = 5'h12;
-parameter m1_scan_dat_whitespace = 5'h13;
-parameter m1_get_dat_field = 5'h14;
-parameter m1_scan_qty_whitespace = 5'h15;
-parameter m1_get_qty_field = 5'h16;
-parameter m1_start_execution = 5'h17;
-parameter m1_request_bus = 5'h18;
-parameter m1_bus_granted = 5'h19;
-parameter m1_execute = 5'h1a;
-parameter m1_rd_send_adr_sr = 5'h1b;
-parameter m1_rd_send_separator = 5'h1c;
-parameter m1_rd_send_dat_sr = 5'h1d;
-parameter m1_rd_send_space = 5'h1e;
-parameter m1_rd_send_crlf = 5'h1f;
-
-// I/O declarations
-input clk_i; // System clock input
-input reset_i; // Reset signal for this module
-input ack_i; // Ack input from Wishbone "slaves"
-input err_i; // Err input from Wishbone "slaves"
-input master_bg_i; // Bus Grant (grants this module the bus)
- // Address bus input from "normal" Wishbone
- // master (i.e. from processor)
-input [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] master_adr_i;
-input master_stb_i; // bus cycle signal from "normal" bus master
-input master_we_i; // write enable from "normal" bus master
-input rs232_rxd_i; // Serial data from debug host terminal.
- // Data bus (tri-state, to save interconnect)
-inout [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_io;
-
-output rst_o; // Rst output to Wishbone "slaves"
-output master_br_o; // Bus request to normal master device.
-output stb_o; // Bus cycle indicator to Wishbone "slaves"
-output cyc_o; // Bus cycle indicator to Wishbone "slaves"
- // Address bus output to Wishbone "slaves"
-output [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_o;
-output we_o; // Write enable to Wishbone "slaves"
-output rs232_txd_o; // Serial transmit data to debug host terminal
-
-reg rst_o;
-reg master_br_o;
-
-// Internal signal declarations
-wire watchdog_timer_done; // High when watchdog timer is expired
-wire rd_addr_field_done; // High when displayed addr field is complete
-wire rd_data_field_done; // High when displayed data field is complete
-wire rd_line_done; // High when displayed line is complete
-wire char_is_enter; // High when cmd_buffer[char_count] is enter.
-wire char_is_whitespace; // High when cmd_buffer[char_count] is whitespace.
-wire char_is_num; // High when cmd_buffer[char_count] is 0..9
-wire char_is_a_f; // High when cmd_buffer[char_count] is a..f
-wire char_is_hex; // High when cmd_buffer[char_count] is a hex char.
-wire char_is_r; // High when cmd_buffer[char_count] is r.
-wire char_is_w; // High when cmd_buffer[char_count] is w.
-wire char_is_i; // High when cmd_buffer[char_count] is i.
-wire rx_char_is_enter; // High when rs232_rx_char is enter.
-wire rx_char_is_backspace; // High when rs232_rx_char is backspace.
-wire [4:0] msg_pointer; // Determines message position or address.
-wire [3:0] hex_digit; // This is the digit to be stored.
-
-reg rs232_echo; // High == echo char's received.
-reg [7:0] msg_char; // Selected response message character.
-reg [4:0] msg_base; // Added to msg_offset to form msg_pointer.
-reg [4:0] msg_offset; // Offset from start of message.
-reg reset_msg_offset; // High == set message offset to zero
-reg incr_msg_offset; // Used for output messages.
-reg cmd_i; // Sets command.
-reg cmd_r; // Sets command.
-reg cmd_w; // Sets command.
-reg shift_rd_adr; // Shifts the rd_adr_sr by one character.
-reg store_adr; // Allows adr_sr to store hex_digit.
-reg store_dat; // Allows dat_sr to store hex_digit.
-reg store_qty; // Allows qty_sr to store hex_digit.
-reg reset_adr; // Clears adr_sr
-reg reset_dat; // Clears dat_sr
-reg reset_qty; // Clears qty_sr
-reg init_qty; // Sets qty_sr to 1
-reg capture_dat; // Puts dat_io into dat_sr for later display.
-
- // For the buses
-wire [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_ptr; // = adr_sr + adr_offset
-
-reg stb_l; // "local" stb signal (to distinguish from stb_o)
-reg we_l; // "local" we signal (to distinguish from we_o)
-
-reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] rd_adr_sr; // sr for printing addresses
-reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_sr; // "nibble" shift register
-reg [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_sr; // "nibble" shift register
-reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] qty_sr; // "nibble" shift register
-reg [1:0] command;
-reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] adr_offset; // counts from 0 to qty_sr
-reg reset_adr_offset;
-reg incr_adr_offset;
-
- // For the command buffer
-reg [CMD_PTR_BITS_PP-1:0] cmd_ptr; // Offset from start of command.
-reg reset_cmd_ptr; // High == set command pointer to zero.
-reg incr_cmd_ptr; // Used for "write port" side of the command buffer
-reg decr_cmd_ptr; // Used for "write port" side of the command buffer
-reg cmd_buffer_write;
-reg [7:0] cmd_buffer [0:CMD_BUFFER_SIZE_PP-1];
-wire [7:0] cmd_char;
-wire [7:0] lc_cmd_char; // Lowercase version of cmd_char
-
- // For the state machine
-reg [4:0] m1_state;
-reg [4:0] m1_next_state;
-
- // For various counters
-reg reset_rd_field_count;
-reg reset_rd_digit_count;
-reg incr_rd_field_count;
-reg incr_rd_digit_count;
-reg [RD_FIELD_COUNT_BITS_PP-1:0] rd_field_count; // "fields displayed"
-reg [RD_DIGIT_COUNT_BITS_PP-1:0] rd_digit_count; // "digits displayed"
-reg [WATCHDOG_TIMER_BITS_PP-1:0] watchdog_timer_count;
-reg reset_watchdog;
-
- // For the rs232 interface
-wire serial_clk;
-wire [2:0] rs232_rx_error;
-wire rs232_tx_load;
-wire rs232_tx_load_request;
-wire rs232_rx_data_ready;
-wire [7:0] rs232_rx_char;
-wire [7:0] rs232_tx_char; // Either rs232_rx_char or msg_char
-
-//--------------------------------------------------------------------------
-// Instantiations
-//--------------------------------------------------------------------------
-
-
-// These defines are for the rs232 interface
-`define START_BITS 1
-`define DATA_BITS 8
-`define STOP_BITS 1
-`define CLOCK_FACTOR 8
-
-// This module generates a serial BAUD clock automatically.
-// The unit synchronizes on the carriage return character, so the user
-// only needs to press the "enter" key for serial communications to start
-// working, no matter what BAUD rate and clk_i frequency are used!
-auto_baud_with_tracking #(
- `CLOCK_FACTOR, // CLOCK_FACTOR_PP
- 16 // LOG2_MAX_COUNT_PP
- )
- clock_unit_2
- (
- .clk_i(clk_i),
- .reset_i(reset_i),
- .serial_dat_i(rs232_rxd_i),
- .auto_baud_locked_o(),
- .baud_clk_o(serial_clk)
- );
-
-// A transmitter, which asserts load_request at the end of the currently
-// transmitted word. The tx_clk must be a "clock enable" (narrow positive
-// pulse) which occurs at 16x the desired transmit rate. If load_request
-// is connected directly to load, the unit will transmit continuously.
-rs232tx #(
- `START_BITS, // start_bits
- `DATA_BITS, // data_bits
- `STOP_BITS, // stop_bits (add intercharacter delay...)
- `CLOCK_FACTOR // clock_factor
- )
- rs232_tx_block // instance name
- (
- .clk(clk_i),
- .tx_clk(serial_clk),
- .reset(reset_i),
- .load(rs232_tx_load),
- .data(rs232_tx_char),
- .load_request(rs232_tx_load_request),
- .txd(rs232_txd_o)
- );
-
-// A receiver, which asserts "word_ready" to indicate a received word.
-// Asserting "read_word" will cause "word_ready" to go low again if it was high.
-// The character is held in the output register, during the time the next
-// character is coming in.
-rs232rx #(
- `START_BITS, // start_bits
- `DATA_BITS, // data_bits
- `STOP_BITS, // stop_bits
- `CLOCK_FACTOR // clock_factor
- )
- rs232_rx_block // instance name
- (
- .clk(clk_i),
- .rx_clk(serial_clk),
- .reset(reset_i || (| rs232_rx_error)),
- .rxd(rs232_rxd_i),
- .read(rs232_tx_load),
- .data(rs232_rx_char),
- .data_ready(rs232_rx_data_ready),
- .error_over_run(rs232_rx_error[0]),
- .error_under_run(rs232_rx_error[1]),
- .error_all_low(rs232_rx_error[2])
- );
-
-//`undef START_BITS
-//`undef DATA_BITS
-//`undef STOP_BITS
-//`undef CLOCK_FACTOR
-
-
-//--------------------------------------------------------------------------
-// Module code
-//--------------------------------------------------------------------------
-
-assign adr_o = master_bg_i?adr_ptr:master_adr_i;
-assign we_o = master_bg_i?we_l:master_we_i;
-assign stb_o = master_bg_i?stb_l:master_stb_i;
-
-
-assign dat_io = (master_bg_i && we_l && stb_l)?
- dat_sr:{`NIBBLE_SIZE*DAT_DIGITS_PP{1'bZ}};
-
-// Temporary
-assign cyc_o = stb_o; // Separate cyc_o is not yet supported!
-
-
-// This is the adress offset counter
-always @(posedge clk_i)
-begin
- if (reset_i || reset_adr_offset) adr_offset <= 0;
- else if (incr_adr_offset) adr_offset <= adr_offset + 1;
-end
-// This forms the adress pointer which is used on the bus.
-assign adr_ptr = adr_sr + adr_offset;
-
-
-// This is the ROM for the ASCII characters to be transmitted.
-always @(msg_pointer)
-begin
- case (msg_pointer) // synthesis parallel_case
- 5'b00000 : msg_char <= 8'h30; // "0"; // Hexadecimal characters
- 5'b00001 : msg_char <= 8'h31; // "1";
- 5'b00010 : msg_char <= 8'h32; // "2";
- 5'b00011 : msg_char <= 8'h33; // "3";
- 5'b00100 : msg_char <= 8'h34; // "4";
- 5'b00101 : msg_char <= 8'h35; // "5";
- 5'b00110 : msg_char <= 8'h36; // "6";
- 5'b00111 : msg_char <= 8'h37; // "7";
- 5'b01000 : msg_char <= 8'h38; // "8";
- 5'b01001 : msg_char <= 8'h39; // "9";
- 5'b01010 : msg_char <= 8'h41; // "A"; // Address error indication
- 5'b01011 : msg_char <= 8'h42; // "B";
- 5'b01100 : msg_char <= 8'h43; // "C"; // Command error indication
- 5'b01101 : msg_char <= 8'h44; // "D"; // Data error indication
- 5'b01110 : msg_char <= 8'h45; // "E";
- 5'b01111 : msg_char <= 8'h46; // "F";
- 5'b10000 : msg_char <= 8'h20; // " "; // Space
- 5'b10001 : msg_char <= 8'h3A; // ":"; // Colon
- 5'b10010 : msg_char <= 8'h20; // " "; // Space
- 5'b10011 : msg_char <= 8'h3F; // "?"; // Parse error indication
- 5'b10100 : msg_char <= 8'h21; // "!"; // ack_i/err_i error indication
- 5'b10101 : msg_char <= 8'h4F; // "O"; // "All is well" message
- 5'b10110 : msg_char <= 8'h4B; // "K";
- 5'b10111 : msg_char <= 8'h0D; // Carriage return & line feed
- 5'b11000 : msg_char <= 8'h0A;
- 5'b11001 : msg_char <= 8'h2D; // "-"; // Command Prompt
- 5'b11010 : msg_char <= 8'h3E; // ">";
- 5'b11011 : msg_char <= 8'h20; // " ";
- 5'b11100 : msg_char <= 8'h51; // "Q"; // Quantity error indication
- default : msg_char <= 8'h3D; // "=";
- endcase
-end
-
-// This logic determines when to load a transmit character.
-assign rs232_tx_load = rs232_echo?
- (rs232_rx_data_ready && rs232_tx_load_request):rs232_tx_load_request;
-
-// This is the counter for incrementing, decrementing or resetting the
-// message pointer.
-always @(posedge clk_i)
-begin
- if (reset_i || reset_msg_offset) msg_offset <= 0;
- else if (incr_msg_offset) msg_offset <= msg_offset + 1;
-end
-assign msg_pointer = msg_offset + msg_base;
-
-
-
-// This is the mux which selects whether to echo back the characters
-// received (as during the entering of a command) or to send back response
-// characters.
-assign rs232_tx_char = (rs232_echo)?rs232_rx_char:msg_char;
-
-
-// These assigments are for detecting whether the received rs232 character is
-// anything of special interest.
-assign rx_char_is_enter = (rs232_rx_char == 8'h0d);
-assign rx_char_is_backspace = (rs232_rx_char == 8'h08);
-
-
-
-// This is state machine m1. It handles receiving the command line, including
-// backspaces, and prints error/response messages. It also parses and
-// executes the commands.
-
-// State register
-always @(posedge clk_i)
-begin : m1_state_register
- if (reset_i) m1_state <= m1_initial_state; // perform reset for rest of system
- else m1_state <= m1_next_state;
-end
-
-// State transition logic
-always @(m1_state
- or rx_char_is_enter
- or rx_char_is_backspace
- or msg_offset
- or cmd_ptr
- or rs232_tx_load
- or char_is_whitespace
- or char_is_hex
- or char_is_enter
- or char_is_i
- or char_is_r
- or char_is_w
- or command
- or master_bg_i
- or watchdog_timer_done
- or err_i
- or ack_i
- or adr_offset
- or qty_sr
- or dat_sr
- or rd_adr_sr
- or rd_field_count
- or rd_digit_count
- )
-begin : m1_state_logic
-
- // Default values for outputs. The individual states can override these.
- msg_base <= 5'b0;
- reset_msg_offset <= 0;
- incr_msg_offset <= 0;
- rs232_echo <= 0;
- rst_o <= 0;
- we_l <= 0;
- stb_l <= 0;
- cmd_buffer_write <= 0;
- reset_cmd_ptr <= 0;
- incr_cmd_ptr <= 0;
- decr_cmd_ptr <= 0;
- master_br_o <= 0;
- cmd_r <= 0;
- cmd_w <= 0;
- cmd_i <= 0;
- shift_rd_adr <= 0;
- store_adr <= 0; // enables storing hex chars in adr_sr (shift)
- store_dat <= 0; // enables storing hex chars in dat_sr (shift)
- store_qty <= 0; // enables storing hex chars in qty_sr (shift)
- reset_adr <= 0;
- reset_dat <= 0;
- reset_qty <= 0;
- init_qty <= 0;
- capture_dat <= 0; // enables capturing bus data in dat_sr (load)
- incr_adr_offset <= 0;
- reset_adr_offset <= 0;
- reset_watchdog <= 0;
- incr_rd_field_count <= 0;
- incr_rd_digit_count <= 0;
- reset_rd_field_count <= 0;
- reset_rd_digit_count <= 0;
-
- case (m1_state) // synthesis parallel_case
-
- m1_initial_state :
- begin
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 15) && rs232_tx_load) begin
- m1_next_state <= m1_send_prompt;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_initial_state;
- end
-
- m1_send_ok :
- begin
- msg_base <= 5'b10101; // Address of the OK message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 1) && rs232_tx_load) begin
- m1_next_state <= m1_send_prompt;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_send_ok;
- end
-
- m1_send_prompt :
- begin
- msg_base <= 5'b10111; // Address of the cr,lf,prompt message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 4) && rs232_tx_load) begin
- m1_next_state <= m1_check_received_char;
- reset_cmd_ptr <= 1;
- end
- else m1_next_state <= m1_send_prompt;
- end
-
- // This state always leads to activating the parser...
- m1_send_crlf :
- begin
- msg_base <= 5'b10111; // Address of the cr/lf message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 1) && rs232_tx_load) begin
- m1_next_state <= m1_scan_command;
- reset_cmd_ptr <= 1;
- end
- else m1_next_state <= m1_send_crlf;
- end
-
- m1_check_received_char :
- begin
- rs232_echo <= 1; // Allow echoing of characters
- if (rx_char_is_backspace && rs232_tx_load)
- begin
- m1_next_state <= m1_check_received_char;
- decr_cmd_ptr <= 1; // This effectively eliminates the last char
- end
- else if (rx_char_is_enter && rs232_tx_load)
- begin
- m1_next_state <= m1_send_crlf;
- cmd_buffer_write <= 1; // Store the enter as "marker" for parsing
- reset_msg_offset <= 1;
- end
- else if (rs232_tx_load && (cmd_ptr == CMD_BUFFER_SIZE_PP-1))
- begin
- m1_next_state <= m1_parse_error_indicator_crlf;
- reset_msg_offset <= 1;
- reset_cmd_ptr <= 1;
- end
- else if (rs232_tx_load)
- begin
- incr_cmd_ptr <= 1;
- cmd_buffer_write <= 1;
- m1_next_state <= m1_check_received_char;
- end
- else m1_next_state <= m1_check_received_char;
- end
-
- m1_bg_error_indicator :
- begin
- msg_base <= 5'b01011; // Address of the B character
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load) begin
- m1_next_state <= m1_ack_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_bg_error_indicator;
- end
-
- m1_ack_error_indicator :
- begin
- msg_base <= 5'b10100; // Address of the ! error message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load) begin
- m1_next_state <= m1_send_prompt;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_ack_error_indicator;
- end
-
- // This state is used when the line is too long...
- m1_parse_error_indicator_crlf :
- begin
- msg_base <= 5'b10111; // Address of the cr,lf message.
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 1) && rs232_tx_load) begin
- m1_next_state <= m1_parse_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_parse_error_indicator_crlf;
- end
-
- m1_parse_error_indicator :
- begin
- msg_base <= 5'b10011; // Address of the ? message.
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load) begin
- m1_next_state <= m1_send_prompt;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_parse_error_indicator;
- end
-
- m1_cmd_error_indicator :
- begin
- msg_base <= 5'b01100; // Address of 'C'
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load) begin
- m1_next_state <= m1_parse_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_cmd_error_indicator;
- end
-
- m1_adr_error_indicator :
- begin
- msg_base <= 5'b01010; // Address of 'A'
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load)
- begin
- m1_next_state <= m1_parse_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_adr_error_indicator;
- end
-
- m1_dat_error_indicator :
- begin
- msg_base <= 5'b01101; // Address of 'D'
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load)
- begin
- m1_next_state <= m1_parse_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_dat_error_indicator;
- end
-
- m1_qty_error_indicator :
- begin
- msg_base <= 5'b11100; // Address of 'Q'
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load)
- begin
- m1_next_state <= m1_parse_error_indicator;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_qty_error_indicator;
- end
-
- // The following states are for parsing and executing the command.
-
- // This state takes care of leading whitespace before the command
- m1_scan_command :
- begin
- rs232_echo <= 1; // Don't send message characters
- reset_msg_offset <= 1; // This one reset should cover all of the
- // parse/exec. states. With rs232_echo
- // on, and no receive characters arrive,
- // then the msg_offset will remain reset.
- // This means the watchdog timer can take
- // a long time, if need be, during exec.
- // (NOTE: It might be better to disable
- // the echoing of rx chars during these
- // states.)
- init_qty <= 1; // Set qty = 1 by default. That can be
- // overridden later, if the command has
- // a different qty field.
- if (char_is_whitespace) begin
- m1_next_state <= m1_scan_command;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_r) begin
- m1_next_state <= m1_scan_adr_whitespace;
- incr_cmd_ptr <= 1;
- cmd_r <= 1;
- end
- else if (char_is_w) begin
- m1_next_state <= m1_scan_adr_whitespace;
- incr_cmd_ptr <= 1;
- cmd_w <= 1;
- end
- else if (char_is_i) begin
- m1_next_state <= m1_start_execution;
- cmd_i <= 1;
- end
- else m1_next_state <= m1_cmd_error_indicator;
- end
-
- // The only way to determine the end of a valid field is to find
- // whitespace. Therefore, char_is_whitespace must be used as an exit
- // condition from the "get_xxx_field" states. So, this state is used to
- // scan through any leading whitespace prior to it.
- m1_scan_adr_whitespace :
- begin
- rs232_echo <= 1; // Don't send message characters
- if (char_is_whitespace) begin
- m1_next_state <= m1_scan_adr_whitespace;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_enter) m1_next_state <= m1_start_execution;
- else begin
- m1_next_state <= m1_get_adr_field;
- reset_adr <= 1;
- end
- end
-
- m1_get_adr_field :
- begin
- rs232_echo <= 1; // Don't send message characters
- if (char_is_hex) begin
- m1_next_state <= m1_get_adr_field;
- store_adr <= 1;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_whitespace) begin // Normal exit
- m1_next_state <= m1_scan_dat_whitespace;
- end
- else if (char_is_enter) m1_next_state <= m1_start_execution;
- else m1_next_state <= m1_adr_error_indicator;
- end
-
- m1_scan_dat_whitespace :
- begin
- rs232_echo <= 1; // Don't send message characters
- // There is no DAT field for reads, so skip it.
- if (command == `CMD_R) m1_next_state <= m1_scan_qty_whitespace;
- else if (char_is_whitespace) begin
- m1_next_state <= m1_scan_dat_whitespace;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_enter) m1_next_state <= m1_start_execution;
- else begin
- m1_next_state <= m1_get_dat_field;
- reset_dat <= 1;
- end
- end
-
- m1_get_dat_field :
- begin
- rs232_echo <= 1; // Don't send message characters
- if (char_is_hex) begin
- m1_next_state <= m1_get_dat_field;
- store_dat <= 1;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_whitespace) begin // Normal exit
- m1_next_state <= m1_scan_qty_whitespace;
- end
- else if (char_is_enter) m1_next_state <= m1_start_execution;
- else m1_next_state <= m1_dat_error_indicator;
- end
-
- m1_scan_qty_whitespace :
- begin
- rs232_echo <= 1; // Don't send message characters
- if (char_is_whitespace) begin
- m1_next_state <= m1_scan_qty_whitespace;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_enter) m1_next_state <= m1_start_execution;
- else begin
- m1_next_state <= m1_get_qty_field;
- reset_qty <= 1;
- end
- end
-
- m1_get_qty_field :
- begin
- rs232_echo <= 1; // Don't send message characters
- if (char_is_hex) begin
- m1_next_state <= m1_get_qty_field;
- store_qty <= 1;
- incr_cmd_ptr <= 1;
- end
- else if (char_is_whitespace || char_is_enter) begin // Normal exit
- m1_next_state <= m1_start_execution;
- end
- else m1_next_state <= m1_qty_error_indicator;
- end
-
- // This state seeks to obtain master_bg_i, which grants the bus to
- // rs232_syscon.
- m1_start_execution :
- begin
- rs232_echo <= 1; // Don't send message characters
- reset_watchdog <= 1; // Reset the timer.
- reset_adr_offset <= 1; // Reset the address offset.
- reset_rd_field_count <= 1; // Reset the rd_field_count.
- m1_next_state <= m1_request_bus;
- end
-
- m1_request_bus :
- begin
- rs232_echo <= 1; // Don't send message characters
- master_br_o <= 1; // Request the bus.
- if (master_bg_i) m1_next_state <= m1_bus_granted;
- else if (watchdog_timer_done) begin
- m1_next_state <= m1_bg_error_indicator;
- end
- else m1_next_state <= m1_request_bus;
- end
-
- m1_bus_granted :
- begin
- rs232_echo <= 1; // Don't send message characters
- master_br_o <= 1; // Keep holding the bus
- reset_watchdog <= 1; // Reset the timer.
- if (adr_offset != qty_sr) m1_next_state <= m1_execute;
- else m1_next_state <= m1_send_ok;
- end
-
- // This single state does reset/write/read depending upon the value
- // contained in "command"!
- m1_execute :
- begin
- rs232_echo <= 1; // Don't send message characters
- master_br_o <= 1; // Keep holding the bus
- stb_l <= 1'b1; // Show that a bus cycle is happening
- case (command) // Assert the appropriate signals
- `CMD_I : rst_o <= 1;
- `CMD_R : capture_dat <= ack_i;
- `CMD_W : we_l <= 1;
- default: ;
- endcase
- if (watchdog_timer_done || err_i) begin
- m1_next_state <= m1_ack_error_indicator;
- end
- else if (ack_i
- && (command == `CMD_R)
- && (rd_field_count == 0)
- )
- begin
- m1_next_state <= m1_rd_send_adr_sr; // Leads to a new address line.
- reset_rd_digit_count <= 1;
- incr_adr_offset <= 1; // move to the next address
- end
- else if (ack_i && (command == `CMD_R)) begin
- m1_next_state <= m1_rd_send_dat_sr; // Leads to a new data field.
- reset_rd_digit_count <= 1;
- reset_msg_offset <= 1;
- incr_adr_offset <= 1; // move to the next address
- end
- else if (ack_i) begin
- m1_next_state <= m1_bus_granted; // continue to the next cycle
- incr_adr_offset <= 1; // move to the next address
- end
- else m1_next_state <= m1_execute;
- end
-
- m1_rd_send_adr_sr :
- begin
- msg_base <= {1'b0,rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:
- `NIBBLE_SIZE*(ADR_DIGITS_PP-1)]};
- if ((rd_digit_count == ADR_DIGITS_PP-1) && rs232_tx_load) begin
- m1_next_state <= m1_rd_send_separator;
- reset_msg_offset <= 1;
- end
- else if (rs232_tx_load) begin
- shift_rd_adr <= 1;
- incr_rd_digit_count <= 1;
- m1_next_state <= m1_rd_send_adr_sr;
- end
- else m1_next_state <= m1_rd_send_adr_sr;
- end
-
- m1_rd_send_separator :
- begin
- msg_base <= 5'b10000; // Address of the separator message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 2) && rs232_tx_load)
- begin
- m1_next_state <= m1_rd_send_dat_sr;
- reset_rd_digit_count <= 1;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_rd_send_separator;
- end
-
- m1_rd_send_dat_sr :
- begin
- msg_base <= {1'b0,dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:
- `NIBBLE_SIZE*(DAT_DIGITS_PP-1)]};
- if (
- (rd_digit_count == DAT_DIGITS_PP-1)
- && (rd_field_count == RD_FIELDS_PP-1)
- && rs232_tx_load
- )
- begin
- m1_next_state <= m1_rd_send_crlf;
- reset_rd_field_count <= 1;
- end
- else if ((rd_digit_count == DAT_DIGITS_PP-1) && rs232_tx_load) begin
- m1_next_state <= m1_rd_send_space;
- incr_rd_field_count <= 1;
- end
- else if (rs232_tx_load) begin
- store_dat <= 1;
- incr_rd_digit_count <= 1;
- m1_next_state <= m1_rd_send_dat_sr;
- end
- else m1_next_state <= m1_rd_send_dat_sr;
- end
-
- m1_rd_send_space :
- begin
- msg_base <= 5'b10000; // Address of the space
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 0) && rs232_tx_load) begin
- m1_next_state <= m1_bus_granted;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_rd_send_space;
- end
-
- m1_rd_send_crlf :
- begin
- msg_base <= 5'b10111; // Address of the cr/lf message
- incr_msg_offset <= rs232_tx_load;
- if ((msg_offset == 1) && rs232_tx_load) begin
- m1_next_state <= m1_bus_granted;
- reset_msg_offset <= 1;
- end
- else m1_next_state <= m1_rd_send_crlf;
- end
-
- default : m1_next_state <= m1_initial_state;
- endcase
-end
-
-
-// This is the counter for incrementing or loading the cmd_ptr
-always @(posedge clk_i)
-begin
- if (reset_i || reset_cmd_ptr) cmd_ptr <= 0;
- else if (decr_cmd_ptr) cmd_ptr <= cmd_ptr - 1;
- else if (incr_cmd_ptr) cmd_ptr <= cmd_ptr + 1;
-end
-
-
-// This is the command buffer writing section
-always @(posedge clk_i)
-begin
- if (rs232_echo && cmd_buffer_write) cmd_buffer[cmd_ptr] <= rs232_rx_char;
-end
-// This is the command buffer reading section
-assign cmd_char = cmd_buffer[cmd_ptr];
-assign lc_cmd_char = (cmd_buffer[cmd_ptr] | 8'h20); // lowercase
-
-
-
-// These assigments are for detecting whether the cmd_char is
-// anything of special interest.
-assign char_is_enter = (cmd_char == 8'h0d); // enter
-assign char_is_whitespace = (
- (cmd_char == 8'h20) // space
- || (cmd_char == 8'h09) // tab
- );
-assign char_is_num = ((cmd_char>=8'h30)&&(cmd_char<=8'h39));
-assign char_is_a_f = ((lc_cmd_char>=8'h61)&&(lc_cmd_char<=8'h66));
-assign char_is_hex = ( char_is_num || char_is_a_f );
-assign char_is_r = (lc_cmd_char == 8'h72); // "r"
-assign char_is_w = (lc_cmd_char == 8'h77); // "w"
-assign char_is_i = (lc_cmd_char == 8'h69); // "i"
-
-assign hex_digit = char_is_num?cmd_char[3:0]:(cmd_char[3:0]+9);
-
-// This is the command register. It stores the type of command to execute.
-// This is so that the state machine can parse address, data and qty
-// into "generic" storage locations, and then when it executes the command,
-// it refers back to this register in order to determine what type of
-// operation to perform.
-
-always @(posedge clk_i)
-begin
- if (reset_i) command <= `CMD_0;
- else if (cmd_i) command <= `CMD_I;
- else if (cmd_r) command <= `CMD_R;
- else if (cmd_w) command <= `CMD_W;
-end
-
-// This is the "nibble" shift register for the address which is sent character
-// by character to the user. It is loaded each time the adr_offset is
-// incremented, in order to save the previous address for use in printing
-// to the user.
-always @(posedge clk_i)
-begin
- if (reset_i || reset_adr) rd_adr_sr <= 0;
- else if (incr_adr_offset) rd_adr_sr <= adr_ptr;
- else if (shift_rd_adr) begin
- rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
- rd_adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
- rd_adr_sr[`NIBBLE_SIZE-1:0] <= {`NIBBLE_SIZE{1'b0}};
- end
-end
-
-// These are the "nibble" shift registers. They handle loading the
-// hexadecimal digits from the command line.
-always @(posedge clk_i)
-begin
- if (reset_i || reset_adr) adr_sr <= 0;
- else if (store_adr) begin
- adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
- adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
- adr_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
- end
-end
-
-always @(posedge clk_i)
-begin
- if (reset_i || reset_dat) dat_sr <= 0;
- else if (capture_dat) dat_sr <= dat_io;
- else if (store_dat) begin
- dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:`NIBBLE_SIZE] <=
- dat_sr[`NIBBLE_SIZE*(DAT_DIGITS_PP-1)-1:0];
- dat_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
- end
-end
-
-always @(posedge clk_i)
-begin
- if (reset_i || reset_qty) qty_sr <= 0;
- else if (init_qty) qty_sr <= 1;
- else if (store_qty) begin
- qty_sr[`NIBBLE_SIZE*QTY_DIGITS_PP-1:`NIBBLE_SIZE] <=
- qty_sr[`NIBBLE_SIZE*(QTY_DIGITS_PP-1)-1:0];
- qty_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
- end
-end
-
-// This is the rd_digit_count counter. It is used for counting digits
-// displayed of both the adr_sr and dat_sr, so it must be able to count up
-// to the extent of the larger of the two...
-always @(posedge clk_i)
-begin
- if (reset_i || reset_rd_digit_count) rd_digit_count <= 0;
- else if (incr_rd_digit_count) rd_digit_count <= rd_digit_count + 1;
-end
-
-// This is the rd_field_count counter. It is used for counting dat_sr fields
-// displayed per line.
-always @(posedge clk_i)
-begin
- if (reset_i || reset_rd_field_count) rd_field_count <= 0;
- else if (incr_rd_field_count) rd_field_count <= rd_field_count + 1;
-end
-
-
-// This is the watchdog timer counter
-// The watchdog timer is always "enabled" to operate.
-always @(posedge clk_i)
-begin
- if (reset_i || reset_watchdog) watchdog_timer_count <= 0;
- else if (~watchdog_timer_done)
- watchdog_timer_count <= watchdog_timer_count + 1;
-end
-assign watchdog_timer_done = (watchdog_timer_count==WATCHDOG_TIMER_VALUE_PP);
-
-
-endmodule
-
-
Index: trunk/rs232_syscon.doc
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/rs232_syscon.doc
===================================================================
--- trunk/rs232_syscon.doc (revision 3)
+++ trunk/rs232_syscon.doc (nonexistent)
trunk/rs232_syscon.doc
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/b13c_environment.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/b13c_environment.zip
===================================================================
--- trunk/b13c_environment.zip (revision 3)
+++ trunk/b13c_environment.zip (nonexistent)
trunk/b13c_environment.zip
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: rs232_syscon/trunk/b13c_environment.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rs232_syscon/trunk/b13c_environment.zip
===================================================================
--- rs232_syscon/trunk/b13c_environment.zip (nonexistent)
+++ rs232_syscon/trunk/b13c_environment.zip (revision 4)
rs232_syscon/trunk/b13c_environment.zip
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rs232_syscon/trunk/rs232_syscon.doc
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rs232_syscon/trunk/rs232_syscon.doc
===================================================================
--- rs232_syscon/trunk/rs232_syscon.doc (nonexistent)
+++ rs232_syscon/trunk/rs232_syscon.doc (revision 4)
rs232_syscon/trunk/rs232_syscon.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rs232_syscon/trunk/rs232_syscon.v
===================================================================
--- rs232_syscon/trunk/rs232_syscon.v (nonexistent)
+++ rs232_syscon/trunk/rs232_syscon.v (revision 4)
@@ -0,0 +1,1168 @@
+//-------------------------------------------------------------------------------------
+//
+// Author: John Clayton
+// Date : June 25, 2001
+// Update: 6/25/01 copied this file from ps2_mouse.v (pared down).
+// Update: 6/07/01 Finished initial coding efforts.
+// Update: 7/19/01 First compilation. Added master_br_o and master_bg_i;
+// Update: 7/25/01 Testing. Eliminated msg_active signal. Changed serial.v
+// to reflect new handshaking (i.e. "load_request" is now a
+// periodic pulse of tx_clk_1x from rs232_tx...)
+// Update: 7/30/01 Began coding m2 state machine. Defined response codes.
+// Update: 8/01/01 After some testing with m2, merged m2 into m1. Eliminated
+// response codes.
+// Update: 8/02/01 Tested & measured the single "combined" state machine's
+// performance, and "it was found wanting." (The 49.152MHz
+// clock frequency was too fast for it...) Created clk_s
+// at 49.152/2 MHz, and this worked.
+// Update: 8/03/01 Added counter loop to "execute" and "bus_granted" states
+// so that multiple bus cycles are generated, at sequential
+// addresses. However, the qty field is not cleared before
+// being loaded with new characters, which causes problems.
+// Update: 8/07/01 Finished debugging. The read print formatting is now
+// correct, and the unit appears to operate correctly.
+// Many hours were spent puzzling over how to make this work.
+// Removed port "debug".
+// Update: 8/24/01 Added "master_stb_i" and "master_we_i" inputs and logic.
+// Update: 12/13/01 For memory_sizer.v, I lowered the frequency of clk_s down
+// to 49.152/4 MHz, so I changed the CLOCK_FACTOR from 8 to 4
+// on the rs232 transciever, and this worked fine.
+// Update: 9/09/02 Incorporated the "autobaud_with_tracking" module so that
+// the serial clock is generated automatically, no matter
+// what frequency clk_i is used. The user simply needs to
+// press "enter" from the terminal program to synchronize
+// the baud rate generator. Changing BAUD rates on the fly
+// is also permitted, simply change to a new BAUD rate in the
+// terminal program and hit enter.
+// Update:11/26/02 Changed the string constants to binary representation
+// (Just to eliminate warnings in XST.)
+//
+//
+//
+//
+//
+// Description
+//-------------------------------------------------------------------------------------
+// This is a state-machine driven rs232 serial port interface to a "Wishbone"
+// type of bus. It is intended to be used as a "Wishbone system controller"
+// for debugging purposes. Specifically, the unit allows the user to send
+// text commands to the "rs232_syscon" unit, in order to generate read and
+// write cycles on the Wishbone compatible bus. The command structure is
+// quite terse and spartan in nature, this is for the sake of the logic itself.
+// Because the menu-driven command structure is supported without the use of
+// dedicated memory blocks (in order to maintain cross-platform portability
+// as much as possible) the menus and command responses were kept as small
+// as possible. In most cases, the responses from the unit to the user
+// consist of a "newline" and one or two visible characters. The command
+// structure consists of the following commands and responses:
+//
+// Command Syntax Purpose
+// --------------- ---------------------------------------
+// w aaaa dddd xx Write data "dddd" starting at address "aaaa"
+// perform this "xx" times at sequential addresses.
+// (The quantity field is optional, default is 1).
+// r aaaa xx Read data starting from address "aaaa."
+// Perform this "xx" times at sequential addresses.
+// (The quantity field is optional, default is 1).
+// i Send a reset pulse to the system. (initialize).
+//
+// Response from rs232_syscon Meaning
+// -------------------------- ---------------------------------------
+// OK Command received and performed. No errors.
+// ? Command buffer full, without receiving "enter."
+// C? Command not recognized.
+// A? Address field syntax error.
+// D? Data field syntax error.
+// Q? Quantity field syntax error.
+// ! No "ack_i", or else "err_i" received from bus.
+// B! No "bg_i" received from master.
+//
+// NOTES on the operation of this unit:
+//
+// - The unit generates a command prompt which is "-> ".
+// - Capitalization is not important.
+// - Each command is terminated by the "enter" key (0x0d character).
+// Commands are executed as soon as "enter" is received.
+// - Trailing parameters need not be re-entered. Their values will
+// remain the same as their previous settings.
+// - Use of the backspace key is supported, so mistakes can be corrected.
+// - The length of the command line is limited to a fixed number of
+// characters, as configured by parameter.
+// - Fields are separated by white space, including "tab" and/or "space"
+// - All numerical fields are interpreted as hexadecimal numbers.
+// Decimal is not supported.
+// - Numerical field values are retained between commands. If a "r" is issued
+// without any fields following it, the previous values will be used. A
+// set of "quantity" reads will take place at sequential addresses.
+// If a "w" is issued without any fields following it, the previous data
+// value will be written "quantity" times at sequential addresses, starting
+// from the next location beyond where the last command ended.
+// - If the user does not wish to use "ack" functionality, simply tie the
+// "ack_i" input to 1b'1, and then the ! response will never be generated.
+// - The data which is read in by the "r" command is displayed using lines
+// which begin with the address, followed by the data fields. The number
+// of data fields displayed per line (following the address) is adjustable
+// by setting a parameter. No other display format adjustments can be made.
+// - There is currently only a single watchdog timer. It begins to count at
+// the time a user hits "enter" to execute a command. If the bus is granted
+// and the ack is received before the expiration of the timer, then the
+// cycle will complete normally. Therefore, the watchdog timeout value
+// needs to include time for the request and granting of the bus, in
+// addition to the time needed for the actual bus cycle to complete.
+//
+//
+// Currently, there is only a single indicator (stb_o) generated during bus
+// output cycles which are generated from this unit.
+// The user can easily implement decoding logic based upon adr_o and stb_o
+// which would serve as multiple "stb_o" type signals for different cores
+// which would be sharing the same bus.
+//
+// The dat_io bus supported by this module is a tri-state type of bus. The
+// Wishbone spec. allows for this type of bus (see Wishbone spec. pg. 66).
+// However, if separate dat_o and dat_i busses are desired, they can be added
+// to the module without too much trouble. Supposedly the only difference
+// between the two forms of data bus is that one of them avoids using tri-state
+// at the cost of doubling the number of interconnects used to carry data back
+// and forth... Some people say that tri-state should be avoided for use
+// in internal busses in ASICs. Maybe they are right.
+// But in FPGAs tri-state seems to work pretty well, even for internal busses.
+//
+// Parameters are provided to configure the width of the different command
+// fields. To simplify the logic for binary to hexadecimal conversion, these
+// parameters allow adjustment in units of 1 hex digit, not anything smaller.
+// If your bus has 10 bits, for instance, simply set the address width to 3
+// which produces 12 bits, and then just don't use the 2 msbs of address
+// output.
+//
+// No support for the optional Wishbone "retry" (rty_i) input is provided at
+// this time.
+// No support for "tagn_o" bits is provided at this time, although a register
+// might be added external to this module in order to implement to tag bits.
+// No BLOCK or RMW cycles are supported currently, so cyc_o is equivalent to
+// stb_o...
+// The output busses are not tri-stated. The user may add tri-state buffers
+// external to the module, using "stb_o" to enable the buffer outputs.
+//
+//-------------------------------------------------------------------------------------
+
+
+`define NIBBLE_SIZE 4 // Number of bits in one nibble
+
+// The command register has these values
+`define CMD_0 0 // Unused command
+`define CMD_I 1 // Initialize (or reset)
+`define CMD_R 2 // Read
+`define CMD_W 3 // Write
+
+module rs232_syscon (
+ clk_i,
+ reset_i,
+ ack_i,
+ err_i,
+ master_bg_i,
+ master_adr_i,
+ master_stb_i,
+ master_we_i,
+ rs232_rxd_i,
+ dat_io,
+ rst_o,
+ master_br_o,
+ stb_o,
+ cyc_o,
+ adr_o,
+ we_o,
+ rs232_txd_o
+ );
+
+
+// Parameters
+
+// The timer value can be from [0 to (2^WATCHDOG_TIMER_BITS_PP)-1] inclusive.
+// RD_FIELDS_PP can be from [0 to (2^RD_FIELD_CTR_BITS_PP)-1] inclusive.
+// Ensure that (2^CHAR_COUNT_BITS_PP) >= CMD_BUFFER_SIZE_PP.
+// The setting of CMD_BUFFER_SIZE_PP should be large enough to hold the
+// largest command, obviously.
+// Ensure that (2^RD_DIGIT_COUNT_BITS_PP) is greater than or equal to the
+// larger of {ADR_DIGITS_PP,DAT_DIGITS_PP}.
+parameter ADR_DIGITS_PP = 4; // # of hex digits for address.
+parameter DAT_DIGITS_PP = 4; // # of hex digits for data.
+parameter QTY_DIGITS_PP = 2; // # of hex digits for quantity.
+parameter CMD_BUFFER_SIZE_PP = 32; // # of chars in the command buffer.
+parameter CMD_PTR_BITS_PP = 4; // # of Bits in command buffer ptr.
+parameter WATCHDOG_TIMER_VALUE_PP = 200; // # of sys_clks before ack expected.
+parameter WATCHDOG_TIMER_BITS_PP = 8; // # of bits needed for timer.
+parameter RD_FIELDS_PP = 8; // # of fields/line (when qty > 1).
+parameter RD_FIELD_COUNT_BITS_PP = 3; // # of bits in the fields counter.
+parameter RD_DIGIT_COUNT_BITS_PP = 2; // # of bits in the digits counter.
+
+
+// State encodings, provided as parameters
+// for flexibility to the one instantiating the module.
+// In general, the default values need not be changed.
+
+// There is one state machines: m1.
+// "default" state upon power-up and configuration is:
+// "m1_initial_state"
+
+parameter m1_initial_state = 5'h00;
+parameter m1_send_ok = 5'h01; // Sends OK
+parameter m1_send_prompt = 5'h02; // Sends "-> "
+parameter m1_check_received_char = 5'h03;
+parameter m1_send_crlf = 5'h04; // Sends cr,lf
+parameter m1_parse_error_indicator_crlf = 5'h05; // Sends cr,lf
+parameter m1_parse_error_indicator = 5'h06; // Sends ?
+parameter m1_ack_error_indicator = 5'h07; // Sends !
+parameter m1_bg_error_indicator = 5'h08; // Sends B!
+parameter m1_cmd_error_indicator = 5'h09; // Sends C?
+parameter m1_adr_error_indicator = 5'h0a; // Sends A?
+parameter m1_dat_error_indicator = 5'h0b; // Sends D?
+parameter m1_qty_error_indicator = 5'h0c; // Sends Q?
+parameter m1_scan_command = 5'h10;
+parameter m1_scan_adr_whitespace = 5'h11;
+parameter m1_get_adr_field = 5'h12;
+parameter m1_scan_dat_whitespace = 5'h13;
+parameter m1_get_dat_field = 5'h14;
+parameter m1_scan_qty_whitespace = 5'h15;
+parameter m1_get_qty_field = 5'h16;
+parameter m1_start_execution = 5'h17;
+parameter m1_request_bus = 5'h18;
+parameter m1_bus_granted = 5'h19;
+parameter m1_execute = 5'h1a;
+parameter m1_rd_send_adr_sr = 5'h1b;
+parameter m1_rd_send_separator = 5'h1c;
+parameter m1_rd_send_dat_sr = 5'h1d;
+parameter m1_rd_send_space = 5'h1e;
+parameter m1_rd_send_crlf = 5'h1f;
+
+// I/O declarations
+input clk_i; // System clock input
+input reset_i; // Reset signal for this module
+input ack_i; // Ack input from Wishbone "slaves"
+input err_i; // Err input from Wishbone "slaves"
+input master_bg_i; // Bus Grant (grants this module the bus)
+ // Address bus input from "normal" Wishbone
+ // master (i.e. from processor)
+input [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] master_adr_i;
+input master_stb_i; // bus cycle signal from "normal" bus master
+input master_we_i; // write enable from "normal" bus master
+input rs232_rxd_i; // Serial data from debug host terminal.
+ // Data bus (tri-state, to save interconnect)
+inout [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_io;
+
+output rst_o; // Rst output to Wishbone "slaves"
+output master_br_o; // Bus request to normal master device.
+output stb_o; // Bus cycle indicator to Wishbone "slaves"
+output cyc_o; // Bus cycle indicator to Wishbone "slaves"
+ // Address bus output to Wishbone "slaves"
+output [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_o;
+output we_o; // Write enable to Wishbone "slaves"
+output rs232_txd_o; // Serial transmit data to debug host terminal
+
+reg rst_o;
+reg master_br_o;
+
+// Internal signal declarations
+wire watchdog_timer_done; // High when watchdog timer is expired
+wire rd_addr_field_done; // High when displayed addr field is complete
+wire rd_data_field_done; // High when displayed data field is complete
+wire rd_line_done; // High when displayed line is complete
+wire char_is_enter; // High when cmd_buffer[char_count] is enter.
+wire char_is_whitespace; // High when cmd_buffer[char_count] is whitespace.
+wire char_is_num; // High when cmd_buffer[char_count] is 0..9
+wire char_is_a_f; // High when cmd_buffer[char_count] is a..f
+wire char_is_hex; // High when cmd_buffer[char_count] is a hex char.
+wire char_is_r; // High when cmd_buffer[char_count] is r.
+wire char_is_w; // High when cmd_buffer[char_count] is w.
+wire char_is_i; // High when cmd_buffer[char_count] is i.
+wire rx_char_is_enter; // High when rs232_rx_char is enter.
+wire rx_char_is_backspace; // High when rs232_rx_char is backspace.
+wire [4:0] msg_pointer; // Determines message position or address.
+wire [3:0] hex_digit; // This is the digit to be stored.
+
+reg rs232_echo; // High == echo char's received.
+reg [7:0] msg_char; // Selected response message character.
+reg [4:0] msg_base; // Added to msg_offset to form msg_pointer.
+reg [4:0] msg_offset; // Offset from start of message.
+reg reset_msg_offset; // High == set message offset to zero
+reg incr_msg_offset; // Used for output messages.
+reg cmd_i; // Sets command.
+reg cmd_r; // Sets command.
+reg cmd_w; // Sets command.
+reg shift_rd_adr; // Shifts the rd_adr_sr by one character.
+reg store_adr; // Allows adr_sr to store hex_digit.
+reg store_dat; // Allows dat_sr to store hex_digit.
+reg store_qty; // Allows qty_sr to store hex_digit.
+reg reset_adr; // Clears adr_sr
+reg reset_dat; // Clears dat_sr
+reg reset_qty; // Clears qty_sr
+reg init_qty; // Sets qty_sr to 1
+reg capture_dat; // Puts dat_io into dat_sr for later display.
+
+ // For the buses
+wire [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_ptr; // = adr_sr + adr_offset
+
+reg stb_l; // "local" stb signal (to distinguish from stb_o)
+reg we_l; // "local" we signal (to distinguish from we_o)
+
+reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] rd_adr_sr; // sr for printing addresses
+reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_sr; // "nibble" shift register
+reg [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_sr; // "nibble" shift register
+reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] qty_sr; // "nibble" shift register
+reg [1:0] command;
+reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] adr_offset; // counts from 0 to qty_sr
+reg reset_adr_offset;
+reg incr_adr_offset;
+
+ // For the command buffer
+reg [CMD_PTR_BITS_PP-1:0] cmd_ptr; // Offset from start of command.
+reg reset_cmd_ptr; // High == set command pointer to zero.
+reg incr_cmd_ptr; // Used for "write port" side of the command buffer
+reg decr_cmd_ptr; // Used for "write port" side of the command buffer
+reg cmd_buffer_write;
+reg [7:0] cmd_buffer [0:CMD_BUFFER_SIZE_PP-1];
+wire [7:0] cmd_char;
+wire [7:0] lc_cmd_char; // Lowercase version of cmd_char
+
+ // For the state machine
+reg [4:0] m1_state;
+reg [4:0] m1_next_state;
+
+ // For various counters
+reg reset_rd_field_count;
+reg reset_rd_digit_count;
+reg incr_rd_field_count;
+reg incr_rd_digit_count;
+reg [RD_FIELD_COUNT_BITS_PP-1:0] rd_field_count; // "fields displayed"
+reg [RD_DIGIT_COUNT_BITS_PP-1:0] rd_digit_count; // "digits displayed"
+reg [WATCHDOG_TIMER_BITS_PP-1:0] watchdog_timer_count;
+reg reset_watchdog;
+
+ // For the rs232 interface
+wire serial_clk;
+wire [2:0] rs232_rx_error;
+wire rs232_tx_load;
+wire rs232_tx_load_request;
+wire rs232_rx_data_ready;
+wire [7:0] rs232_rx_char;
+wire [7:0] rs232_tx_char; // Either rs232_rx_char or msg_char
+
+//--------------------------------------------------------------------------
+// Instantiations
+//--------------------------------------------------------------------------
+
+
+// These defines are for the rs232 interface
+`define START_BITS 1
+`define DATA_BITS 8
+`define STOP_BITS 1
+`define CLOCK_FACTOR 8
+
+// This module generates a serial BAUD clock automatically.
+// The unit synchronizes on the carriage return character, so the user
+// only needs to press the "enter" key for serial communications to start
+// working, no matter what BAUD rate and clk_i frequency are used!
+auto_baud_with_tracking #(
+ `CLOCK_FACTOR, // CLOCK_FACTOR_PP
+ 16 // LOG2_MAX_COUNT_PP
+ )
+ clock_unit_2
+ (
+ .clk_i(clk_i),
+ .reset_i(reset_i),
+ .serial_dat_i(rs232_rxd_i),
+ .auto_baud_locked_o(),
+ .baud_clk_o(serial_clk)
+ );
+
+// A transmitter, which asserts load_request at the end of the currently
+// transmitted word. The tx_clk must be a "clock enable" (narrow positive
+// pulse) which occurs at 16x the desired transmit rate. If load_request
+// is connected directly to load, the unit will transmit continuously.
+rs232tx #(
+ `START_BITS, // start_bits
+ `DATA_BITS, // data_bits
+ `STOP_BITS, // stop_bits (add intercharacter delay...)
+ `CLOCK_FACTOR // clock_factor
+ )
+ rs232_tx_block // instance name
+ (
+ .clk(clk_i),
+ .tx_clk(serial_clk),
+ .reset(reset_i),
+ .load(rs232_tx_load),
+ .data(rs232_tx_char),
+ .load_request(rs232_tx_load_request),
+ .txd(rs232_txd_o)
+ );
+
+// A receiver, which asserts "word_ready" to indicate a received word.
+// Asserting "read_word" will cause "word_ready" to go low again if it was high.
+// The character is held in the output register, during the time the next
+// character is coming in.
+rs232rx #(
+ `START_BITS, // start_bits
+ `DATA_BITS, // data_bits
+ `STOP_BITS, // stop_bits
+ `CLOCK_FACTOR // clock_factor
+ )
+ rs232_rx_block // instance name
+ (
+ .clk(clk_i),
+ .rx_clk(serial_clk),
+ .reset(reset_i || (| rs232_rx_error)),
+ .rxd(rs232_rxd_i),
+ .read(rs232_tx_load),
+ .data(rs232_rx_char),
+ .data_ready(rs232_rx_data_ready),
+ .error_over_run(rs232_rx_error[0]),
+ .error_under_run(rs232_rx_error[1]),
+ .error_all_low(rs232_rx_error[2])
+ );
+
+//`undef START_BITS
+//`undef DATA_BITS
+//`undef STOP_BITS
+//`undef CLOCK_FACTOR
+
+
+//--------------------------------------------------------------------------
+// Module code
+//--------------------------------------------------------------------------
+
+assign adr_o = master_bg_i?adr_ptr:master_adr_i;
+assign we_o = master_bg_i?we_l:master_we_i;
+assign stb_o = master_bg_i?stb_l:master_stb_i;
+
+
+assign dat_io = (master_bg_i && we_l && stb_l)?
+ dat_sr:{`NIBBLE_SIZE*DAT_DIGITS_PP{1'bZ}};
+
+// Temporary
+assign cyc_o = stb_o; // Separate cyc_o is not yet supported!
+
+
+// This is the adress offset counter
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr_offset) adr_offset <= 0;
+ else if (incr_adr_offset) adr_offset <= adr_offset + 1;
+end
+// This forms the adress pointer which is used on the bus.
+assign adr_ptr = adr_sr + adr_offset;
+
+
+// This is the ROM for the ASCII characters to be transmitted.
+always @(msg_pointer)
+begin
+ case (msg_pointer) // synthesis parallel_case
+ 5'b00000 : msg_char <= 8'h30; // "0"; // Hexadecimal characters
+ 5'b00001 : msg_char <= 8'h31; // "1";
+ 5'b00010 : msg_char <= 8'h32; // "2";
+ 5'b00011 : msg_char <= 8'h33; // "3";
+ 5'b00100 : msg_char <= 8'h34; // "4";
+ 5'b00101 : msg_char <= 8'h35; // "5";
+ 5'b00110 : msg_char <= 8'h36; // "6";
+ 5'b00111 : msg_char <= 8'h37; // "7";
+ 5'b01000 : msg_char <= 8'h38; // "8";
+ 5'b01001 : msg_char <= 8'h39; // "9";
+ 5'b01010 : msg_char <= 8'h41; // "A"; // Address error indication
+ 5'b01011 : msg_char <= 8'h42; // "B";
+ 5'b01100 : msg_char <= 8'h43; // "C"; // Command error indication
+ 5'b01101 : msg_char <= 8'h44; // "D"; // Data error indication
+ 5'b01110 : msg_char <= 8'h45; // "E";
+ 5'b01111 : msg_char <= 8'h46; // "F";
+ 5'b10000 : msg_char <= 8'h20; // " "; // Space
+ 5'b10001 : msg_char <= 8'h3A; // ":"; // Colon
+ 5'b10010 : msg_char <= 8'h20; // " "; // Space
+ 5'b10011 : msg_char <= 8'h3F; // "?"; // Parse error indication
+ 5'b10100 : msg_char <= 8'h21; // "!"; // ack_i/err_i error indication
+ 5'b10101 : msg_char <= 8'h4F; // "O"; // "All is well" message
+ 5'b10110 : msg_char <= 8'h4B; // "K";
+ 5'b10111 : msg_char <= 8'h0D; // Carriage return & line feed
+ 5'b11000 : msg_char <= 8'h0A;
+ 5'b11001 : msg_char <= 8'h2D; // "-"; // Command Prompt
+ 5'b11010 : msg_char <= 8'h3E; // ">";
+ 5'b11011 : msg_char <= 8'h20; // " ";
+ 5'b11100 : msg_char <= 8'h51; // "Q"; // Quantity error indication
+ default : msg_char <= 8'h3D; // "=";
+ endcase
+end
+
+// This logic determines when to load a transmit character.
+assign rs232_tx_load = rs232_echo?
+ (rs232_rx_data_ready && rs232_tx_load_request):rs232_tx_load_request;
+
+// This is the counter for incrementing, decrementing or resetting the
+// message pointer.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_msg_offset) msg_offset <= 0;
+ else if (incr_msg_offset) msg_offset <= msg_offset + 1;
+end
+assign msg_pointer = msg_offset + msg_base;
+
+
+
+// This is the mux which selects whether to echo back the characters
+// received (as during the entering of a command) or to send back response
+// characters.
+assign rs232_tx_char = (rs232_echo)?rs232_rx_char:msg_char;
+
+
+// These assigments are for detecting whether the received rs232 character is
+// anything of special interest.
+assign rx_char_is_enter = (rs232_rx_char == 8'h0d);
+assign rx_char_is_backspace = (rs232_rx_char == 8'h08);
+
+
+
+// This is state machine m1. It handles receiving the command line, including
+// backspaces, and prints error/response messages. It also parses and
+// executes the commands.
+
+// State register
+always @(posedge clk_i)
+begin : m1_state_register
+ if (reset_i) m1_state <= m1_initial_state; // perform reset for rest of system
+ else m1_state <= m1_next_state;
+end
+
+// State transition logic
+always @(m1_state
+ or rx_char_is_enter
+ or rx_char_is_backspace
+ or msg_offset
+ or cmd_ptr
+ or rs232_tx_load
+ or char_is_whitespace
+ or char_is_hex
+ or char_is_enter
+ or char_is_i
+ or char_is_r
+ or char_is_w
+ or command
+ or master_bg_i
+ or watchdog_timer_done
+ or err_i
+ or ack_i
+ or adr_offset
+ or qty_sr
+ or dat_sr
+ or rd_adr_sr
+ or rd_field_count
+ or rd_digit_count
+ )
+begin : m1_state_logic
+
+ // Default values for outputs. The individual states can override these.
+ msg_base <= 5'b0;
+ reset_msg_offset <= 0;
+ incr_msg_offset <= 0;
+ rs232_echo <= 0;
+ rst_o <= 0;
+ we_l <= 0;
+ stb_l <= 0;
+ cmd_buffer_write <= 0;
+ reset_cmd_ptr <= 0;
+ incr_cmd_ptr <= 0;
+ decr_cmd_ptr <= 0;
+ master_br_o <= 0;
+ cmd_r <= 0;
+ cmd_w <= 0;
+ cmd_i <= 0;
+ shift_rd_adr <= 0;
+ store_adr <= 0; // enables storing hex chars in adr_sr (shift)
+ store_dat <= 0; // enables storing hex chars in dat_sr (shift)
+ store_qty <= 0; // enables storing hex chars in qty_sr (shift)
+ reset_adr <= 0;
+ reset_dat <= 0;
+ reset_qty <= 0;
+ init_qty <= 0;
+ capture_dat <= 0; // enables capturing bus data in dat_sr (load)
+ incr_adr_offset <= 0;
+ reset_adr_offset <= 0;
+ reset_watchdog <= 0;
+ incr_rd_field_count <= 0;
+ incr_rd_digit_count <= 0;
+ reset_rd_field_count <= 0;
+ reset_rd_digit_count <= 0;
+
+ case (m1_state) // synthesis parallel_case
+
+ m1_initial_state :
+ begin
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 15) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_initial_state;
+ end
+
+ m1_send_ok :
+ begin
+ msg_base <= 5'b10101; // Address of the OK message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_send_ok;
+ end
+
+ m1_send_prompt :
+ begin
+ msg_base <= 5'b10111; // Address of the cr,lf,prompt message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 4) && rs232_tx_load) begin
+ m1_next_state <= m1_check_received_char;
+ reset_cmd_ptr <= 1;
+ end
+ else m1_next_state <= m1_send_prompt;
+ end
+
+ // This state always leads to activating the parser...
+ m1_send_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr/lf message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_scan_command;
+ reset_cmd_ptr <= 1;
+ end
+ else m1_next_state <= m1_send_crlf;
+ end
+
+ m1_check_received_char :
+ begin
+ rs232_echo <= 1; // Allow echoing of characters
+ if (rx_char_is_backspace && rs232_tx_load)
+ begin
+ m1_next_state <= m1_check_received_char;
+ decr_cmd_ptr <= 1; // This effectively eliminates the last char
+ end
+ else if (rx_char_is_enter && rs232_tx_load)
+ begin
+ m1_next_state <= m1_send_crlf;
+ cmd_buffer_write <= 1; // Store the enter as "marker" for parsing
+ reset_msg_offset <= 1;
+ end
+ else if (rs232_tx_load && (cmd_ptr == CMD_BUFFER_SIZE_PP-1))
+ begin
+ m1_next_state <= m1_parse_error_indicator_crlf;
+ reset_msg_offset <= 1;
+ reset_cmd_ptr <= 1;
+ end
+ else if (rs232_tx_load)
+ begin
+ incr_cmd_ptr <= 1;
+ cmd_buffer_write <= 1;
+ m1_next_state <= m1_check_received_char;
+ end
+ else m1_next_state <= m1_check_received_char;
+ end
+
+ m1_bg_error_indicator :
+ begin
+ msg_base <= 5'b01011; // Address of the B character
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_ack_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_bg_error_indicator;
+ end
+
+ m1_ack_error_indicator :
+ begin
+ msg_base <= 5'b10100; // Address of the ! error message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_ack_error_indicator;
+ end
+
+ // This state is used when the line is too long...
+ m1_parse_error_indicator_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr,lf message.
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_parse_error_indicator_crlf;
+ end
+
+ m1_parse_error_indicator :
+ begin
+ msg_base <= 5'b10011; // Address of the ? message.
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_parse_error_indicator;
+ end
+
+ m1_cmd_error_indicator :
+ begin
+ msg_base <= 5'b01100; // Address of 'C'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_cmd_error_indicator;
+ end
+
+ m1_adr_error_indicator :
+ begin
+ msg_base <= 5'b01010; // Address of 'A'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_adr_error_indicator;
+ end
+
+ m1_dat_error_indicator :
+ begin
+ msg_base <= 5'b01101; // Address of 'D'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_dat_error_indicator;
+ end
+
+ m1_qty_error_indicator :
+ begin
+ msg_base <= 5'b11100; // Address of 'Q'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_qty_error_indicator;
+ end
+
+ // The following states are for parsing and executing the command.
+
+ // This state takes care of leading whitespace before the command
+ m1_scan_command :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ reset_msg_offset <= 1; // This one reset should cover all of the
+ // parse/exec. states. With rs232_echo
+ // on, and no receive characters arrive,
+ // then the msg_offset will remain reset.
+ // This means the watchdog timer can take
+ // a long time, if need be, during exec.
+ // (NOTE: It might be better to disable
+ // the echoing of rx chars during these
+ // states.)
+ init_qty <= 1; // Set qty = 1 by default. That can be
+ // overridden later, if the command has
+ // a different qty field.
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_command;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_r) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ cmd_r <= 1;
+ end
+ else if (char_is_w) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ cmd_w <= 1;
+ end
+ else if (char_is_i) begin
+ m1_next_state <= m1_start_execution;
+ cmd_i <= 1;
+ end
+ else m1_next_state <= m1_cmd_error_indicator;
+ end
+
+ // The only way to determine the end of a valid field is to find
+ // whitespace. Therefore, char_is_whitespace must be used as an exit
+ // condition from the "get_xxx_field" states. So, this state is used to
+ // scan through any leading whitespace prior to it.
+ m1_scan_adr_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_adr_field;
+ reset_adr <= 1;
+ end
+ end
+
+ m1_get_adr_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_adr_field;
+ store_adr <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace) begin // Normal exit
+ m1_next_state <= m1_scan_dat_whitespace;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else m1_next_state <= m1_adr_error_indicator;
+ end
+
+ m1_scan_dat_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ // There is no DAT field for reads, so skip it.
+ if (command == `CMD_R) m1_next_state <= m1_scan_qty_whitespace;
+ else if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_dat_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_dat_field;
+ reset_dat <= 1;
+ end
+ end
+
+ m1_get_dat_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_dat_field;
+ store_dat <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace) begin // Normal exit
+ m1_next_state <= m1_scan_qty_whitespace;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else m1_next_state <= m1_dat_error_indicator;
+ end
+
+ m1_scan_qty_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_qty_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_qty_field;
+ reset_qty <= 1;
+ end
+ end
+
+ m1_get_qty_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_qty_field;
+ store_qty <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace || char_is_enter) begin // Normal exit
+ m1_next_state <= m1_start_execution;
+ end
+ else m1_next_state <= m1_qty_error_indicator;
+ end
+
+ // This state seeks to obtain master_bg_i, which grants the bus to
+ // rs232_syscon.
+ m1_start_execution :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ reset_watchdog <= 1; // Reset the timer.
+ reset_adr_offset <= 1; // Reset the address offset.
+ reset_rd_field_count <= 1; // Reset the rd_field_count.
+ m1_next_state <= m1_request_bus;
+ end
+
+ m1_request_bus :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Request the bus.
+ if (master_bg_i) m1_next_state <= m1_bus_granted;
+ else if (watchdog_timer_done) begin
+ m1_next_state <= m1_bg_error_indicator;
+ end
+ else m1_next_state <= m1_request_bus;
+ end
+
+ m1_bus_granted :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Keep holding the bus
+ reset_watchdog <= 1; // Reset the timer.
+ if (adr_offset != qty_sr) m1_next_state <= m1_execute;
+ else m1_next_state <= m1_send_ok;
+ end
+
+ // This single state does reset/write/read depending upon the value
+ // contained in "command"!
+ m1_execute :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Keep holding the bus
+ stb_l <= 1'b1; // Show that a bus cycle is happening
+ case (command) // Assert the appropriate signals
+ `CMD_I : rst_o <= 1;
+ `CMD_R : capture_dat <= ack_i;
+ `CMD_W : we_l <= 1;
+ default: ;
+ endcase
+ if (watchdog_timer_done || err_i) begin
+ m1_next_state <= m1_ack_error_indicator;
+ end
+ else if (ack_i
+ && (command == `CMD_R)
+ && (rd_field_count == 0)
+ )
+ begin
+ m1_next_state <= m1_rd_send_adr_sr; // Leads to a new address line.
+ reset_rd_digit_count <= 1;
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else if (ack_i && (command == `CMD_R)) begin
+ m1_next_state <= m1_rd_send_dat_sr; // Leads to a new data field.
+ reset_rd_digit_count <= 1;
+ reset_msg_offset <= 1;
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else if (ack_i) begin
+ m1_next_state <= m1_bus_granted; // continue to the next cycle
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else m1_next_state <= m1_execute;
+ end
+
+ m1_rd_send_adr_sr :
+ begin
+ msg_base <= {1'b0,rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:
+ `NIBBLE_SIZE*(ADR_DIGITS_PP-1)]};
+ if ((rd_digit_count == ADR_DIGITS_PP-1) && rs232_tx_load) begin
+ m1_next_state <= m1_rd_send_separator;
+ reset_msg_offset <= 1;
+ end
+ else if (rs232_tx_load) begin
+ shift_rd_adr <= 1;
+ incr_rd_digit_count <= 1;
+ m1_next_state <= m1_rd_send_adr_sr;
+ end
+ else m1_next_state <= m1_rd_send_adr_sr;
+ end
+
+ m1_rd_send_separator :
+ begin
+ msg_base <= 5'b10000; // Address of the separator message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 2) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_rd_send_dat_sr;
+ reset_rd_digit_count <= 1;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_separator;
+ end
+
+ m1_rd_send_dat_sr :
+ begin
+ msg_base <= {1'b0,dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:
+ `NIBBLE_SIZE*(DAT_DIGITS_PP-1)]};
+ if (
+ (rd_digit_count == DAT_DIGITS_PP-1)
+ && (rd_field_count == RD_FIELDS_PP-1)
+ && rs232_tx_load
+ )
+ begin
+ m1_next_state <= m1_rd_send_crlf;
+ reset_rd_field_count <= 1;
+ end
+ else if ((rd_digit_count == DAT_DIGITS_PP-1) && rs232_tx_load) begin
+ m1_next_state <= m1_rd_send_space;
+ incr_rd_field_count <= 1;
+ end
+ else if (rs232_tx_load) begin
+ store_dat <= 1;
+ incr_rd_digit_count <= 1;
+ m1_next_state <= m1_rd_send_dat_sr;
+ end
+ else m1_next_state <= m1_rd_send_dat_sr;
+ end
+
+ m1_rd_send_space :
+ begin
+ msg_base <= 5'b10000; // Address of the space
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_bus_granted;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_space;
+ end
+
+ m1_rd_send_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr/lf message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_bus_granted;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_crlf;
+ end
+
+ default : m1_next_state <= m1_initial_state;
+ endcase
+end
+
+
+// This is the counter for incrementing or loading the cmd_ptr
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_cmd_ptr) cmd_ptr <= 0;
+ else if (decr_cmd_ptr) cmd_ptr <= cmd_ptr - 1;
+ else if (incr_cmd_ptr) cmd_ptr <= cmd_ptr + 1;
+end
+
+
+// This is the command buffer writing section
+always @(posedge clk_i)
+begin
+ if (rs232_echo && cmd_buffer_write) cmd_buffer[cmd_ptr] <= rs232_rx_char;
+end
+// This is the command buffer reading section
+assign cmd_char = cmd_buffer[cmd_ptr];
+assign lc_cmd_char = (cmd_buffer[cmd_ptr] | 8'h20); // lowercase
+
+
+
+// These assigments are for detecting whether the cmd_char is
+// anything of special interest.
+assign char_is_enter = (cmd_char == 8'h0d); // enter
+assign char_is_whitespace = (
+ (cmd_char == 8'h20) // space
+ || (cmd_char == 8'h09) // tab
+ );
+assign char_is_num = ((cmd_char>=8'h30)&&(cmd_char<=8'h39));
+assign char_is_a_f = ((lc_cmd_char>=8'h61)&&(lc_cmd_char<=8'h66));
+assign char_is_hex = ( char_is_num || char_is_a_f );
+assign char_is_r = (lc_cmd_char == 8'h72); // "r"
+assign char_is_w = (lc_cmd_char == 8'h77); // "w"
+assign char_is_i = (lc_cmd_char == 8'h69); // "i"
+
+assign hex_digit = char_is_num?cmd_char[3:0]:(cmd_char[3:0]+9);
+
+// This is the command register. It stores the type of command to execute.
+// This is so that the state machine can parse address, data and qty
+// into "generic" storage locations, and then when it executes the command,
+// it refers back to this register in order to determine what type of
+// operation to perform.
+
+always @(posedge clk_i)
+begin
+ if (reset_i) command <= `CMD_0;
+ else if (cmd_i) command <= `CMD_I;
+ else if (cmd_r) command <= `CMD_R;
+ else if (cmd_w) command <= `CMD_W;
+end
+
+// This is the "nibble" shift register for the address which is sent character
+// by character to the user. It is loaded each time the adr_offset is
+// incremented, in order to save the previous address for use in printing
+// to the user.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr) rd_adr_sr <= 0;
+ else if (incr_adr_offset) rd_adr_sr <= adr_ptr;
+ else if (shift_rd_adr) begin
+ rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ rd_adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
+ rd_adr_sr[`NIBBLE_SIZE-1:0] <= {`NIBBLE_SIZE{1'b0}};
+ end
+end
+
+// These are the "nibble" shift registers. They handle loading the
+// hexadecimal digits from the command line.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr) adr_sr <= 0;
+ else if (store_adr) begin
+ adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
+ adr_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_dat) dat_sr <= 0;
+ else if (capture_dat) dat_sr <= dat_io;
+ else if (store_dat) begin
+ dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ dat_sr[`NIBBLE_SIZE*(DAT_DIGITS_PP-1)-1:0];
+ dat_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_qty) qty_sr <= 0;
+ else if (init_qty) qty_sr <= 1;
+ else if (store_qty) begin
+ qty_sr[`NIBBLE_SIZE*QTY_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ qty_sr[`NIBBLE_SIZE*(QTY_DIGITS_PP-1)-1:0];
+ qty_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+// This is the rd_digit_count counter. It is used for counting digits
+// displayed of both the adr_sr and dat_sr, so it must be able to count up
+// to the extent of the larger of the two...
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_rd_digit_count) rd_digit_count <= 0;
+ else if (incr_rd_digit_count) rd_digit_count <= rd_digit_count + 1;
+end
+
+// This is the rd_field_count counter. It is used for counting dat_sr fields
+// displayed per line.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_rd_field_count) rd_field_count <= 0;
+ else if (incr_rd_field_count) rd_field_count <= rd_field_count + 1;
+end
+
+
+// This is the watchdog timer counter
+// The watchdog timer is always "enabled" to operate.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_watchdog) watchdog_timer_count <= 0;
+ else if (~watchdog_timer_done)
+ watchdog_timer_count <= watchdog_timer_count + 1;
+end
+assign watchdog_timer_done = (watchdog_timer_count==WATCHDOG_TIMER_VALUE_PP);
+
+
+endmodule
+
+
Index: rs232_syscon/trunk
===================================================================
--- rs232_syscon/trunk (nonexistent)
+++ rs232_syscon/trunk (revision 4)
rs232_syscon/trunk
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: rs232_syscon/web_uploads
===================================================================
--- rs232_syscon/web_uploads (nonexistent)
+++ rs232_syscon/web_uploads (revision 4)
rs232_syscon/web_uploads
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: rs232_syscon/branches
===================================================================
--- rs232_syscon/branches (nonexistent)
+++ rs232_syscon/branches (revision 4)
rs232_syscon/branches
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: rs232_syscon/tags/V001/b13c_environment.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rs232_syscon/tags/V001/b13c_environment.zip
===================================================================
--- rs232_syscon/tags/V001/b13c_environment.zip (nonexistent)
+++ rs232_syscon/tags/V001/b13c_environment.zip (revision 4)
rs232_syscon/tags/V001/b13c_environment.zip
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rs232_syscon/tags/V001/rs232_syscon.doc
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rs232_syscon/tags/V001/rs232_syscon.doc
===================================================================
--- rs232_syscon/tags/V001/rs232_syscon.doc (nonexistent)
+++ rs232_syscon/tags/V001/rs232_syscon.doc (revision 4)
rs232_syscon/tags/V001/rs232_syscon.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rs232_syscon/tags/V001/rs232_syscon.v
===================================================================
--- rs232_syscon/tags/V001/rs232_syscon.v (nonexistent)
+++ rs232_syscon/tags/V001/rs232_syscon.v (revision 4)
@@ -0,0 +1,1168 @@
+//-------------------------------------------------------------------------------------
+//
+// Author: John Clayton
+// Date : June 25, 2001
+// Update: 6/25/01 copied this file from ps2_mouse.v (pared down).
+// Update: 6/07/01 Finished initial coding efforts.
+// Update: 7/19/01 First compilation. Added master_br_o and master_bg_i;
+// Update: 7/25/01 Testing. Eliminated msg_active signal. Changed serial.v
+// to reflect new handshaking (i.e. "load_request" is now a
+// periodic pulse of tx_clk_1x from rs232_tx...)
+// Update: 7/30/01 Began coding m2 state machine. Defined response codes.
+// Update: 8/01/01 After some testing with m2, merged m2 into m1. Eliminated
+// response codes.
+// Update: 8/02/01 Tested & measured the single "combined" state machine's
+// performance, and "it was found wanting." (The 49.152MHz
+// clock frequency was too fast for it...) Created clk_s
+// at 49.152/2 MHz, and this worked.
+// Update: 8/03/01 Added counter loop to "execute" and "bus_granted" states
+// so that multiple bus cycles are generated, at sequential
+// addresses. However, the qty field is not cleared before
+// being loaded with new characters, which causes problems.
+// Update: 8/07/01 Finished debugging. The read print formatting is now
+// correct, and the unit appears to operate correctly.
+// Many hours were spent puzzling over how to make this work.
+// Removed port "debug".
+// Update: 8/24/01 Added "master_stb_i" and "master_we_i" inputs and logic.
+// Update: 12/13/01 For memory_sizer.v, I lowered the frequency of clk_s down
+// to 49.152/4 MHz, so I changed the CLOCK_FACTOR from 8 to 4
+// on the rs232 transciever, and this worked fine.
+// Update: 9/09/02 Incorporated the "autobaud_with_tracking" module so that
+// the serial clock is generated automatically, no matter
+// what frequency clk_i is used. The user simply needs to
+// press "enter" from the terminal program to synchronize
+// the baud rate generator. Changing BAUD rates on the fly
+// is also permitted, simply change to a new BAUD rate in the
+// terminal program and hit enter.
+// Update:11/26/02 Changed the string constants to binary representation
+// (Just to eliminate warnings in XST.)
+//
+//
+//
+//
+//
+// Description
+//-------------------------------------------------------------------------------------
+// This is a state-machine driven rs232 serial port interface to a "Wishbone"
+// type of bus. It is intended to be used as a "Wishbone system controller"
+// for debugging purposes. Specifically, the unit allows the user to send
+// text commands to the "rs232_syscon" unit, in order to generate read and
+// write cycles on the Wishbone compatible bus. The command structure is
+// quite terse and spartan in nature, this is for the sake of the logic itself.
+// Because the menu-driven command structure is supported without the use of
+// dedicated memory blocks (in order to maintain cross-platform portability
+// as much as possible) the menus and command responses were kept as small
+// as possible. In most cases, the responses from the unit to the user
+// consist of a "newline" and one or two visible characters. The command
+// structure consists of the following commands and responses:
+//
+// Command Syntax Purpose
+// --------------- ---------------------------------------
+// w aaaa dddd xx Write data "dddd" starting at address "aaaa"
+// perform this "xx" times at sequential addresses.
+// (The quantity field is optional, default is 1).
+// r aaaa xx Read data starting from address "aaaa."
+// Perform this "xx" times at sequential addresses.
+// (The quantity field is optional, default is 1).
+// i Send a reset pulse to the system. (initialize).
+//
+// Response from rs232_syscon Meaning
+// -------------------------- ---------------------------------------
+// OK Command received and performed. No errors.
+// ? Command buffer full, without receiving "enter."
+// C? Command not recognized.
+// A? Address field syntax error.
+// D? Data field syntax error.
+// Q? Quantity field syntax error.
+// ! No "ack_i", or else "err_i" received from bus.
+// B! No "bg_i" received from master.
+//
+// NOTES on the operation of this unit:
+//
+// - The unit generates a command prompt which is "-> ".
+// - Capitalization is not important.
+// - Each command is terminated by the "enter" key (0x0d character).
+// Commands are executed as soon as "enter" is received.
+// - Trailing parameters need not be re-entered. Their values will
+// remain the same as their previous settings.
+// - Use of the backspace key is supported, so mistakes can be corrected.
+// - The length of the command line is limited to a fixed number of
+// characters, as configured by parameter.
+// - Fields are separated by white space, including "tab" and/or "space"
+// - All numerical fields are interpreted as hexadecimal numbers.
+// Decimal is not supported.
+// - Numerical field values are retained between commands. If a "r" is issued
+// without any fields following it, the previous values will be used. A
+// set of "quantity" reads will take place at sequential addresses.
+// If a "w" is issued without any fields following it, the previous data
+// value will be written "quantity" times at sequential addresses, starting
+// from the next location beyond where the last command ended.
+// - If the user does not wish to use "ack" functionality, simply tie the
+// "ack_i" input to 1b'1, and then the ! response will never be generated.
+// - The data which is read in by the "r" command is displayed using lines
+// which begin with the address, followed by the data fields. The number
+// of data fields displayed per line (following the address) is adjustable
+// by setting a parameter. No other display format adjustments can be made.
+// - There is currently only a single watchdog timer. It begins to count at
+// the time a user hits "enter" to execute a command. If the bus is granted
+// and the ack is received before the expiration of the timer, then the
+// cycle will complete normally. Therefore, the watchdog timeout value
+// needs to include time for the request and granting of the bus, in
+// addition to the time needed for the actual bus cycle to complete.
+//
+//
+// Currently, there is only a single indicator (stb_o) generated during bus
+// output cycles which are generated from this unit.
+// The user can easily implement decoding logic based upon adr_o and stb_o
+// which would serve as multiple "stb_o" type signals for different cores
+// which would be sharing the same bus.
+//
+// The dat_io bus supported by this module is a tri-state type of bus. The
+// Wishbone spec. allows for this type of bus (see Wishbone spec. pg. 66).
+// However, if separate dat_o and dat_i busses are desired, they can be added
+// to the module without too much trouble. Supposedly the only difference
+// between the two forms of data bus is that one of them avoids using tri-state
+// at the cost of doubling the number of interconnects used to carry data back
+// and forth... Some people say that tri-state should be avoided for use
+// in internal busses in ASICs. Maybe they are right.
+// But in FPGAs tri-state seems to work pretty well, even for internal busses.
+//
+// Parameters are provided to configure the width of the different command
+// fields. To simplify the logic for binary to hexadecimal conversion, these
+// parameters allow adjustment in units of 1 hex digit, not anything smaller.
+// If your bus has 10 bits, for instance, simply set the address width to 3
+// which produces 12 bits, and then just don't use the 2 msbs of address
+// output.
+//
+// No support for the optional Wishbone "retry" (rty_i) input is provided at
+// this time.
+// No support for "tagn_o" bits is provided at this time, although a register
+// might be added external to this module in order to implement to tag bits.
+// No BLOCK or RMW cycles are supported currently, so cyc_o is equivalent to
+// stb_o...
+// The output busses are not tri-stated. The user may add tri-state buffers
+// external to the module, using "stb_o" to enable the buffer outputs.
+//
+//-------------------------------------------------------------------------------------
+
+
+`define NIBBLE_SIZE 4 // Number of bits in one nibble
+
+// The command register has these values
+`define CMD_0 0 // Unused command
+`define CMD_I 1 // Initialize (or reset)
+`define CMD_R 2 // Read
+`define CMD_W 3 // Write
+
+module rs232_syscon (
+ clk_i,
+ reset_i,
+ ack_i,
+ err_i,
+ master_bg_i,
+ master_adr_i,
+ master_stb_i,
+ master_we_i,
+ rs232_rxd_i,
+ dat_io,
+ rst_o,
+ master_br_o,
+ stb_o,
+ cyc_o,
+ adr_o,
+ we_o,
+ rs232_txd_o
+ );
+
+
+// Parameters
+
+// The timer value can be from [0 to (2^WATCHDOG_TIMER_BITS_PP)-1] inclusive.
+// RD_FIELDS_PP can be from [0 to (2^RD_FIELD_CTR_BITS_PP)-1] inclusive.
+// Ensure that (2^CHAR_COUNT_BITS_PP) >= CMD_BUFFER_SIZE_PP.
+// The setting of CMD_BUFFER_SIZE_PP should be large enough to hold the
+// largest command, obviously.
+// Ensure that (2^RD_DIGIT_COUNT_BITS_PP) is greater than or equal to the
+// larger of {ADR_DIGITS_PP,DAT_DIGITS_PP}.
+parameter ADR_DIGITS_PP = 4; // # of hex digits for address.
+parameter DAT_DIGITS_PP = 4; // # of hex digits for data.
+parameter QTY_DIGITS_PP = 2; // # of hex digits for quantity.
+parameter CMD_BUFFER_SIZE_PP = 32; // # of chars in the command buffer.
+parameter CMD_PTR_BITS_PP = 4; // # of Bits in command buffer ptr.
+parameter WATCHDOG_TIMER_VALUE_PP = 200; // # of sys_clks before ack expected.
+parameter WATCHDOG_TIMER_BITS_PP = 8; // # of bits needed for timer.
+parameter RD_FIELDS_PP = 8; // # of fields/line (when qty > 1).
+parameter RD_FIELD_COUNT_BITS_PP = 3; // # of bits in the fields counter.
+parameter RD_DIGIT_COUNT_BITS_PP = 2; // # of bits in the digits counter.
+
+
+// State encodings, provided as parameters
+// for flexibility to the one instantiating the module.
+// In general, the default values need not be changed.
+
+// There is one state machines: m1.
+// "default" state upon power-up and configuration is:
+// "m1_initial_state"
+
+parameter m1_initial_state = 5'h00;
+parameter m1_send_ok = 5'h01; // Sends OK
+parameter m1_send_prompt = 5'h02; // Sends "-> "
+parameter m1_check_received_char = 5'h03;
+parameter m1_send_crlf = 5'h04; // Sends cr,lf
+parameter m1_parse_error_indicator_crlf = 5'h05; // Sends cr,lf
+parameter m1_parse_error_indicator = 5'h06; // Sends ?
+parameter m1_ack_error_indicator = 5'h07; // Sends !
+parameter m1_bg_error_indicator = 5'h08; // Sends B!
+parameter m1_cmd_error_indicator = 5'h09; // Sends C?
+parameter m1_adr_error_indicator = 5'h0a; // Sends A?
+parameter m1_dat_error_indicator = 5'h0b; // Sends D?
+parameter m1_qty_error_indicator = 5'h0c; // Sends Q?
+parameter m1_scan_command = 5'h10;
+parameter m1_scan_adr_whitespace = 5'h11;
+parameter m1_get_adr_field = 5'h12;
+parameter m1_scan_dat_whitespace = 5'h13;
+parameter m1_get_dat_field = 5'h14;
+parameter m1_scan_qty_whitespace = 5'h15;
+parameter m1_get_qty_field = 5'h16;
+parameter m1_start_execution = 5'h17;
+parameter m1_request_bus = 5'h18;
+parameter m1_bus_granted = 5'h19;
+parameter m1_execute = 5'h1a;
+parameter m1_rd_send_adr_sr = 5'h1b;
+parameter m1_rd_send_separator = 5'h1c;
+parameter m1_rd_send_dat_sr = 5'h1d;
+parameter m1_rd_send_space = 5'h1e;
+parameter m1_rd_send_crlf = 5'h1f;
+
+// I/O declarations
+input clk_i; // System clock input
+input reset_i; // Reset signal for this module
+input ack_i; // Ack input from Wishbone "slaves"
+input err_i; // Err input from Wishbone "slaves"
+input master_bg_i; // Bus Grant (grants this module the bus)
+ // Address bus input from "normal" Wishbone
+ // master (i.e. from processor)
+input [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] master_adr_i;
+input master_stb_i; // bus cycle signal from "normal" bus master
+input master_we_i; // write enable from "normal" bus master
+input rs232_rxd_i; // Serial data from debug host terminal.
+ // Data bus (tri-state, to save interconnect)
+inout [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_io;
+
+output rst_o; // Rst output to Wishbone "slaves"
+output master_br_o; // Bus request to normal master device.
+output stb_o; // Bus cycle indicator to Wishbone "slaves"
+output cyc_o; // Bus cycle indicator to Wishbone "slaves"
+ // Address bus output to Wishbone "slaves"
+output [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_o;
+output we_o; // Write enable to Wishbone "slaves"
+output rs232_txd_o; // Serial transmit data to debug host terminal
+
+reg rst_o;
+reg master_br_o;
+
+// Internal signal declarations
+wire watchdog_timer_done; // High when watchdog timer is expired
+wire rd_addr_field_done; // High when displayed addr field is complete
+wire rd_data_field_done; // High when displayed data field is complete
+wire rd_line_done; // High when displayed line is complete
+wire char_is_enter; // High when cmd_buffer[char_count] is enter.
+wire char_is_whitespace; // High when cmd_buffer[char_count] is whitespace.
+wire char_is_num; // High when cmd_buffer[char_count] is 0..9
+wire char_is_a_f; // High when cmd_buffer[char_count] is a..f
+wire char_is_hex; // High when cmd_buffer[char_count] is a hex char.
+wire char_is_r; // High when cmd_buffer[char_count] is r.
+wire char_is_w; // High when cmd_buffer[char_count] is w.
+wire char_is_i; // High when cmd_buffer[char_count] is i.
+wire rx_char_is_enter; // High when rs232_rx_char is enter.
+wire rx_char_is_backspace; // High when rs232_rx_char is backspace.
+wire [4:0] msg_pointer; // Determines message position or address.
+wire [3:0] hex_digit; // This is the digit to be stored.
+
+reg rs232_echo; // High == echo char's received.
+reg [7:0] msg_char; // Selected response message character.
+reg [4:0] msg_base; // Added to msg_offset to form msg_pointer.
+reg [4:0] msg_offset; // Offset from start of message.
+reg reset_msg_offset; // High == set message offset to zero
+reg incr_msg_offset; // Used for output messages.
+reg cmd_i; // Sets command.
+reg cmd_r; // Sets command.
+reg cmd_w; // Sets command.
+reg shift_rd_adr; // Shifts the rd_adr_sr by one character.
+reg store_adr; // Allows adr_sr to store hex_digit.
+reg store_dat; // Allows dat_sr to store hex_digit.
+reg store_qty; // Allows qty_sr to store hex_digit.
+reg reset_adr; // Clears adr_sr
+reg reset_dat; // Clears dat_sr
+reg reset_qty; // Clears qty_sr
+reg init_qty; // Sets qty_sr to 1
+reg capture_dat; // Puts dat_io into dat_sr for later display.
+
+ // For the buses
+wire [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_ptr; // = adr_sr + adr_offset
+
+reg stb_l; // "local" stb signal (to distinguish from stb_o)
+reg we_l; // "local" we signal (to distinguish from we_o)
+
+reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] rd_adr_sr; // sr for printing addresses
+reg [`NIBBLE_SIZE*ADR_DIGITS_PP-1:0] adr_sr; // "nibble" shift register
+reg [`NIBBLE_SIZE*DAT_DIGITS_PP-1:0] dat_sr; // "nibble" shift register
+reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] qty_sr; // "nibble" shift register
+reg [1:0] command;
+reg [`NIBBLE_SIZE*QTY_DIGITS_PP-1:0] adr_offset; // counts from 0 to qty_sr
+reg reset_adr_offset;
+reg incr_adr_offset;
+
+ // For the command buffer
+reg [CMD_PTR_BITS_PP-1:0] cmd_ptr; // Offset from start of command.
+reg reset_cmd_ptr; // High == set command pointer to zero.
+reg incr_cmd_ptr; // Used for "write port" side of the command buffer
+reg decr_cmd_ptr; // Used for "write port" side of the command buffer
+reg cmd_buffer_write;
+reg [7:0] cmd_buffer [0:CMD_BUFFER_SIZE_PP-1];
+wire [7:0] cmd_char;
+wire [7:0] lc_cmd_char; // Lowercase version of cmd_char
+
+ // For the state machine
+reg [4:0] m1_state;
+reg [4:0] m1_next_state;
+
+ // For various counters
+reg reset_rd_field_count;
+reg reset_rd_digit_count;
+reg incr_rd_field_count;
+reg incr_rd_digit_count;
+reg [RD_FIELD_COUNT_BITS_PP-1:0] rd_field_count; // "fields displayed"
+reg [RD_DIGIT_COUNT_BITS_PP-1:0] rd_digit_count; // "digits displayed"
+reg [WATCHDOG_TIMER_BITS_PP-1:0] watchdog_timer_count;
+reg reset_watchdog;
+
+ // For the rs232 interface
+wire serial_clk;
+wire [2:0] rs232_rx_error;
+wire rs232_tx_load;
+wire rs232_tx_load_request;
+wire rs232_rx_data_ready;
+wire [7:0] rs232_rx_char;
+wire [7:0] rs232_tx_char; // Either rs232_rx_char or msg_char
+
+//--------------------------------------------------------------------------
+// Instantiations
+//--------------------------------------------------------------------------
+
+
+// These defines are for the rs232 interface
+`define START_BITS 1
+`define DATA_BITS 8
+`define STOP_BITS 1
+`define CLOCK_FACTOR 8
+
+// This module generates a serial BAUD clock automatically.
+// The unit synchronizes on the carriage return character, so the user
+// only needs to press the "enter" key for serial communications to start
+// working, no matter what BAUD rate and clk_i frequency are used!
+auto_baud_with_tracking #(
+ `CLOCK_FACTOR, // CLOCK_FACTOR_PP
+ 16 // LOG2_MAX_COUNT_PP
+ )
+ clock_unit_2
+ (
+ .clk_i(clk_i),
+ .reset_i(reset_i),
+ .serial_dat_i(rs232_rxd_i),
+ .auto_baud_locked_o(),
+ .baud_clk_o(serial_clk)
+ );
+
+// A transmitter, which asserts load_request at the end of the currently
+// transmitted word. The tx_clk must be a "clock enable" (narrow positive
+// pulse) which occurs at 16x the desired transmit rate. If load_request
+// is connected directly to load, the unit will transmit continuously.
+rs232tx #(
+ `START_BITS, // start_bits
+ `DATA_BITS, // data_bits
+ `STOP_BITS, // stop_bits (add intercharacter delay...)
+ `CLOCK_FACTOR // clock_factor
+ )
+ rs232_tx_block // instance name
+ (
+ .clk(clk_i),
+ .tx_clk(serial_clk),
+ .reset(reset_i),
+ .load(rs232_tx_load),
+ .data(rs232_tx_char),
+ .load_request(rs232_tx_load_request),
+ .txd(rs232_txd_o)
+ );
+
+// A receiver, which asserts "word_ready" to indicate a received word.
+// Asserting "read_word" will cause "word_ready" to go low again if it was high.
+// The character is held in the output register, during the time the next
+// character is coming in.
+rs232rx #(
+ `START_BITS, // start_bits
+ `DATA_BITS, // data_bits
+ `STOP_BITS, // stop_bits
+ `CLOCK_FACTOR // clock_factor
+ )
+ rs232_rx_block // instance name
+ (
+ .clk(clk_i),
+ .rx_clk(serial_clk),
+ .reset(reset_i || (| rs232_rx_error)),
+ .rxd(rs232_rxd_i),
+ .read(rs232_tx_load),
+ .data(rs232_rx_char),
+ .data_ready(rs232_rx_data_ready),
+ .error_over_run(rs232_rx_error[0]),
+ .error_under_run(rs232_rx_error[1]),
+ .error_all_low(rs232_rx_error[2])
+ );
+
+//`undef START_BITS
+//`undef DATA_BITS
+//`undef STOP_BITS
+//`undef CLOCK_FACTOR
+
+
+//--------------------------------------------------------------------------
+// Module code
+//--------------------------------------------------------------------------
+
+assign adr_o = master_bg_i?adr_ptr:master_adr_i;
+assign we_o = master_bg_i?we_l:master_we_i;
+assign stb_o = master_bg_i?stb_l:master_stb_i;
+
+
+assign dat_io = (master_bg_i && we_l && stb_l)?
+ dat_sr:{`NIBBLE_SIZE*DAT_DIGITS_PP{1'bZ}};
+
+// Temporary
+assign cyc_o = stb_o; // Separate cyc_o is not yet supported!
+
+
+// This is the adress offset counter
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr_offset) adr_offset <= 0;
+ else if (incr_adr_offset) adr_offset <= adr_offset + 1;
+end
+// This forms the adress pointer which is used on the bus.
+assign adr_ptr = adr_sr + adr_offset;
+
+
+// This is the ROM for the ASCII characters to be transmitted.
+always @(msg_pointer)
+begin
+ case (msg_pointer) // synthesis parallel_case
+ 5'b00000 : msg_char <= 8'h30; // "0"; // Hexadecimal characters
+ 5'b00001 : msg_char <= 8'h31; // "1";
+ 5'b00010 : msg_char <= 8'h32; // "2";
+ 5'b00011 : msg_char <= 8'h33; // "3";
+ 5'b00100 : msg_char <= 8'h34; // "4";
+ 5'b00101 : msg_char <= 8'h35; // "5";
+ 5'b00110 : msg_char <= 8'h36; // "6";
+ 5'b00111 : msg_char <= 8'h37; // "7";
+ 5'b01000 : msg_char <= 8'h38; // "8";
+ 5'b01001 : msg_char <= 8'h39; // "9";
+ 5'b01010 : msg_char <= 8'h41; // "A"; // Address error indication
+ 5'b01011 : msg_char <= 8'h42; // "B";
+ 5'b01100 : msg_char <= 8'h43; // "C"; // Command error indication
+ 5'b01101 : msg_char <= 8'h44; // "D"; // Data error indication
+ 5'b01110 : msg_char <= 8'h45; // "E";
+ 5'b01111 : msg_char <= 8'h46; // "F";
+ 5'b10000 : msg_char <= 8'h20; // " "; // Space
+ 5'b10001 : msg_char <= 8'h3A; // ":"; // Colon
+ 5'b10010 : msg_char <= 8'h20; // " "; // Space
+ 5'b10011 : msg_char <= 8'h3F; // "?"; // Parse error indication
+ 5'b10100 : msg_char <= 8'h21; // "!"; // ack_i/err_i error indication
+ 5'b10101 : msg_char <= 8'h4F; // "O"; // "All is well" message
+ 5'b10110 : msg_char <= 8'h4B; // "K";
+ 5'b10111 : msg_char <= 8'h0D; // Carriage return & line feed
+ 5'b11000 : msg_char <= 8'h0A;
+ 5'b11001 : msg_char <= 8'h2D; // "-"; // Command Prompt
+ 5'b11010 : msg_char <= 8'h3E; // ">";
+ 5'b11011 : msg_char <= 8'h20; // " ";
+ 5'b11100 : msg_char <= 8'h51; // "Q"; // Quantity error indication
+ default : msg_char <= 8'h3D; // "=";
+ endcase
+end
+
+// This logic determines when to load a transmit character.
+assign rs232_tx_load = rs232_echo?
+ (rs232_rx_data_ready && rs232_tx_load_request):rs232_tx_load_request;
+
+// This is the counter for incrementing, decrementing or resetting the
+// message pointer.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_msg_offset) msg_offset <= 0;
+ else if (incr_msg_offset) msg_offset <= msg_offset + 1;
+end
+assign msg_pointer = msg_offset + msg_base;
+
+
+
+// This is the mux which selects whether to echo back the characters
+// received (as during the entering of a command) or to send back response
+// characters.
+assign rs232_tx_char = (rs232_echo)?rs232_rx_char:msg_char;
+
+
+// These assigments are for detecting whether the received rs232 character is
+// anything of special interest.
+assign rx_char_is_enter = (rs232_rx_char == 8'h0d);
+assign rx_char_is_backspace = (rs232_rx_char == 8'h08);
+
+
+
+// This is state machine m1. It handles receiving the command line, including
+// backspaces, and prints error/response messages. It also parses and
+// executes the commands.
+
+// State register
+always @(posedge clk_i)
+begin : m1_state_register
+ if (reset_i) m1_state <= m1_initial_state; // perform reset for rest of system
+ else m1_state <= m1_next_state;
+end
+
+// State transition logic
+always @(m1_state
+ or rx_char_is_enter
+ or rx_char_is_backspace
+ or msg_offset
+ or cmd_ptr
+ or rs232_tx_load
+ or char_is_whitespace
+ or char_is_hex
+ or char_is_enter
+ or char_is_i
+ or char_is_r
+ or char_is_w
+ or command
+ or master_bg_i
+ or watchdog_timer_done
+ or err_i
+ or ack_i
+ or adr_offset
+ or qty_sr
+ or dat_sr
+ or rd_adr_sr
+ or rd_field_count
+ or rd_digit_count
+ )
+begin : m1_state_logic
+
+ // Default values for outputs. The individual states can override these.
+ msg_base <= 5'b0;
+ reset_msg_offset <= 0;
+ incr_msg_offset <= 0;
+ rs232_echo <= 0;
+ rst_o <= 0;
+ we_l <= 0;
+ stb_l <= 0;
+ cmd_buffer_write <= 0;
+ reset_cmd_ptr <= 0;
+ incr_cmd_ptr <= 0;
+ decr_cmd_ptr <= 0;
+ master_br_o <= 0;
+ cmd_r <= 0;
+ cmd_w <= 0;
+ cmd_i <= 0;
+ shift_rd_adr <= 0;
+ store_adr <= 0; // enables storing hex chars in adr_sr (shift)
+ store_dat <= 0; // enables storing hex chars in dat_sr (shift)
+ store_qty <= 0; // enables storing hex chars in qty_sr (shift)
+ reset_adr <= 0;
+ reset_dat <= 0;
+ reset_qty <= 0;
+ init_qty <= 0;
+ capture_dat <= 0; // enables capturing bus data in dat_sr (load)
+ incr_adr_offset <= 0;
+ reset_adr_offset <= 0;
+ reset_watchdog <= 0;
+ incr_rd_field_count <= 0;
+ incr_rd_digit_count <= 0;
+ reset_rd_field_count <= 0;
+ reset_rd_digit_count <= 0;
+
+ case (m1_state) // synthesis parallel_case
+
+ m1_initial_state :
+ begin
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 15) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_initial_state;
+ end
+
+ m1_send_ok :
+ begin
+ msg_base <= 5'b10101; // Address of the OK message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_send_ok;
+ end
+
+ m1_send_prompt :
+ begin
+ msg_base <= 5'b10111; // Address of the cr,lf,prompt message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 4) && rs232_tx_load) begin
+ m1_next_state <= m1_check_received_char;
+ reset_cmd_ptr <= 1;
+ end
+ else m1_next_state <= m1_send_prompt;
+ end
+
+ // This state always leads to activating the parser...
+ m1_send_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr/lf message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_scan_command;
+ reset_cmd_ptr <= 1;
+ end
+ else m1_next_state <= m1_send_crlf;
+ end
+
+ m1_check_received_char :
+ begin
+ rs232_echo <= 1; // Allow echoing of characters
+ if (rx_char_is_backspace && rs232_tx_load)
+ begin
+ m1_next_state <= m1_check_received_char;
+ decr_cmd_ptr <= 1; // This effectively eliminates the last char
+ end
+ else if (rx_char_is_enter && rs232_tx_load)
+ begin
+ m1_next_state <= m1_send_crlf;
+ cmd_buffer_write <= 1; // Store the enter as "marker" for parsing
+ reset_msg_offset <= 1;
+ end
+ else if (rs232_tx_load && (cmd_ptr == CMD_BUFFER_SIZE_PP-1))
+ begin
+ m1_next_state <= m1_parse_error_indicator_crlf;
+ reset_msg_offset <= 1;
+ reset_cmd_ptr <= 1;
+ end
+ else if (rs232_tx_load)
+ begin
+ incr_cmd_ptr <= 1;
+ cmd_buffer_write <= 1;
+ m1_next_state <= m1_check_received_char;
+ end
+ else m1_next_state <= m1_check_received_char;
+ end
+
+ m1_bg_error_indicator :
+ begin
+ msg_base <= 5'b01011; // Address of the B character
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_ack_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_bg_error_indicator;
+ end
+
+ m1_ack_error_indicator :
+ begin
+ msg_base <= 5'b10100; // Address of the ! error message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_ack_error_indicator;
+ end
+
+ // This state is used when the line is too long...
+ m1_parse_error_indicator_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr,lf message.
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_parse_error_indicator_crlf;
+ end
+
+ m1_parse_error_indicator :
+ begin
+ msg_base <= 5'b10011; // Address of the ? message.
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_send_prompt;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_parse_error_indicator;
+ end
+
+ m1_cmd_error_indicator :
+ begin
+ msg_base <= 5'b01100; // Address of 'C'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_cmd_error_indicator;
+ end
+
+ m1_adr_error_indicator :
+ begin
+ msg_base <= 5'b01010; // Address of 'A'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_adr_error_indicator;
+ end
+
+ m1_dat_error_indicator :
+ begin
+ msg_base <= 5'b01101; // Address of 'D'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_dat_error_indicator;
+ end
+
+ m1_qty_error_indicator :
+ begin
+ msg_base <= 5'b11100; // Address of 'Q'
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_parse_error_indicator;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_qty_error_indicator;
+ end
+
+ // The following states are for parsing and executing the command.
+
+ // This state takes care of leading whitespace before the command
+ m1_scan_command :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ reset_msg_offset <= 1; // This one reset should cover all of the
+ // parse/exec. states. With rs232_echo
+ // on, and no receive characters arrive,
+ // then the msg_offset will remain reset.
+ // This means the watchdog timer can take
+ // a long time, if need be, during exec.
+ // (NOTE: It might be better to disable
+ // the echoing of rx chars during these
+ // states.)
+ init_qty <= 1; // Set qty = 1 by default. That can be
+ // overridden later, if the command has
+ // a different qty field.
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_command;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_r) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ cmd_r <= 1;
+ end
+ else if (char_is_w) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ cmd_w <= 1;
+ end
+ else if (char_is_i) begin
+ m1_next_state <= m1_start_execution;
+ cmd_i <= 1;
+ end
+ else m1_next_state <= m1_cmd_error_indicator;
+ end
+
+ // The only way to determine the end of a valid field is to find
+ // whitespace. Therefore, char_is_whitespace must be used as an exit
+ // condition from the "get_xxx_field" states. So, this state is used to
+ // scan through any leading whitespace prior to it.
+ m1_scan_adr_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_adr_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_adr_field;
+ reset_adr <= 1;
+ end
+ end
+
+ m1_get_adr_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_adr_field;
+ store_adr <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace) begin // Normal exit
+ m1_next_state <= m1_scan_dat_whitespace;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else m1_next_state <= m1_adr_error_indicator;
+ end
+
+ m1_scan_dat_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ // There is no DAT field for reads, so skip it.
+ if (command == `CMD_R) m1_next_state <= m1_scan_qty_whitespace;
+ else if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_dat_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_dat_field;
+ reset_dat <= 1;
+ end
+ end
+
+ m1_get_dat_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_dat_field;
+ store_dat <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace) begin // Normal exit
+ m1_next_state <= m1_scan_qty_whitespace;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else m1_next_state <= m1_dat_error_indicator;
+ end
+
+ m1_scan_qty_whitespace :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_whitespace) begin
+ m1_next_state <= m1_scan_qty_whitespace;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_enter) m1_next_state <= m1_start_execution;
+ else begin
+ m1_next_state <= m1_get_qty_field;
+ reset_qty <= 1;
+ end
+ end
+
+ m1_get_qty_field :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ if (char_is_hex) begin
+ m1_next_state <= m1_get_qty_field;
+ store_qty <= 1;
+ incr_cmd_ptr <= 1;
+ end
+ else if (char_is_whitespace || char_is_enter) begin // Normal exit
+ m1_next_state <= m1_start_execution;
+ end
+ else m1_next_state <= m1_qty_error_indicator;
+ end
+
+ // This state seeks to obtain master_bg_i, which grants the bus to
+ // rs232_syscon.
+ m1_start_execution :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ reset_watchdog <= 1; // Reset the timer.
+ reset_adr_offset <= 1; // Reset the address offset.
+ reset_rd_field_count <= 1; // Reset the rd_field_count.
+ m1_next_state <= m1_request_bus;
+ end
+
+ m1_request_bus :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Request the bus.
+ if (master_bg_i) m1_next_state <= m1_bus_granted;
+ else if (watchdog_timer_done) begin
+ m1_next_state <= m1_bg_error_indicator;
+ end
+ else m1_next_state <= m1_request_bus;
+ end
+
+ m1_bus_granted :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Keep holding the bus
+ reset_watchdog <= 1; // Reset the timer.
+ if (adr_offset != qty_sr) m1_next_state <= m1_execute;
+ else m1_next_state <= m1_send_ok;
+ end
+
+ // This single state does reset/write/read depending upon the value
+ // contained in "command"!
+ m1_execute :
+ begin
+ rs232_echo <= 1; // Don't send message characters
+ master_br_o <= 1; // Keep holding the bus
+ stb_l <= 1'b1; // Show that a bus cycle is happening
+ case (command) // Assert the appropriate signals
+ `CMD_I : rst_o <= 1;
+ `CMD_R : capture_dat <= ack_i;
+ `CMD_W : we_l <= 1;
+ default: ;
+ endcase
+ if (watchdog_timer_done || err_i) begin
+ m1_next_state <= m1_ack_error_indicator;
+ end
+ else if (ack_i
+ && (command == `CMD_R)
+ && (rd_field_count == 0)
+ )
+ begin
+ m1_next_state <= m1_rd_send_adr_sr; // Leads to a new address line.
+ reset_rd_digit_count <= 1;
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else if (ack_i && (command == `CMD_R)) begin
+ m1_next_state <= m1_rd_send_dat_sr; // Leads to a new data field.
+ reset_rd_digit_count <= 1;
+ reset_msg_offset <= 1;
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else if (ack_i) begin
+ m1_next_state <= m1_bus_granted; // continue to the next cycle
+ incr_adr_offset <= 1; // move to the next address
+ end
+ else m1_next_state <= m1_execute;
+ end
+
+ m1_rd_send_adr_sr :
+ begin
+ msg_base <= {1'b0,rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:
+ `NIBBLE_SIZE*(ADR_DIGITS_PP-1)]};
+ if ((rd_digit_count == ADR_DIGITS_PP-1) && rs232_tx_load) begin
+ m1_next_state <= m1_rd_send_separator;
+ reset_msg_offset <= 1;
+ end
+ else if (rs232_tx_load) begin
+ shift_rd_adr <= 1;
+ incr_rd_digit_count <= 1;
+ m1_next_state <= m1_rd_send_adr_sr;
+ end
+ else m1_next_state <= m1_rd_send_adr_sr;
+ end
+
+ m1_rd_send_separator :
+ begin
+ msg_base <= 5'b10000; // Address of the separator message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 2) && rs232_tx_load)
+ begin
+ m1_next_state <= m1_rd_send_dat_sr;
+ reset_rd_digit_count <= 1;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_separator;
+ end
+
+ m1_rd_send_dat_sr :
+ begin
+ msg_base <= {1'b0,dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:
+ `NIBBLE_SIZE*(DAT_DIGITS_PP-1)]};
+ if (
+ (rd_digit_count == DAT_DIGITS_PP-1)
+ && (rd_field_count == RD_FIELDS_PP-1)
+ && rs232_tx_load
+ )
+ begin
+ m1_next_state <= m1_rd_send_crlf;
+ reset_rd_field_count <= 1;
+ end
+ else if ((rd_digit_count == DAT_DIGITS_PP-1) && rs232_tx_load) begin
+ m1_next_state <= m1_rd_send_space;
+ incr_rd_field_count <= 1;
+ end
+ else if (rs232_tx_load) begin
+ store_dat <= 1;
+ incr_rd_digit_count <= 1;
+ m1_next_state <= m1_rd_send_dat_sr;
+ end
+ else m1_next_state <= m1_rd_send_dat_sr;
+ end
+
+ m1_rd_send_space :
+ begin
+ msg_base <= 5'b10000; // Address of the space
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 0) && rs232_tx_load) begin
+ m1_next_state <= m1_bus_granted;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_space;
+ end
+
+ m1_rd_send_crlf :
+ begin
+ msg_base <= 5'b10111; // Address of the cr/lf message
+ incr_msg_offset <= rs232_tx_load;
+ if ((msg_offset == 1) && rs232_tx_load) begin
+ m1_next_state <= m1_bus_granted;
+ reset_msg_offset <= 1;
+ end
+ else m1_next_state <= m1_rd_send_crlf;
+ end
+
+ default : m1_next_state <= m1_initial_state;
+ endcase
+end
+
+
+// This is the counter for incrementing or loading the cmd_ptr
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_cmd_ptr) cmd_ptr <= 0;
+ else if (decr_cmd_ptr) cmd_ptr <= cmd_ptr - 1;
+ else if (incr_cmd_ptr) cmd_ptr <= cmd_ptr + 1;
+end
+
+
+// This is the command buffer writing section
+always @(posedge clk_i)
+begin
+ if (rs232_echo && cmd_buffer_write) cmd_buffer[cmd_ptr] <= rs232_rx_char;
+end
+// This is the command buffer reading section
+assign cmd_char = cmd_buffer[cmd_ptr];
+assign lc_cmd_char = (cmd_buffer[cmd_ptr] | 8'h20); // lowercase
+
+
+
+// These assigments are for detecting whether the cmd_char is
+// anything of special interest.
+assign char_is_enter = (cmd_char == 8'h0d); // enter
+assign char_is_whitespace = (
+ (cmd_char == 8'h20) // space
+ || (cmd_char == 8'h09) // tab
+ );
+assign char_is_num = ((cmd_char>=8'h30)&&(cmd_char<=8'h39));
+assign char_is_a_f = ((lc_cmd_char>=8'h61)&&(lc_cmd_char<=8'h66));
+assign char_is_hex = ( char_is_num || char_is_a_f );
+assign char_is_r = (lc_cmd_char == 8'h72); // "r"
+assign char_is_w = (lc_cmd_char == 8'h77); // "w"
+assign char_is_i = (lc_cmd_char == 8'h69); // "i"
+
+assign hex_digit = char_is_num?cmd_char[3:0]:(cmd_char[3:0]+9);
+
+// This is the command register. It stores the type of command to execute.
+// This is so that the state machine can parse address, data and qty
+// into "generic" storage locations, and then when it executes the command,
+// it refers back to this register in order to determine what type of
+// operation to perform.
+
+always @(posedge clk_i)
+begin
+ if (reset_i) command <= `CMD_0;
+ else if (cmd_i) command <= `CMD_I;
+ else if (cmd_r) command <= `CMD_R;
+ else if (cmd_w) command <= `CMD_W;
+end
+
+// This is the "nibble" shift register for the address which is sent character
+// by character to the user. It is loaded each time the adr_offset is
+// incremented, in order to save the previous address for use in printing
+// to the user.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr) rd_adr_sr <= 0;
+ else if (incr_adr_offset) rd_adr_sr <= adr_ptr;
+ else if (shift_rd_adr) begin
+ rd_adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ rd_adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
+ rd_adr_sr[`NIBBLE_SIZE-1:0] <= {`NIBBLE_SIZE{1'b0}};
+ end
+end
+
+// These are the "nibble" shift registers. They handle loading the
+// hexadecimal digits from the command line.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_adr) adr_sr <= 0;
+ else if (store_adr) begin
+ adr_sr[`NIBBLE_SIZE*ADR_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ adr_sr[`NIBBLE_SIZE*(ADR_DIGITS_PP-1)-1:0];
+ adr_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_dat) dat_sr <= 0;
+ else if (capture_dat) dat_sr <= dat_io;
+ else if (store_dat) begin
+ dat_sr[`NIBBLE_SIZE*DAT_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ dat_sr[`NIBBLE_SIZE*(DAT_DIGITS_PP-1)-1:0];
+ dat_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_qty) qty_sr <= 0;
+ else if (init_qty) qty_sr <= 1;
+ else if (store_qty) begin
+ qty_sr[`NIBBLE_SIZE*QTY_DIGITS_PP-1:`NIBBLE_SIZE] <=
+ qty_sr[`NIBBLE_SIZE*(QTY_DIGITS_PP-1)-1:0];
+ qty_sr[`NIBBLE_SIZE-1:0] <= hex_digit;
+ end
+end
+
+// This is the rd_digit_count counter. It is used for counting digits
+// displayed of both the adr_sr and dat_sr, so it must be able to count up
+// to the extent of the larger of the two...
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_rd_digit_count) rd_digit_count <= 0;
+ else if (incr_rd_digit_count) rd_digit_count <= rd_digit_count + 1;
+end
+
+// This is the rd_field_count counter. It is used for counting dat_sr fields
+// displayed per line.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_rd_field_count) rd_field_count <= 0;
+ else if (incr_rd_field_count) rd_field_count <= rd_field_count + 1;
+end
+
+
+// This is the watchdog timer counter
+// The watchdog timer is always "enabled" to operate.
+always @(posedge clk_i)
+begin
+ if (reset_i || reset_watchdog) watchdog_timer_count <= 0;
+ else if (~watchdog_timer_done)
+ watchdog_timer_count <= watchdog_timer_count + 1;
+end
+assign watchdog_timer_done = (watchdog_timer_count==WATCHDOG_TIMER_VALUE_PP);
+
+
+endmodule
+
+
Index: rs232_syscon/tags
===================================================================
--- rs232_syscon/tags (nonexistent)
+++ rs232_syscon/tags (revision 4)
rs232_syscon/tags
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##