0% found this document useful (0 votes)
41 views19 pages

Uart Transmit Module

This module implements the transmit portion of an 8 bit uart. There is no provision for any other word size, or the addition of parity, / / since in general I have absolutely no use for any of that.

Uploaded by

Swetha Vanam
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views19 pages

Uart Transmit Module

This module implements the transmit portion of an 8 bit uart. There is no provision for any other word size, or the addition of parity, / / since in general I have absolutely no use for any of that.

Uploaded by

Swetha Vanam
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

Uart Transmit Module // // Created March 6, 2005 // Author:James Patchell // Copyleft (c) 2005 by James Patchell // This code

may be used freely in anyway you see fit... // This is open source. // // This is a module that implements the transmit portion of an 8 bit uart. // This is a very simple minded implementation in that that is all it does. // There is no provision for any other word size, or the addition of parity, // since in general I have absolutely no use for any of that. // // parameter: // din............8 bit bus of data that is to be sent out // load...........This signal write the data to a holding register and // sets a Ready flag to let the transmitter know that // there is data ready to go out. // clock..........system clock // reset..........system reset, returns uart to an idle stat and clears ready // shift..........signal to let the system know when it is time to shift a bit // (this is the baud rate). // txd............transmit data output // ready..........status: 0 indicates no data in holding register // status: 1 indicates holding register is full //----------------------------------------------------------------------------// Revision History: // Rev 1.01 // April 17, 2005 // Changed the shift register to shift the LSB out first //--------------------------------------------------------------------------------module uarttx(din,load,clock,reset,shift,txd,ready,CS); input [7:0] din; //data to be transmitted input load; //loads the transmit register input clock; // 1x transmit clock input reset; // resets the registers input shift; // this is when the shift register is supposed to shift output txd; // output data output ready; // indicates ready to recieve char to transmit output [3:0]CS; //state output reg ready; reg txd; //ready status bit //transmit bit

reg [8:0] INT; //nine bit shift register reg [7:0] Hold; //holding register for the data reg doshift; //tells the shift register to shift its data reg doload; //tells the shift register to load its data reg clearready; //tells the ready bit to clear

reg setready; always @(posedge clock) begin if(load) begin Hold <= din; end end always @(load) if(load) setready <= 1; else setready <= 0;

//tells the ready bit to set

//load data into holding register

//----------------------------------------------------------------// Uart State machine // // it should be noted, the LSB is the first bit to // be transmitted...the states would seem to imply // that we start at BIT7...well, that is wrong //----------------------------------------------------------------parameter [3:0] //synopsys enum STATE_TYPE UART_IDLE = 4'b0000, UART_STARTBIT = 4'b0001, UART_BIT7 = 4'b0010, UART_BIT6 = 4'b0011, UART_BIT5 = 4'b0100, UART_BIT4 = 4'b0101, UART_BIT3 = 4'b0110, UART_BIT2 = 4'b0111, UART_BIT1 = 4'b1000, UART_BIT0 = 4'b1001, UART_STOPBIT = 4'b1010; // Declare current state and next state variables reg [3:0] /* synopsys enum STATE_TYPE */ CS; reg [3:0] /* synopsys enum STATE_TYPE */ NS; //synopsys state_vector CS always @ (posedge clock or posedge reset) begin if (reset) CS <= UART_IDLE; else CS <= NS; end always @ (CS or ready or shift) begin case (CS) //synopsys full_case UART_IDLE: begin if (ready && shift) begin NS <= UART_STARTBIT; doshift = 0;

doload = 1; shift register

//load data into

clearready = 1; //clear ready bit end else begin NS <= UART_IDLE; doshift = 0; doload = 0; clearready = 0; end end UART_STARTBIT: begin if(shift) begin NS <= UART_BIT7; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_STARTBIT; state doshift = 0; doload = 0; clearready = 0; end end UART_BIT7: begin if(shift) begin NS <= UART_BIT6; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT7; this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT6: begin if(shift) begin NS <= UART_BIT5; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT6; this state //hold //shift //hold //shift //hold this //shift

//go to

//go to

//go to

doshift = 0; doload = 0; clearready = 0; end end UART_BIT5: begin if(shift) begin NS <= UART_BIT4; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT5; this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT4: begin if(shift) begin NS <= UART_BIT3; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT4; this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT3: begin if(shift) begin NS <= UART_BIT2; next state doshift = 1; data out register doload = 0; clearready = 0; end else this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT2: begin begin NS <= UART_BIT3; //hold //shift //hold //shift //hold //shift

//go to

//go to

//go to

if(shift) begin NS <= UART_BIT1; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT2; this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT1: begin if(shift) begin NS <= UART_BIT0; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT1; this state doshift = 0; doload = 0; clearready = 0; end end UART_BIT0: begin if(shift) begin NS <= UART_STOPBIT; next state doshift = 1; data out register doload = 0; clearready = 0; end else begin NS <= UART_BIT0; this state doshift = 0; doload = 0; clearready = 0; end end UART_STOPBIT: begin if(shift && !ready) begin NS <= UART_IDLE; more to do, so idle doshift = 0; doload = 0; clearready = 0;

//go to //shift

//hold

//go to //shift

//hold

//go to //shift

//hold

//nothing

end else if (shift && ready) begin NS <= UART_STARTBIT; //another byte waiting, go do it doshift = 0; doload = 1; data into shift register clearready = 1; bit end else begin NS <= UART_STOPBIT; this state doshift = 0; doload = 0; clearready = 0; end end default: begin doshift = 0; doload = 0; clearready = 0; NS <= UART_IDLE; end endcase end //--------------------------------------------------------------// shift register // // shift register can do a load, and do a shift //--------------------------------------------------------------always @(posedge clock or posedge reset) begin if(reset) begin INT <= 9'b111111111; //reset transmit register to all 1's end else begin if(doload) begin INT <= {Hold,1'b0}; //load data and set start bit to 0 txd <= INT[0]; end else if (doshift) begin INT <= {1'b1,INT[8:1]}; //shift data, shift in 1's txd <= INT[0]; end else begin INT <= INT; //hold data txd <= INT[0]; end end end //--------------------------------------------------------------//hold //clear ready //load

// ready status bit // when status == 1, this indicates that there is data waiting // in the data holding register ready to be // transmitted. // when status == 0, data holding register is empty //--------------------------------------------------------------always @ (posedge clock or posedge reset) begin if(reset) ready <= 0; //always not ready at reset else begin if(setready) ready <= 1; else if(clearready) ready <= 0; else ready <= ready; //hold ready end end endmodule

Uart Reciever // Created March 21, 2004 by James Patchell // // Doing a Uart Reciever is a lot more complicated than doing a Uart Transmitter // Parameters: // dout.......this is the data that is recieved, valid only when ready is true // clk........16x baud rate clock // reset......resets all of the registers // rxd........recieve data input // frame......frame error output........Not Implemented Yet // overrun....overrun error output......Not Implemented Yet // ready......indicates that all 8 bits have been read // //----------------------------------------------------------------------------// Revision History: // Rev 1.01 // April 17, 2005 // Changed the shift register to shift the LSB out first //----------------------------------------------------------------------------module uartrx(dout,clk,bclk,reset,rxd,frame,overrun,ready,busy,CS); output [7:0] dout; //data output from input shift register

input clk; input bclk; input reset; input rxd; output frame; output overrun; output ready; output [3:0] CS; output busy;

//system clock //16x baud rate clock //reinitializes the whole mess //serial port input //framing error //overrun error //data is ready //For debug use

wire frame; wire overrun; reg [7:0] dout; reg ready; reg din,din1,din2; reg syncbitcnt; //synchronize the clock bit divider reg [3:0] bitcnt; //divide by sixteen bit counter reg bitenable; //indicate bit time reg shiftenable; //enable shifter reg start; //indicates a start condition reg done; //indicate all bits shifted in reg busy; reg [3:0] NS; reg [3:0] CS; reg [7:0] datain; //data in shift register reg loadout; //transfers data from datain to dout assign frame = 0; assign overrun = 0; //----------------------------------------------------------// Start bit detection logic //----------------------------------------------------------always @(posedge clk or posedge reset) begin if(reset) begin din <= 1; din1 <= 1; din2 <= 1; end else begin if (bclk) begin din <= din1; //shift din1 <= din2; din2 <= rxd; end else begin din <= din; //hold din1 <= din1; din2 <= din2; end end end

always @(din or din1 or bclk) begin start <= din & !din1 & bclk; end

//indicates we have a start condition

//--------------------------------------------------------// status bit indicates if we are in the process of getting // a byte in //--------------------------------------------------------always @ (posedge clk or posedge reset) begin if(reset) busy <= 0; else begin if(start) busy <= 1; else if (done) busy <= 0; end end //--------------------------------------------------------// this bit will go true for one clock cycle indicating that // the output holding register has a byte in it ready for // use //--------------------------------------------------------always @ (posedge clk) ready <= done; //-------------------------------------------------------// when we get a start condition and we are not busy, // resync the bit counter //-------------------------------------------------------always @ (start or busy) begin if(start && !busy) syncbitcnt <= 1; else syncbitcnt <= 0; end always @(posedge clk or posedge reset) //------------------------------------------------------// this is the divider for the 16x clock // syncbitcnt is used to syncronize this counter with the // start bit //------------------------------------------------------begin if (reset) bitcnt <= 4'b0; //initialize counter else begin

if (syncbitcnt) //synchronize bitcnt <= 4'b0; else if(bclk) bitcnt <= bitcnt + 1; //count else bitcnt <= bitcnt; end end always @(bitcnt or bclk) //---------------------------------------------// we want to check the serial stream right in // the middle of the bit time //---------------------------------------------begin if(bitcnt == 4'b1000) // if count == 8 bitenable <= bclk; else bitenable <= 0; end

//hold

//---------------------------------------------------// data shift register //---------------------------------------------------always @(posedge clk or posedge reset) begin if(reset) begin datain <= 0; //reset shift register to zero end else if(shiftenable) datain <= {din,datain[7:1]}; //shift when told to else datain <= datain; //hold that thought. end //---------------------------------------------------// output register //---------------------------------------------------always @ (posedge clk or posedge reset) begin if(reset) dout <= 0; else if (loadout) dout <= datain; end //---------------------------------------------------// UART rx State Machine // as it turns out...this looks an awful lot like the // transmit state machine :-) // // it should be noted, the LSB is the first bit to // be transmitted...the states would seem to imply // that we start at BIT7...well, that is wrong //

//---------------------------------------------------parameter [3:0] //synopsys enum STATE_TYPE UART_IDLE = 4'b0000, UART_STARTBIT = 4'b0001, UART_BIT7 = 4'b0010, UART_BIT6 = 4'b0011, UART_BIT5 = 4'b0100, UART_BIT4 = 4'b0101, UART_BIT3 = 4'b0110, UART_BIT2 = 4'b0111, UART_BIT1 = 4'b1000, UART_BIT0 = 4'b1001, UART_STOPBIT = 4'b1010; always @ (posedge clk or posedge reset) begin if (reset) CS <= UART_IDLE; else CS <= NS; end always @ (CS or bitenable or start) begin case (CS) //synopsys full_case UART_IDLE: begin if(start) begin NS = UART_STARTBIT; shiftenable = 0; done = 0; loadout = 0; end else begin NS = UART_IDLE; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_STARTBIT: begin if(bitenable) begin NS = UART_BIT7; shiftenable = 1; loadout = 0; done = 0; end else begin NS = UART_STARTBIT; //hold shiftenable = 0; loadout = 0; done = 0; end end UART_BIT7: begin

if(bitenable) begin NS = UART_BIT6; shiftenable = 1; done = 0; loadout = 0; end else begin NS = UART_BIT7; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT6: begin if(bitenable) begin NS = UART_BIT5; shiftenable = 1; done = 0; loadout = 0; end else begin NS = UART_BIT6; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT5: begin if(bitenable) begin NS = UART_BIT4; shiftenable = 1; done = 0; loadout = 0; end else begin NS = UART_BIT5; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT4: begin if(bitenable) begin NS = UART_BIT3; shiftenable = 1; done = 0; loadout = 0; end else begin

NS = UART_BIT4; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT3: begin if(bitenable) begin NS = UART_BIT2; shiftenable = 1; loadout = 0; done = 0; end else begin NS = UART_BIT3; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT2: begin if(bitenable) begin NS = UART_BIT1; shiftenable = 1; loadout = 0; done = 0; end else begin NS = UART_BIT2; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT1: begin if(bitenable) begin NS = UART_BIT0; shiftenable = 1; done = 0; loadout = 0; end else begin NS = UART_BIT1; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_BIT0: begin if(bitenable) begin

NS = UART_STOPBIT; shiftenable = 1; loadout = 0; done = 0; end else begin NS = UART_BIT0; //hold shiftenable = 0; done = 0; loadout = 0; end end UART_STOPBIT: begin if(bitenable) begin NS = UART_IDLE; shiftenable = 0; done = 1; clear busy status loadout = 1; end else begin NS = UART_STOPBIT; shiftenable = 0; done = 0; loadout = 0; end end default: begin NS = UART_IDLE; shiftenable = 0; done = 0; loadout = 0; end endcase end endmodule //hold

//this will

Universal Asynchronous Receiver (UAR)


Many thanks to Gerard Blair at the University of Edinburgh for allowing us to use his UAR model for February's Model of the Month. Gerard's home page is http://www.ee.ed.ac.uk/~gerard/. If you have a model that you are willing to have advertised on these pages, please drop us a line by clicking here. OK, on with this month's Model...

The above figure shows a simplified picture of an asynchronous serial interface of the type commonly used to transfer data in computer and communications systems. The data transfer is referred to as `asynchronous' because the spacing between the characters may be of any length. In contrast, the timing of the bits within the character is well defined (and is related to the baud rate of the interface). The Tx clock and Rx clock signals are nominally of the same frequency, but are generated locally at each end of the transmission link and therefore cannot be assumed to be locked' together. The design of a suitable transmitter circuit is not difficult, but the receiver must be able to detect the start of an incoming character and then store the value of each data bit, despite the fact that the relative frequency and phase of the Tx and Rx clocks may vary.

As shown in the data diagram above, the beginning and end of each character is delimited by a start bit whose value is always 0, and a stop bit whose value is always 1. In between characters, the transmitter outputs a constant value of 1. In operation, the receiver continually samples the input data. Following a 1 -> 0 data input transition, the eight data bits must be stored, and this is where a problem may occur, since for maximum reliability we wish to sample the data bits in the centre of their bit times and not close to either edge, so that small differences between the Tx and Rx clocks can be accommodated. This may be accomplished by using an Rx clock frequency which is a multiple of the data bit rate. In this exercise we shall assume that the Rx clock signal is eight times the bit rate. Following the detection of a start bit, the stop bit should be detected 76 clock cycles later. If so, the Data Available output is set high; if not, the Framing Error output is set. Both status outputs are reset low by the detection of the next start bit. There is thought to be a danger of spikes on the communication channel falsely starting the receiver. This means that a momentary LOW on the input to the receiver would be seen as a oneto-zero transition where-as it is really just noise. To counter this, the specification is changed as follows:
y

The start bit is a one-to zero transition where the input signal is still zero four (or three or five) samples later.

Thus you will have to update your design for detectng a valid start bit. Note:- the flexibility of 3-4-5 clock periods is to allow you to implement whichever is simplest BUT there is no definition of what value is on the input at the sample AFTER the one-to-zero transition: this is to avoid problems associated with signal bounce. Well, that's the specification for a UAR model. Here is a design based on sound synchronous design principles. The following Verilog code has five major sub-modules:
y y y y y

a start detector which deals with recognizing the beginning of a new data frame. This sends a signal to set the... control module into run mode. A counter generates a pulse every 8 bits to input the data (thus sampled in the middle of the valid period) serially into a... serial-parallel shift register. On the last bit of the data frame, the shift register is not updated, but rather the.. flags are set according to the value of the stop bit.

As with all good synchronous modules, a global_reset signal is included so that the registers can be put into a known state at the start of testing.

You are welcome to use the source code we provide but you must keep the copyright notice with the code (see the Notices page for details).
// // // // // // // Universal Asynchronous Receiver +-----------------------------+ | Library : Datacomms | | designer : Gerard Blair | | opened: 03 Feb 1997 | +-----------------------------+

// Architectures: // 03.02.97 uar // Start detection module start_detect (valid, clk, reset, gl_reset, dIn); output valid; input clk, reset, gl_reset, dIn; reg [3:0] shift_reg; always @ (posedge clk) begin if (reset | gl_reset) shift_reg = 0; else shift_reg = { shift_reg[2:0], dIn }; end assign valid = (shift_reg [0] == 0) & (shift_reg [2] == 0) & (shift_reg [3] == 1); endmodule // controller module counter (count72, count8, clk, enable); output count72, count8; input clk, enable; wire each8; reg [8:0] count_reg; always @ (posedge clk) if (enable == 0) count_reg <= 0; else begin count_reg <= count_reg + 1; end assign each8 = ((count_reg % 8) == 7); assign count72 = (count_reg == 71); assign count8 = each8 & ~count72; endmodule // serial parallel converter module ser_par_conv (dOut, clk, enable, dIn); output [7:0] dOut;

input reg

clk, enable, dIn; [7:0] dOut;

always @ (posedge clk) if (enable == 1) dOut = {dIn, dOut[7:1]}; endmodule // flags for ready and data error module flags (dReady, dError, clk, set, output dReady, dError; input clk, set, reset, dIn; reg dReady, dError; always @(posedge clk) if (reset == 1) begin dReady = 0; dError = 0; end else if (set == 1) begin dReady <= dIn; dError <= ~dIn; end initial $monitor("dReady %b %b", dReady, dError, $time); endmodule // generating the run signals module control (running, clk, reset, gl_reset, set); output running; input clk, reset, gl_reset, set; reg running; always @ (posedge clk) if ((reset == 1) | (gl_reset == 1)) running = 0; else if (set == 1) running = 1; endmodule // overall receiver definition module uar (dOut, dReady, dError, clk, gl_reset, dIn); output [7:0] dOut; output dReady, dError; input clk, gl_reset, dIn; wire start_detect counter ser_par_conv flags control endmodule running, finish, count8, start; s_d cov s_p fla con (start, clk, running, gl_reset, dIn); (finish, count8, clk, running); (dOut, clk, count8, dIn); (dReady, dError, clk, finish, start, dIn); (running, clk, finish, gl_reset, start); reset, dIn);

You might also like