add rs232 uart
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 17 Jul 2018 10:53:43 +0000 (11:53 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 17 Jul 2018 10:53:43 +0000 (11:53 +0100)
src/bsv/bsv_lib/RS232_modified.bsv [new file with mode: 0644]
src/bsv/bsv_lib/Uart_bs.bsv [new file with mode: 0644]
src/bsv/bsv_lib/instance_defines.bsv

diff --git a/src/bsv/bsv_lib/RS232_modified.bsv b/src/bsv/bsv_lib/RS232_modified.bsv
new file mode 100644 (file)
index 0000000..ca336d9
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+Copyright (c) 2013, IIT Madras
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+*  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*  Neither the name of IIT Madras  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+*/
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2010  Bluespec, Inc.   ALL RIGHTS RESERVED.
+////////////////////////////////////////////////////////////////////////////////
+//  Filename      : RS232.bsv
+//  Description   : Simple UART BFM   RS232 <-> Bit#(8)
+////////////////////////////////////////////////////////////////////////////////
+package RS232_modified;
+
+// Notes :
+
+////////////////////////////////////////////////////////////////////////////////
+/// Imports
+////////////////////////////////////////////////////////////////////////////////
+import Clocks            ::*;
+import GetPut            ::*;
+import Connectable       ::*;
+import FIFOLevel         ::*;
+import Vector            ::*;
+import BUtils            ::*;
+import Counter           ::*;
+
+////////////////////////////////////////////////////////////////////////////////
+/// Exports
+////////////////////////////////////////////////////////////////////////////////
+export RS232             (..);
+export UART              (..);
+export BaudGenerator     (..);
+export Parity            (..);
+export StopBits          (..);
+export InputFilter       (..);
+export Synchronizer      (..);
+export EdgeDetector      (..);
+export InputMovingFilter (..);
+export mkUART;
+export mkBaudGenerator;
+export mkInputFilter;
+export mkSynchronizer;
+export mkEdgeDetector;
+export mkInputMovingFilter;
+
+////////////////////////////////////////////////////////////////////////////////
+/// Types
+////////////////////////////////////////////////////////////////////////////////
+typedef union tagged {
+   void Start;
+   void Center;
+   void Wait;
+   void Sample;
+   void Parity;
+   void StopFirst;
+   void StopLast;
+   } RecvState deriving (Bits, Eq);
+
+typedef union tagged {
+   void Idle;
+   void Start;
+   void Wait;
+   void Shift;
+   void Stop;
+   void Stop5;
+   void Stop2;
+   void Parity;
+   } XmitState deriving (Bits, Eq);
+
+typedef enum {
+   NONE,
+   ODD,
+   EVEN
+   } Parity deriving (Bits, Eq);
+
+typedef enum {
+   STOP_1,
+   STOP_1_5,
+   STOP_2
+   } StopBits deriving (Bits, Eq);
+
+////////////////////////////////////////////////////////////////////////////////
+/// Interfaces
+////////////////////////////////////////////////////////////////////////////////
+(* always_ready, always_enabled *)
+interface RS232;
+   // Inputs
+   (* prefix = "" *)
+   method    Action      sin((* port = "SIN" *)Bit#(1) x);
+   // Outputs
+   (* prefix = "", result = "SOUT" *)
+   method    Bit#(1)     sout();
+endinterface
+
+interface BaudGenerator;
+   method    Action    clock_enable();
+   method    Action    clear();
+   method    Bool      baud_tick_16x();
+   method    Bool      baud_tick_2x();
+endinterface
+
+interface InputFilter#(numeric type size, type a);
+   method    Action    clock_enable();
+   method    a         _read();
+endinterface
+
+(* always_ready, always_enabled *)
+interface EdgeDetector#(type a);
+   method    Bool      rising();
+   method    Bool      falling();
+endinterface
+
+(* always_ready, always_enabled *)
+interface Synchronizer#(type a);
+   method    Action    _write(a x);
+   method    a         _read();
+endinterface
+
+interface InputMovingFilter#(numeric type width, numeric type threshold, type a);
+   method    Action    sample();
+   method    Action    clear();
+   method    a         _read();
+endinterface
+
+interface UART#(numeric type depth);
+   (* prefix = "" *)
+   interface RS232           rs232;
+   interface Get#(Bit#(8))   tx;
+   interface Put#(Bit#(8))   rx;
+   method Bool transmission_done;
+   method Bool receiver_not_empty;
+   method Bool receiver_not_full;
+   method Bool transmittor_not_empty;
+endinterface
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation of Baud Generator
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkBaudGenerator#(Bit#(16) divider)(BaudGenerator);
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   Counter#(16)                              rBaudCounter        <- mkCounter(0);
+   PulseWire                                 pwBaudTick16x       <- mkPulseWire;
+
+   Counter#(3)                               rBaudTickCounter    <- mkCounter(0);
+   PulseWire                                 pwBaudTick2x        <- mkPulseWire;
+
+   Wire#(Bit#(16))                           wBaudCount          <- mkWire;
+   rule baud_count_wire;
+      wBaudCount <= rBaudCounter.value;
+   endrule
+   Wire#(Bit#(3))                            wBaudTickCount      <- mkWire;
+   rule baud_tick_count_wire;
+      wBaudTickCount <= rBaudTickCounter.value;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Rules
+   ////////////////////////////////////////////////////////////////////////////////
+   rule count_baudtick_16x(pwBaudTick16x);
+      rBaudTickCounter.up;
+   endrule
+
+   rule assert_2x_baud_tick(rBaudTickCounter.value() == 0 && pwBaudTick16x);
+      pwBaudTick2x.send;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   method Action clock_enable();
+      if (rBaudCounter.value() + 1 >= divider) begin
+         pwBaudTick16x.send;
+         rBaudCounter.clear;
+      end
+      else begin
+         rBaudCounter.up;
+      end
+   endmethod
+
+   method Action clear();
+      rBaudCounter.clear;
+   endmethod
+
+   method Bool baud_tick_16x();
+      return pwBaudTick16x;
+   endmethod
+
+   method Bool baud_tick_2x();
+      return pwBaudTick2x;
+   endmethod
+
+endmodule: mkBaudGenerator
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation of Input Filter
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkInputFilter#(a initval, a din)(InputFilter#(size, a))
+   provisos( Bits#(a, sa)
+           , Eq#(a)
+           , Add#(0, sa, 1)
+           , Log#(size, logsize)
+           , Add#(logsize, 1, csize)
+           );
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   Counter#(csize)                           counter             <- mkCounter(0);
+   Reg#(a)                                   rOut                <- mkReg(initval);
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Rules
+   ////////////////////////////////////////////////////////////////////////////////
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   method Action clock_enable();
+      if (din == unpack(1) && counter.value() != fromInteger(valueof(size)))
+         counter.up;
+      else if (din == unpack(0) && counter.value() != 0)
+         counter.down;
+
+      if (counter.value() == fromInteger(valueof(size)))
+         rOut <= unpack(1);
+      else if (counter.value() == 0)
+         rOut <= unpack(0);
+   endmethod
+
+   method a _read;
+      return rOut;
+   endmethod
+
+endmodule
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkEdgeDetector#(a initval, a din)(EdgeDetector#(a))
+   provisos( Bits#(a, sa)
+           , Eq#(a)
+           , Add#(0, sa, 1)
+           );
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   Reg#(a)                                   rDinD1              <- mkReg(initval);
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Rules
+   ////////////////////////////////////////////////////////////////////////////////
+   (* fire_when_enabled *)
+   (* no_implicit_conditions *)
+   rule pipeline;
+      rDinD1 <= din;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   method Bool rising();
+      return (din == unpack(1) && rDinD1 == unpack(0));
+   endmethod
+
+   method Bool falling();
+      return (din == unpack(0) && rDinD1 == unpack(1));
+   endmethod
+
+endmodule: mkEdgeDetector
+
+////////////////////////////////////////////////////////////////////////////////
+///
+////////////////////////////////////////////////////////////////////////////////
+function Bool getRising(EdgeDetector#(a) ifc);
+   return ifc.rising;
+endfunction
+
+function Bool getFalling(EdgeDetector#(a) ifc);
+   return ifc.falling;
+endfunction
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation of Synchronizer
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkSynchronizer#(a initval)(Synchronizer#(a))
+   provisos( Bits#(a, sa)
+           , Add#(0, sa, 1)
+           );
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   Reg#(a)                                   d1                  <- mkReg(initval);
+   Reg#(a)                                   d2                  <- mkReg(initval);
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   method Action _write(x);
+      d1 <= x;
+      d2 <= d1;
+   endmethod
+
+   method a _read();
+      return d2;
+   endmethod
+
+endmodule: mkSynchronizer
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation of Input Filter
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkInputMovingFilter#(a din)(InputMovingFilter#(width, threshold, a))
+   provisos( Bits#(a, sa)
+           , Eq#(a)
+           , Add#(0, sa, 1)
+           );
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   Counter#(width)                           counter             <- mkCounter(0);
+   Reg#(a)                                   rOut                <- mkReg(unpack(0));
+   PulseWire                                 pwSample            <- mkPulseWire;
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Rules
+   ////////////////////////////////////////////////////////////////////////////////
+   (* preempts = "threshold_compare, take_sample" *)
+   rule threshold_compare(counter.value() >= fromInteger(valueof(threshold)));
+      rOut <= unpack(1);
+   endrule
+
+   rule take_sample(pwSample && din == unpack(1));
+      counter.up;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   method Action sample();
+      pwSample.send;
+   endmethod
+
+   method Action clear();
+      counter.clear();
+      rOut <= unpack(0);
+   endmethod
+
+   method a _read;
+      return rOut;
+   endmethod
+
+endmodule
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Implementation of UART
+///
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+module mkUART( Bit#(4) charsize
+             , Parity paritysel
+             , StopBits stopbits
+             , Bit#(16) divider
+             , UART#(d) ifc)
+   provisos(Add#(2, _1, d));
+
+   Integer fifodepth = valueof(d);
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Design Elements
+   ////////////////////////////////////////////////////////////////////////////////
+   let                                       baudGen               <- mkBaudGenerator( divider );
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Receive UART
+   ////////////////////////////////////////////////////////////////////////////////
+   FIFOLevelIfc#(Bit#(8), d)                 fifoRecv              <- mkGFIFOLevel(True, False, True);
+
+   Vector#(8, Reg#(Bit#(1)))                 vrRecvBuffer          <- replicateM(mkRegU);
+
+   Reg#(Bit#(1))                             rRecvData             <- mkReg(1);
+
+   Reg#(RecvState)                           rRecvState            <- mkRegA(Start);
+   Reg#(Bit#(4))                             rRecvCellCount        <- mkRegA(0);
+   Reg#(Bit#(4))                             rRecvBitCount         <- mkRegA(0);
+   Reg#(Bit#(1))                             rRecvParity           <- mkRegA(0);
+
+   PulseWire                                 pwRecvShiftBuffer     <- mkPulseWire;
+   PulseWire                                 pwRecvCellCountReset  <- mkPulseWire;
+   PulseWire                                 pwRecvResetBitCount   <- mkPulseWire;
+   PulseWire                                 pwRecvEnableBitCount  <- mkPulseWire;
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Transmit UART
+   ////////////////////////////////////////////////////////////////////////////////
+   FIFOLevelIfc#(Bit#(8), d)                 fifoXmit              <- mkGFIFOLevel(False, False, True);
+
+   Vector#(8, Reg#(Bit#(1)))                 vrXmitBuffer          <- replicateM(mkRegU);
+
+   Reg#(XmitState)                           rXmitState            <- mkRegA(Idle);
+   Reg#(Bit#(4))                             rXmitCellCount        <- mkRegA(0);
+   Reg#(Bit#(4))                             rXmitBitCount         <- mkRegA(0);
+   Reg#(Bit#(1))                             rXmitDataOut          <- mkRegA(1);
+   Reg#(Bit#(1))                             rXmitParity           <- mkRegA(0);
+
+   PulseWire                                 pwXmitCellCountReset  <- mkPulseWire;
+   PulseWire                                 pwXmitResetBitCount   <- mkPulseWire;
+   PulseWire                                 pwXmitEnableBitCount  <- mkPulseWire;
+   PulseWire                                 pwXmitLoadBuffer      <- mkPulseWire;
+   PulseWire                                 pwXmitShiftBuffer     <- mkPulseWire;
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Definitions
+   ////////////////////////////////////////////////////////////////////////////////
+   let tick               = baudGen.baud_tick_16x;
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Baud Clock Enable
+   ////////////////////////////////////////////////////////////////////////////////
+   (* no_implicit_conditions, fire_when_enabled *)
+   rule baud_generator_clock_enable;
+      baudGen.clock_enable;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Receive Rules
+   ////////////////////////////////////////////////////////////////////////////////
+   rule receive_bit_cell_time_counter(tick);
+      if (pwRecvCellCountReset)
+         rRecvCellCount <= 0;
+      else
+         rRecvCellCount <= rRecvCellCount + 1;
+   endrule
+
+   rule receive_buffer_shift(pwRecvShiftBuffer);
+      let v = shiftInAtN(readVReg(vrRecvBuffer), rRecvData);
+      writeVReg(vrRecvBuffer, v);
+   endrule
+
+   rule receive_bit_counter;
+      if (pwRecvResetBitCount)
+         rRecvBitCount <= 0;
+      else if (pwRecvEnableBitCount)
+         rRecvBitCount <= rRecvBitCount + 1;
+   endrule
+
+   rule receive_wait_for_start_bit(rRecvState == Start && tick);
+      pwRecvCellCountReset.send();
+      if (rRecvData == 1'b0) begin
+         rRecvState <= Center;
+      end
+      else begin
+         rRecvState <= Start;
+         pwRecvResetBitCount.send();
+      end
+   endrule
+
+   rule receive_find_center_of_bit_cell(rRecvState == Center && tick);
+      if (rRecvCellCount == 4'h4) begin
+         pwRecvCellCountReset.send();
+         if (rRecvData == 1'b0)
+            rRecvState <= Wait;
+         else
+            rRecvState <= Start;
+      end
+      else begin
+         rRecvState <= Center;
+      end
+   endrule
+
+   rule receive_wait_bit_cell_time_for_sample(rRecvState == Wait && rRecvCellCount == 4'hF && tick);
+      pwRecvCellCountReset.send;
+
+      if (rRecvBitCount == charsize) begin
+         if (paritysel != NONE)
+            rRecvState <= Parity;
+         else if (stopbits != STOP_1)
+            rRecvState <= StopFirst;
+         else
+            rRecvState <= StopLast;
+      end
+      else if (rRecvBitCount == charsize + 1) begin
+         if (paritysel == NONE || stopbits == STOP_1)
+            rRecvState <= StopLast;
+         else
+            rRecvState <= StopFirst;
+      end
+      else if (rRecvBitCount == charsize + 2) begin
+         rRecvState <= StopLast;
+      end
+      else begin
+         rRecvState <= Sample;
+      end
+   endrule
+
+   rule receive_sample_pin(rRecvState == Sample && tick);
+      pwRecvShiftBuffer.send;
+      pwRecvEnableBitCount.send;
+      pwRecvCellCountReset.send;
+      rRecvState <= Wait;
+   endrule
+
+   rule receive_parity_bit(rRecvState == Parity && tick);
+      rRecvParity <= rRecvData;
+      pwRecvEnableBitCount.send;
+      pwRecvCellCountReset.send;
+      rRecvState <= Wait;
+   endrule
+
+   rule receive_stop_first_bit(rRecvState == StopFirst && tick);
+      pwRecvEnableBitCount.send;
+      pwRecvCellCountReset.send;
+      if (rRecvData == 1)
+         rRecvState <= Wait;
+      else
+         rRecvState <= Start;
+   endrule
+
+   rule receive_stop_last_bit(rRecvState == StopLast && tick);
+      Vector#(8, Bit#(1)) data = take(readVReg(vrRecvBuffer));
+      Bit#(8)          bitdata = pack(data) >> (8 - charsize);
+
+      fifoRecv.enq(bitdata);
+      rRecvState <= Start;
+      pwRecvCellCountReset.send;
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Transmit Rules
+   ////////////////////////////////////////////////////////////////////////////////
+   rule transmit_bit_cell_time_counter(tick);
+      if (pwXmitCellCountReset)
+         rXmitCellCount <= 0;
+      else
+         rXmitCellCount <= rXmitCellCount + 1;
+   endrule
+
+   rule transmit_bit_counter;
+      if (pwXmitResetBitCount)
+         rXmitBitCount <= 0;
+      else if (pwXmitEnableBitCount)
+         rXmitBitCount <= rXmitBitCount + 1;
+   endrule
+
+   rule transmit_buffer_load(pwXmitLoadBuffer);
+      Bit#(8) data = pack(fifoXmit.first);
+      fifoXmit.deq;
+
+      writeVReg(vrXmitBuffer, unpack(data));
+      rXmitParity <= parity(data);
+   endrule
+
+   rule transmit_buffer_shift(!pwXmitLoadBuffer && pwXmitShiftBuffer);
+      let v = shiftInAtN(readVReg(vrXmitBuffer), 1);
+      writeVReg(vrXmitBuffer, v);
+   endrule
+
+   rule transmit_wait_for_start_command(rXmitState == Idle && tick);
+      rXmitDataOut <= 1'b1;
+      pwXmitResetBitCount.send;
+      if (fifoXmit.notEmpty) begin
+         pwXmitCellCountReset.send;
+         pwXmitLoadBuffer.send;
+         rXmitState <= Start;
+      end
+      else begin
+         rXmitState <= Idle;
+      end
+   endrule
+
+   rule transmit_send_start_bit(rXmitState == Start && tick);
+      rXmitDataOut <= 1'b0;
+      if (rXmitCellCount == 4'hF) begin
+         rXmitState <= Wait;
+         pwXmitCellCountReset.send;
+      end
+      else begin
+         rXmitState <= Start;
+      end
+   endrule
+
+   rule transmit_wait_1_bit_cell_time(rXmitState == Wait && tick);
+      rXmitDataOut <= head(readVReg(vrXmitBuffer));
+      if (rXmitCellCount == 4'hF) begin
+         pwXmitCellCountReset.send;
+         if (rXmitBitCount == (charsize - 1) && (paritysel == NONE)) begin
+            rXmitState <= Stop;
+         end
+         else if (rXmitBitCount == (charsize - 1) && (paritysel != NONE)) begin
+            rXmitState <= Parity;
+         end
+         else begin
+            rXmitState <= Shift;
+            pwXmitEnableBitCount.send;
+         end
+      end
+      else begin
+         rXmitState <= Wait;
+      end
+   endrule
+
+   rule transmit_shift_next_bit(rXmitState == Shift && tick);
+      rXmitDataOut <= head(readVReg(vrXmitBuffer));
+      rXmitState  <= Wait;
+      pwXmitShiftBuffer.send;
+   endrule
+
+   rule transmit_send_parity_bit(rXmitState == Parity && tick);
+      case(paritysel) matches
+         ODD:        rXmitDataOut <= rXmitParity;
+         EVEN:       rXmitDataOut <= ~rXmitParity;
+         default:    rXmitDataOut <= 1'b0;
+      endcase
+
+      if (rXmitCellCount == 4'hF) begin
+         rXmitState   <= Stop;
+         pwXmitCellCountReset.send;
+      end
+      else begin
+         rXmitState   <= Parity;
+      end
+   endrule
+
+   rule transmit_send_stop_bit(rXmitState == Stop && tick);
+      rXmitDataOut <= 1'b1;
+      if (rXmitCellCount == 4'hF && (stopbits == STOP_1)) begin
+         rXmitState <= Idle;
+         pwXmitCellCountReset.send;
+      end
+      else if (rXmitCellCount == 4'hF && (stopbits == STOP_2)) begin
+         rXmitState <= Stop2;
+         pwXmitCellCountReset.send;
+      end
+      else if (rXmitCellCount == 4'hF && (stopbits == STOP_1_5)) begin
+         rXmitState <= Stop5;
+         pwXmitCellCountReset.send;
+      end
+      else begin
+         rXmitState <= Stop;
+      end
+   endrule
+
+   rule transmit_send_stop_bit1_5(rXmitState == Stop5 && tick);
+      rXmitDataOut <= 1'b1;
+      if (rXmitCellCount == 4'h7) begin
+         rXmitState <= Idle;
+         pwXmitCellCountReset.send;
+      end
+      else begin
+         rXmitState <= Stop5;
+      end
+   endrule
+
+   rule transmit_send_stop_bit2(rXmitState == Stop2 && tick);
+      rXmitDataOut <= 1'b1;
+      if (rXmitCellCount == 4'hF) begin
+         rXmitState <= Idle;
+         pwXmitCellCountReset.send;
+      end
+      else begin
+         rXmitState <= Stop2;
+      end
+   endrule
+
+   ////////////////////////////////////////////////////////////////////////////////
+   /// Interface Connections / Methods
+   ////////////////////////////////////////////////////////////////////////////////
+   interface RS232 rs232;
+      method sout    = rXmitDataOut;
+      method sin     = rRecvData._write;
+   endinterface
+
+   interface Get tx;
+      method ActionValue#(Bit#(8)) get;
+         let data = pack(fifoRecv.first);
+         fifoRecv.deq;
+         return data;
+      endmethod
+   endinterface
+
+   interface Put rx;
+      method Action put(x);
+         fifoXmit.enq(x);
+      endmethod
+   endinterface
+
+   method Bool transmission_done;
+          if(!fifoXmit.notEmpty && rXmitState==Idle)
+             return True;
+          else
+             return False;
+   endmethod
+
+   method Bool receiver_not_empty;
+      return fifoRecv.notEmpty();
+   endmethod
+
+   method Bool receiver_not_full;
+         return fifoRecv.notFull();
+   endmethod
+
+   method Bool transmittor_not_empty;
+         return fifoXmit.notEmpty();
+   endmethod
+endmodule
+
+
+endpackage
+
diff --git a/src/bsv/bsv_lib/Uart_bs.bsv b/src/bsv/bsv_lib/Uart_bs.bsv
new file mode 100644 (file)
index 0000000..0d7a27b
--- /dev/null
@@ -0,0 +1,156 @@
+
+/*
+Copyright (c) 2013, IIT Madras
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+*  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*  Neither the name of IIT Madras  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+Description: Bluespec UART with an AXI interface.
+*/
+package Uart_bs;
+
+       `define Depth 16
+
+       import defined_types::*;
+       import AXI4_Lite_Types::*;
+       import AXI4_Lite_Fabric::*;
+       import Semi_FIFOF::*;
+       `include "instance_defines.bsv"
+       import RS232_modified::*;
+       import GetPut::*;
+       import FIFO::*;
+       import Clocks::*;
+
+
+       interface Ifc_Uart_bs;
+               interface AXI4_Lite_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) slave_axi_uart;
+               interface RS232 coe_rs232;
+       endinterface
+
+       (*synthesize*)
+       module mkUart_bs#(Clock core_clock, Reset core_reset)(Ifc_Uart_bs);
+
+               Clock uart_clock<-exposeCurrentClock;
+               Reset uart_reset<-exposeCurrentReset;
+               Reg#(Bit#(16)) baud_value <-mkReg(`BAUD_RATE);
+               UART#(`Depth) uart <-mkUART(8,NONE,STOP_1,baud_value); // charasize,Parity,Stop Bits,BaudDIV
+               AXI4_Lite_Slave_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE)  s_xactor <- mkAXI4_Lite_Slave_Xactor(clocked_by core_clock, reset_by core_reset);
+               Reg#(Bit#(4)) rg_status <-mkReg(0);             //This register keeps track of whether some data
+                                                                                                                       //is pending to be sent out through the UART Tx
+               
+               SyncFIFOIfc#(AXI4_Lite_Rd_Addr  #(`PADDR,`USERSPACE))           ff_rd_addr <-   mkSyncFIFOToCC(1,core_clock,core_reset);
+               SyncFIFOIfc#(AXI4_Lite_Wr_Addr  #(`PADDR, `USERSPACE))          ff_wr_addr <-   mkSyncFIFOToCC(1,core_clock,core_reset);
+               SyncFIFOIfc#(AXI4_Lite_Wr_Data  #(`Reg_width))                                  ff_wr_data <-   mkSyncFIFOToCC(1,core_clock,core_reset);
+
+               SyncFIFOIfc#(AXI4_Lite_Rd_Data  #(`Reg_width,`USERSPACE))       ff_rd_resp <-   mkSyncFIFOFromCC(1,core_clock);
+               SyncFIFOIfc#(AXI4_Lite_Wr_Resp  #(`USERSPACE))                                  ff_wr_resp <-   mkSyncFIFOFromCC(1,core_clock);
+
+               rule capture_read_request;
+                       let req <- pop_o (s_xactor.o_rd_addr);
+                       ff_rd_addr.enq(req);
+               endrule
+
+               //Address 'h11304 is uart read data
+               rule rl_handle_axi4_uart_read(ff_rd_addr.notEmpty && ff_rd_addr.first.araddr[3:2]=='d1);
+                       let req = ff_rd_addr.first;
+                       ff_rd_addr.deq;
+                       `ifdef verbose $display($time,"\tReq: RD_ADDR %h", req.araddr); `endif
+                       Bit#(8) data<-uart.tx.get;
+                       let lv_resp= AXI4_Lite_Rd_Data {rresp:AXI4_LITE_OKAY, rdata: zeroExtend(data), ruser: ?};
+
+                       `ifdef verbose $display($time,"\tResp: RD_RESP %h", req.araddr); `endif
+                       ff_rd_resp.enq(lv_resp);
+               endrule
+
+               //Address 'b11308 is uart read status
+               rule rl_handle_axi4_uart_status(ff_rd_addr.notEmpty && ff_rd_addr.first.araddr[3:2]!='d1);
+                       let req =ff_rd_addr.first;
+                       ff_rd_addr.deq;
+                       `ifdef verbose $display($time,"\tReq: RD_ADDR %h", req.araddr); `endif
+                       let lv_resp= AXI4_Lite_Rd_Data {rresp:AXI4_LITE_OKAY, rdata: zeroExtend(rg_status), ruser: ?};
+                       if(req.araddr[3:2]==2)
+                               lv_resp.rdata=zeroExtend(rg_status);
+                       else if(req.araddr[3:2]==3)
+                               lv_resp.rdata=zeroExtend(baud_value);
+                       else
+                               lv_resp.rresp=AXI4_LITE_SLVERR;
+
+                       `ifdef verbose $display($time,"\tResp: RD_RESP %h Status: %b", req.araddr, rg_status); `endif
+                       ff_rd_resp.enq(lv_resp);
+               endrule
+               
+               rule send_read_respone_to_bus;
+                       s_xactor.i_rd_data.enq(ff_rd_resp.first);
+                       ff_rd_resp.deq;
+               endrule
+
+               rule capture_write_request;
+                       let req <- pop_o (s_xactor.o_wr_addr);
+                       let wr_data <- pop_o(s_xactor.o_wr_data);
+                       ff_wr_addr.enq(req);
+                       ff_wr_data.enq(wr_data);
+               endrule
+
+               //Address 'b0000 is uart write data
+               rule rl_handle_axi4_write_rx(ff_wr_addr.notEmpty && ff_wr_data.notEmpty && ff_wr_addr.first.awaddr[3:2]==0);
+                       let wr_addr = ff_wr_addr.first;
+                       ff_wr_addr.deq;
+                       let wr_data = ff_wr_data.first;
+                       ff_wr_data.deq;
+
+                       `ifdef verbose $display($time,"\tReq: WR_ADDR %h", wr_addr.awaddr); `endif
+                       `ifdef verbose $display($time,"\tReq: WR_DATA %h", wr_data.wdata); `endif
+
+                       uart.rx.put(truncate(wr_data.wdata));
+         let lv_resp = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_OKAY, buser: ?};
+       ff_wr_resp.enq(lv_resp);
+               endrule
+
+               rule rl_handle_axi4_write(ff_wr_addr.notEmpty && ff_wr_data.notEmpty && ff_wr_addr.first.awaddr[3:2]!=0);
+                       let wr_addr = ff_wr_addr.first;
+                       ff_wr_addr.deq;
+                       let wr_data = ff_wr_data.first;
+                       ff_wr_data.deq;
+
+                       `ifdef verbose $display($time,"\tReq: WR_ADDR %h", wr_addr.awaddr); `endif
+                       `ifdef verbose $display($time,"\tReq: WR_DATA %h", wr_data.wdata); `endif
+
+                       if(wr_addr.awaddr[3:2]=='d3) begin // change the baud value
+                               baud_value<=truncate(wr_data.wdata);
+                       let lv_resp = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_OKAY, buser: ?};
+                       ff_wr_resp.enq(lv_resp);
+                       end
+                       else begin
+                       let lv_resp = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_SLVERR, buser: ?};
+                       ff_wr_resp.enq(lv_resp);
+                       end
+               endrule
+
+               rule send_write_response;
+               s_xactor.i_wr_resp.enq(ff_wr_resp.first);
+                       ff_wr_resp.deq;
+               endrule
+
+               //The status register is 1 if the transmission FIFO is empty
+               (*no_implicit_conditions, fire_when_enabled*)
+               rule rl_update_status_reg;
+                       let lv_status= {pack(uart.receiver_not_empty), pack(uart.receiver_not_full), pack(uart.transmittor_not_empty), pack(uart.transmission_done)};
+                       rg_status<= lv_status;
+                       `ifdef verbose
+                       if(lv_status==0)
+                               $display($time,"-------UART1 TX Fifo not empty"); 
+                       `endif
+               endrule
+
+               interface slave_axi_uart = s_xactor.axi_side;
+               interface coe_rs232= uart.rs232;
+       endmodule
+endpackage
+               
index e66b478cc948cf17bc4044cb767dd6b0b0da9bd0..003ad2c6f793adbf5fd88b40a3ed966360bda211 100644 (file)
@@ -5,12 +5,21 @@
 `define Reg_width 64
 `define PRFDEPTH 6
 `define VADDR 39
+`define UART1 enable
 `define DCACHE_BLOCK_SIZE 4
 `define DCACHE_WORD_SIZE 8
 `define PERFMONITORS                            64
 `define DCACHE_WAYS 4
 `define DCACHE_TAG_BITS 20      // tag_bits = 52
 
+    `define UART1Base       'h00011300
+    `define UART1End        'h000113FF // 2 32-bit registers
+
+`define BAUD_RATE 130
+`ifdef simulate
+  `define BAUD_RATE 5 //130 //
+`endif
+
 
 //`define PWM_AXI4Lite enable