差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
rs-232 [2017/03/26 19:48]
gongyu [接收器]
rs-232 [2017/03/26 20:00] (当前版本)
gongyu [应用案例]
行 231: 行 231:
 Our implementation works like that: Our implementation works like that:
  
-The module assembles data from the RxD line as it comes. +  * The module assembles data from the RxD line as it comes. 
-As a byte is being received, it appears on the "​data"​ bus. Once a complete byte has been received, "​data_ready"​ is asserted for one clock.+  ​* ​As a byte is being received, it appears on the "​data"​ bus. Once a complete byte has been received, "​data_ready"​ is asserted for one clock. 
 Note that "​data"​ is valid only when "​data_ready"​ is asserted. The rest of the time, don't use it as new data may come that shuffles it. Note that "​data"​ is valid only when "​data_ready"​ is asserted. The rest of the time, don't use it as new data may come that shuffles it.
  
-Oversampling+===== Oversampling ​=====
  
 An asynchronous receiver has to somehow get in-sync with the incoming signal (it normally doesn'​t have access to the clock used by the transmitter). An asynchronous receiver has to somehow get in-sync with the incoming signal (it normally doesn'​t have access to the clock used by the transmitter).
行 245: 行 246:
 Let's assume that we have a "​Baud8Tick"​ signal available, asserted 921600 times a second. Let's assume that we have a "​Baud8Tick"​ signal available, asserted 921600 times a second.
  
-The design+===== The design ​=====
  
 First, the incoming "​RxD"​ signal has no relationship with our clock. First, the incoming "​RxD"​ signal has no relationship with our clock.
 We use two D flip-flops to oversample it, and synchronize it to our clock domain. We use two D flip-flops to oversample it, and synchronize it to our clock domain.
  
 +<code verilog>
 reg [1:0] RxD_sync; reg [1:0] RxD_sync;
 always @(posedge clk) if(Baud8Tick) RxD_sync <= {RxD_sync[0],​ RxD}; always @(posedge clk) if(Baud8Tick) RxD_sync <= {RxD_sync[0],​ RxD};
-We filter the data, so that short spikes on the RxD line aren't mistaken with start bits.+</​code>​
  
 +We filter the data, so that short spikes on the RxD line aren't mistaken with start bits.
 +<code verilog>
 reg [1:0] RxD_cnt; reg [1:0] RxD_cnt;
 reg RxD_bit; reg RxD_bit;
行 268: 行 272:
   if(RxD_cnt==2'​b11) RxD_bit <= 1;   if(RxD_cnt==2'​b11) RxD_bit <= 1;
 end end
-A state machine allows us to go through each bit received, once a "​start"​ is detected.+</​code>​
  
 +A state machine allows us to go through each bit received, once a "​start"​ is detected.
 +<code verilog>
 reg [3:0] state; reg [3:0] state;
  
行 287: 行 293:
   default: state <= 4'​b0000;​   default: state <= 4'​b0000;​
 endcase endcase
-Notice that we used a "​next_bit"​ signal, to go from bit to bit.+</​code>​
  
 +Notice that we used a "​next_bit"​ signal, to go from bit to bit.
 +<code verilog>
 reg [2:0] bit_spacing;​ reg [2:0] bit_spacing;​
  
行 303: 行 311:
 reg [7:0] RxD_data; reg [7:0] RxD_data;
 always @(posedge clk) if(Baud8Tick && next_bit && state[3]) RxD_data <= {RxD_bit, RxD_data[7:​1]};​ always @(posedge clk) if(Baud8Tick && next_bit && state[3]) RxD_data <= {RxD_bit, RxD_data[7:​1]};​
-The complete ​code can be found here. +</code>
-It has a few improvements;​ follow the comments in the code.+
  
-Links 
  
-More details on Asynchronous Communication 
 ====== 应用案例 ====== ====== 应用案例 ======
 +This design allows controlling a few FPGA pins from your PC (through your PC's serial port).
 +
 +  * It create 8 outputs on the FPGA (port named "​GPout"​). GPout is updated by any character that the FPGA receives.
 +  * Also 8 inputs on the FPGA (port named "​GPin"​). GPin is transmitted every time the FPGA receives a character.
 +
 +The GP outputs can be used to control anything remotely from your PC, might be LEDs or a coffee machine...
 +<code verilog>
 +module serialGPIO(
 +    input clk,
 +    input RxD,
 +    output TxD,
 +
 +    output reg [7:0] GPout, ​ // general purpose outputs
 +    input [7:0] GPin  // general purpose inputs
 +);
 +
 +wire RxD_data_ready;​
 +wire [7:0] RxD_data;
 +async_receiver RX(.clk(clk),​ .RxD(RxD), .RxD_data_ready(RxD_data_ready),​ .RxD_data(RxD_data));​
 +always @(posedge clk) if(RxD_data_ready) GPout <= RxD_data;
 +
 +async_transmitter TX(.clk(clk),​ .TxD(TxD), .TxD_start(RxD_data_ready),​ .TxD_data(GPin));​
 +endmodule
 +
 +</​code>​
 +
 +Remember to grab the async_receiver and async_transmitter modules here, and to update the clock frequency values inside.