📄 mcst_rx_ctl.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 + -