⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcst_rx_ctl.v

📁 ---简化版
💻 V
字号:
module mcst_rx_ctl
(
	input pci_rst_l,    // 计算机系统复位信号
	input clk,          // PCI总线时钟(33MHz)
	input clk_10K,      // 10K参考时钟
	input clear,        // 清除FIFO中所有数据
	input rx_mcst,      // 曼彻斯特数据总线
	input rdreq,        // 读FIFO数据请求
	
	output [31:0] data, // 从FIFO中读出的数据
	output empty,       // = 1: data fifo is emtpy
	output full         // = 1: data fifo is full
);

//====================================================
//--------------接收数据滤波---------------------------
    
    reg rx_clk; // 接收数据及时钟信号
    reg clock;   // 10K同步时钟
    reg [6:0] filter_cnt;
    
    always @ (negedge pci_rst_l or posedge clk)   // 同步接收数据与pci系统时钟
    begin
		if (!pci_rst_l) begin
            rx_clk <= 1'b0;
            filter_cnt <= 7'd0;
		    end
        else if (!rx_mcst) begin
		    rx_clk <= 1'b0;
		    filter_cnt <= 7'd0;
		    end
		else if (filter_cnt == 7'd124) begin
            rx_clk <= 1'b1;
            filter_cnt <= filter_cnt;
            end
        else begin
            rx_clk <= rx_clk;
            filter_cnt <= filter_cnt + 7'b1;
            end
	end
	
    always @ (negedge pci_rst_l or posedge clk) // 同步设定的接收参考时钟
    begin
        if (!pci_rst_l)
			clock <= 1'b0;
        else
            clock <= clk_10K;
    end

//====================================================
//---------------接收数据有效性检查-------------------

    reg wrreq; // --------------- 接收FIFO写入数据请求
    reg [47:0] rx_data_b; // ----- 临时位值数据记录
    reg [5:0] data_cnt; // ------ 记录每次接收数据的位计数
    reg [4:0] space_cnt; // ----- 空闲周期计数(记录12个总线必须的空闲周期)
    reg [10:0] cnt_10K; // ------ 10K采样时钟计时(时间间隔为50uS)1649
    wire load_10K_F; // --------- 定时50uS(以33MHz为基准)
    reg [4:0] state;
    parameter S0 = 4'h0, 
              S1 = 4'h1, 
              S2 = 4'h2, 
              S3 = 4'h3, 
              S4 = 4'h4, 
              S5 = 4'h5, 
              S6 = 4'h6, 
              S7 = 4'h7;
    
    
    assign load_10K_F  = (cnt_10K == 11'd1649) ? 1'b1 : 1'b0;
    
	always @ (negedge pci_rst_l or posedge clk) // 接收数据空及前置4个0位的检查
    begin
		if (!pci_rst_l) begin
            state <= S0;
			wrreq <= 1'b0;
			end
		else // ------------------- 接收数据为低电平,采样12个空闲周期
            case (state)
            S0: begin
                space_cnt <= 5'd0;
                if (clock) begin // --- 参考时钟为高,转入状态S1
                    state <= S1;
                    end
                else begin // --------- 参考时钟为低,转入状态S2
                    state <= S2;
                    end
                end
            S1: begin 
                if (rx_clk) // ------------------------- 若空闲间隔不足12个,则转入初始状态
                    state <= S0;
                else if (space_cnt == 5'd24) // -------- 若空闲周期达到12个,等待接收数据的第1个脉冲输入
                    state <= S3;
                else if (!clock) begin // -------------- 检查参考时钟,若为低,计数器加1,并进入状态S2
                    state <= S2;
                    space_cnt <= space_cnt + 5'd1;
                    end
                else 
                    space_cnt <= space_cnt;
                end
            S2: begin 
                if (rx_clk) // ------------------------- 若空闲间隔不足12个,则转入初始状态
                    state <= S0;
                else if (space_cnt == 5'd24) // -------- 若空闲周期达到12个,等待接收数据的第1个脉冲输入
                    state <= S3;
                else if (clock) begin // --------------- 检查参考时钟,若为高,计数器加1,并进入状态S1
                    state <= S1;
                    space_cnt <= space_cnt + 5'd1;
                    end
                else 
                    space_cnt <= space_cnt;
                end
            S3: begin // ------------------------------- 空闲周期检查完,等待第一个脉冲到来
                if (rx_clk) begin
                    state <= S4;
                    cnt_10K    <= 11'd1000; // --------- 预装定时数据,使第一个脉冲高电平后的20uS处记录第一个0数据
                    end
                end
            S4: begin // ------------------------------- 处理第1个0数据脉冲
                if (load_10K_F) begin // --------------- 第一个脉冲到来后,延时约20uS,记录第一个位数据
                    cnt_10K <= 0;
                    if (rx_clk) begin
                        rx_data_b[0] <= 1'b0;
                        rx_data_b[1] <= 1'b1;
                        data_cnt   <= 6'd2;
                        state <= S5;
                        end
                    else // ---------------------------- 第一个脉冲出现错误,退回状态0
                        state <= S0;
                    end
                else
                    cnt_10K <= cnt_10K + 11'b1;
                end
            S5: begin // ------------------------------- 记录后3个起始0数据位、4个地址位、16个数据位
                if (data_cnt == 6'd48)
                    state <= S6;
                else if (load_10K_F) begin // ---------- 在每个曼彻斯特数据的位周期,前后半周期中延时约20uS,记录两次数据
                    cnt_10K  <= 0;
                    data_cnt <= data_cnt + 6'd1;
                    rx_data_b[data_cnt] <= rx_clk;
                    end
                else
                    cnt_10K <= cnt_10K + 11'b1;
                end
            S6: begin // ------------------------------- 若数据有效,准备写入FIFO
                if (rx_data_b[7:0] == 8'haa)
                    wrreq <= 1'b1;
                state <= S7;
                end
            S7: begin // ------------------------------- 数据处理完毕,进入空闲状态S0
                wrreq <= 1'b0;
                state <= S0;
                end
            default: begin
                wrreq <= 1'b0;
                state <= S0;
                end
            endcase
	end

//====================================================
//---------------处理接收数据-------------------------
    
    wire [31:0] rx_data;
    assign rx_data[0]  = (rx_data_b[17:16] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[1]  = (rx_data_b[19:18] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[2]  = (rx_data_b[21:20] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[3]  = (rx_data_b[23:22] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[4]  = (rx_data_b[25:24] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[5]  = (rx_data_b[27:26] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[7]  = (rx_data_b[31:30] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[8]  = (rx_data_b[33:32] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[9]  = (rx_data_b[35:34] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[10] = (rx_data_b[37:36] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[11] = (rx_data_b[39:38] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[12] = (rx_data_b[41:40] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[13] = (rx_data_b[43:42] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[14] = (rx_data_b[45:44] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[15] = (rx_data_b[47:46] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[16] = (rx_data_b[9:8]   == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[17] = (rx_data_b[11:10] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[18] = (rx_data_b[13:12] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[19] = (rx_data_b[15:14] == 2'b10) ? 1'b0 : 1'b1;
    assign rx_data[31:20] = 12'b0;
    
/*---------------------------------------------------------
    Data FIFO
---------------------------------------------------------*/ 
mcst_rx_fifo rx_Data_FIFO (
    .clock(clk),
	.data(rx_data), 
	.rdreq(rdreq),
	.sclr(clear),
    .wrreq(wrreq),
	.empty(empty),
	.full(full), 
	.q(data)
	); 
	
	
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -