Verilog簡單功能實現--接口設計(並行輸入串行輸出)


利用狀態機實現比較復雜的接口設計:

這是一個將並行數據轉換為串行輸出的變換器,利用雙向總線輸出。這是由EEPROM讀寫器的縮減得到的,首先對I2C總線特征介紹:

I2C總線(inter integrated circuit)雙向二線制串行總線協議為:只有總線處於“非忙”狀態時,數據傳輸才開始。在數據傳輸期間,只要時鍾線為高電平,數據線都必須保持穩定,否則數據線上的任何變化都被當作“啟動”或“停止”信號。

 

下面介紹A、B、C、D的工作狀態:

(1)總線處於非忙狀態(A段):該段內的數據線(sda)和時鍾線(scl)都保持高電平;

(2)啟動數據傳輸(B段):當時鍾線(scl)為高電平時,數據線(sda)由高電平變為低電平的下降沿被認為是“啟動”信號;

(3)停止數據傳輸(C段):當時鍾線(scl)為高電平時,數據線(sda)由低電平變為高電平的上升沿被認為是“停止”信號;

(4)數據有效(D段):在出現“啟動”信號之后,在時鍾線(scl)為高電平時,數據線是穩定的,這是數據線上的數據就是要傳送的數據,數據線上的數據改變必須在時鍾線(scl)為低電平期間完成,每個數據占用一個時鍾;

(5)應答信號:每個正在接受數據的EEPROM在接收到一個字節的數據后,通常需要發出一個應答信號;而每個正在發送數據的EEPROM在發出一個字節的數據后,通常需要接受一個應答信號;EEPROM讀寫控制器必須提供一個與這個應答信號相聯系的二外的始終脈沖。

其控制字節一共有8位:1010xxxW/R 其中1010是I2C總線器件特征編碼,xxx表示地址,W/R表示讀寫狀態。

 

在實現並行輸入串行輸出時,需要兩個狀態機:

主狀態機主要控制內部存儲器和輸入端的連接,以及給出應答信號;從狀態機主要負責總線連接時,內部寄存器的最高位輸出個移位;

 

狀態機的源碼如下:

復制代碼
  1 module parallel_to_serial(rst,clk,addr,data,sda,ack);
  2   input rst,clk;
  3   input [7:0]data,addr;
  4   
  5   inout sda;                     //data bus
  6   output ack;                    //ask for next address/data writting wo eeprm;
  7   reg link_write;                //whether connect to output
  8   reg [2:0]state;                //main status,
  9   reg [4:0]sh8out_state;         //serial output status
 10   reg [7:0]sh8out_buf;           //output data buffer
 11   reg finish_F;                  //whether finished an operation of main status
 12   reg ack;                       
 13   
 14   parameter  idle=0, addr_write=3'd1, data_write=3'd2, stop_ack=3'd4;          //main status code
 15   parameter  bit0=1, bit1=2, bit2=3, bit3=4, bit4=5, bit5=6, bit6=7, bit7=8;   //serial output status code
 16   
 17   assign sda=link_write?sh8out_buf[7]:1'bz;               //???????????
 18   
 19   always @(posedge clk)
 20   begin
 21   if(!rst)                       //reset
 22     begin
 23     ack<=0;
 24     link_write<=0;               //???????
 25     finish_F<=0;
 26     state<=idle;
 27     sh8out_state<=idle;
 28     sh8out_buf<=0;
 29     end
 30     else
 31       case(state)
 32         idle:begin
 33              link_write<=0;        //??????
 34              ack<=0;
 35              finish_F<=0;
 36              sh8out_buf<=addr;     //???????
 37              sh8out_state<=idle;
 38              state<=addr_write;    //???????
 39              end
 40         addr_write:begin
 41              if (finish_F==0) begin shift8_out;end    //???????
 42              else
 43                begin
 44                link_write<=0;
 45                ack<=0;
 46                finish_F<=0;
 47                sh8out_buf<=data;  //???????
 48                state<=data_write;
 49                sh8out_state<=idle;     
 50                end          
 51              end
 52         data_write:begin
 53              if (finish_F==0) begin shift8_out;end    //???????
 54              else
 55                begin
 56                link_write<=0;
 57                finish_F<=0;
 58                state<=stop_ack;
 59                ack<=1;            //????????
 60                end
 61              end 
 62         stop_ack:begin            //????
 63              ack<=0;
 64              state<=idle;
 65              end    
 66       endcase
 67     end
 68     
 69     task shift8_out;             //???????
 70     begin
 71     case(sh8out_state)
 72       idle:begin
 73            link_write<=1;        //?????????????????17?assign sda=link_write?sh8out_buf[7]:1'bz;  sda??????????sh8out_buf?????  
 74            sh8out_state<=bit7;
 75            end
 76       bit7:begin
 77            link_write<=1;       
 78            sh8out_buf=sh8out_buf<<1;   //?????data?????bit6
 79            sh8out_state<=bit6;
 80            end
 81       bit6:begin
 82            link_write<=1;       
 83            sh8out_buf=sh8out_buf<<1;  
 84            sh8out_state<=bit5;
 85            end
 86       bit5:begin
 87            link_write<=1;       
 88            sh8out_buf=sh8out_buf<<1;   
 89            sh8out_state<=bit4;
 90            end
 91       bit4:begin
 92            link_write<=1;       
 93            sh8out_buf=sh8out_buf<<1;   
 94            sh8out_state<=bit3;
 95            end
 96       bit3:begin
 97            link_write<=1;       
 98            sh8out_buf=sh8out_buf<<1;   
 99            sh8out_state<=bit2;
100            end
101       bit2:begin
102            link_write<=1;       
103            sh8out_buf=sh8out_buf<<1;   
104            sh8out_state<=bit1;
105            end
106       bit1:begin
107            link_write<=1;       
108            sh8out_buf=sh8out_buf<<1;   
109            sh8out_state<=bit0;
110            end
111       bit0:begin
112            link_write<=0;       
113            finish_F<=1;
114            end
115       endcase
116     end
117     endtask
118 endmodule
復制代碼

 

 測試程序:

 

復制代碼
 1 `timescale 1ns/1ns
 2 `define clk_period 50
 3 module parallel_to_serial_test;
 4   reg rst,clk;
 5   reg [7:0]data,addr;
 6   wire ack,sda;
 7   wire [2:0]state;                //main status,
 8   wire [4:0]sh8out_state; 
 9   
10   initial 
11   begin
12   clk=0;
13   rst=1;
14   data=0;
15   addr=0;
16   #(2*`clk_period) rst=0;
17   #(2*`clk_period) rst=1;
18   #(100*`clk_period) $stop;
19   end
20   
21   always #50 clk=~clk;
22   
23   
24 
25   always @(posedge clk)
26   begin data=data+1; addr=addr+1; end
27   
28   parallel_to_serial m(
29                        .rst(rst),
30                        .clk(clk),
31                        .addr(addr),
32                        .data(data),
33                        .sda(sda),
34                        .ack(ack)
35   );
36   
37   assign state=m.state;
38   assign sh8out_state=m.sh8out_state; 
39 endmodule
復制代碼

波形信號:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM