實驗簡述
將輸入的數據流經過曼徹斯特編碼器編碼后經過解碼器恢復為原來的輸入序列。
一、曼徹斯特碼簡介
曼徹斯特碼(Manchester code),又稱數字雙向碼、分相碼或相位編碼(PE),是一種常用的二源碼線路編碼方式之一,被物理層使用來編碼一個同步位流的時鐘和數據。在通信技術中,用來表示所要發送比特流中的數據宇定時信號所結合起來的代碼。常用在以太網通信,列車總線控制,工業總線等領域。
二、編碼規則
有兩個輸入時鐘,一個是基帶時鐘(起同步信號作用),一個是頻帶時鐘。輸入的數據流是基帶時鐘域信號,經過編碼后變成頻帶時鐘域信號輸出。曼徹斯特編碼是將輸入為1的變成輸出前半拍為1,后半拍為0,輸入為0的變成前半拍為0,后半拍為1的頻帶信號。
三、時序圖
輸入序列以101為例,經過編碼后應為100110
四、FPGA實現
1、頂層架構
2、信號說明
信號 | 功能 | 說明 |
clk_b | 基帶時鐘,作為同步信號使用 | 外部輸入 |
clk_f | 頻帶時鐘,系統工作時鐘 | 外部輸入 |
rst_n | 系統復位 | 外部輸入 |
enc_in | 輸入數據流 | 外部輸入 |
enc_en | 編碼使能 | 外部輸入 |
enc_out | 數據流經編碼后的輸出,輸入到解碼模塊 | 編碼輸出,解碼輸入 |
dec_en | 解碼使能 | 外部輸入 |
dec_out | 解碼輸出 | 輸出 |
3、頂層代碼
module manchester(clk_b, clk_f, rst_n, enc_in, enc_en, dec_out, dec_en); input clk_b, clk_f, rst_n; input enc_in; input enc_en; output dec_out; input dec_en;
wire enc_out;
manchester_enc ENC( .clk_f(clk_f), .clk_b(clk_b), .rst_n(rst_n), .enc_en(enc_en), .enc_in(enc_in), .enc_out(enc_out) );
manchester_dec DEC( .clk_f(clk_f), .clk_b(clk_b), .rst_n(rst_n), .dec_en(dec_en), .enc_out(enc_out), .dec_out(dec_out) );
endmodule |
4、編碼模塊
采用狀態機來實現編碼模塊。
當檢測到編碼使能為高時,狀態機開始執行,判斷clk_b的值為1時,在S1狀態等待,當clk_b的值為0時,判斷輸入的值是1還是0。(clk_b主要起基頻同步作用)如果是1,跳轉到S2狀態,并將enc_out賦值為1。到S2狀態后,無條件跳回S1狀態,并將enc_out賦值為0。如果是0,跳轉到S3狀態,并將enc_out賦值為0。到S3狀態后,無條件跳回S1狀態,并將enc_out賦值為1。
狀態轉移圖如下:
說明:圓圈代表狀態,→ 代表轉移,轉移下面的文本框代表轉移時的動作。以后文章的狀態轉移圖均按此繪制。
module manchester_enc(clk_f, clk_b, rst_n, enc_en, enc_in, enc_out); input clk_f, clk_b, rst_n; input enc_en; input enc_in; output reg enc_out;
reg [2:0] state_c, state_n;
localparam S1 = 3'b001; localparam S2 = 3'b010; localparam S3 = 3'b100;
wire S12S2_start ; wire S12S3_start ; wire S22S1_start ; wire S33S1_start ;
//四段式狀態機 //第一段:同步時序always模塊,格式化描述次態寄存器遷移到現態寄存器(不需更改- always@(posedge clk_f or negedge rst_n)begin if(!rst_n)begin state_c <= S1; end else begin state_c <= state_n; end end //第二段:組合邏輯always模塊,描述狀態轉移條件判斍 always@(*)begin if(enc_en) case(state_c) S1:begin if(S12S2_start)begin state_n = S2; end else if(S12S3_start)begin state_n = S3; end else begin state_n = state_c; end end S2:begin if(S22S1_start)begin state_n = S1; end else begin state_n = state_c; end end S3:begin if(S33S1_start)begin state_n = S1; end else begin state_n = state_c; end end default:begin state_n = S1; end endcase else state_n = S1; end //第三段:設計轉移條件 assign S12S2_start = state_c==S1 && clk_b && !enc_in; assign S12S3_start = state_c==S1 && clk_b && enc_in; assign S22S1_start = state_c==S2 && 1; assign S33S1_start = state_c==S3 && 1; //第四段:同步時序always模塊,格式化描述寄存器輸出(可有多個輸出- always @(posedge clk_f or negedge rst_n)begin if(!rst_n)begin enc_out <=1'b0; //初始匍 end else if(enc_en) if((state_c==S1 && !enc_in) || (state_c==S3))begin enc_out <= 1'b0; end else if((state_c==S1 && enc_in) || (state_c==S2))begin enc_out <= 1'b1; end else begin enc_out <= 1'b0; end else enc_out <=1'b0; end endmodule |
5、解碼模塊
解碼模塊也采用狀態機實現,當檢測到dec_en為高時,狀態機才執行,判斷clk_b的值,當clk_b為0時,在S1上等待,當clk_b為1時,判斷enc_out的值,為1時跳轉到S2狀態,并將dec_out賦值為。S2狀態無條件跳轉到S1狀態。為0時,跳轉到S3狀態并將dec_out賦值為0。S3狀態無條件跳轉到S1狀態。
狀態轉移圖如下:
解碼模塊代碼
module manchester_dec(clk_f, clk_b, rst_n, dec_en, enc_out, dec_out); input clk_f, clk_b, rst_n; input dec_en; input enc_out; output reg dec_out;
reg [2:0] state_c, state_n;
localparam S1 = 3'b001; localparam S2 = 3'b010; localparam S3 = 3'b100;
wire S12S2_start ; wire S12S3_start ; wire S22S1_start ; wire S33S1_start ;
always@(posedge clk_f or negedge rst_n)begin if(!rst_n)begin state_c <= S1; end else begin state_c <= state_n; end end //第二段:組合邏輯always模塊,描述狀態轉移條件判斍 always@(*)begin if(dec_en) case(state_c) S1:begin if(S12S2_start)begin state_n = S2; end else if(S12S3_start)begin state_n = S3; end else begin state_n = state_c; end end S2:begin if(S22S1_start)begin state_n = S1; end else begin state_n = state_c; end end S3:begin if(S33S1_start)begin state_n = S1; end else begin state_n = state_c; end end default:begin state_n = S1; end endcase else state_n = S1; end //第三段:設計轉移條件 assign S12S2_start = state_c==S1 && (!clk_b) && enc_out; assign S12S3_start = state_c==S1 && (!clk_b) && (!enc_out); assign S22S1_start = state_c==S2 && 1; assign S33S1_start = state_c==S3 && 1; //第四段:同步時序always模塊,格式化描述寄存器輸出(可有多個輸出- always @(posedge clk_f or negedge rst_n)begin if(!rst_n)begin dec_out <=1'b0; //初始匍 end else if(dec_en) if(state_c==S1 && (!clk_b) && enc_out)begin dec_out <= 1'b1; end else if((state_c==S1 && (!clk_b) && (!enc_out)))begin dec_out <= 1'b0; end else begin dec_out <= dec_out; end else dec_out <=1'b0; end endmodule |
6、仿真驗證
tb文件參考工程文件夾中的sim文件夾
輸入的數據流enc_in為1011,對應的曼徹斯特碼應為10011010
我們看到輸入到編碼模塊的enc_in與解碼模塊的dec_out的輸出是一樣的
再來看編碼之后的數據流
enc_out為10011010與結果一致
解碼模塊圖形
溫馨提示:明德揚2023推出了全新課程——邏輯設計基本功修煉課,降低學習FPGA門檻的同時,增加了學習的趣味性,并組織了考試贏積分活動
http://www.cqqtmy.cn/ffkc/415.html
(點擊→了解課程詳情?)感興趣請聯系易老師:13112063618(微信同步)