Compare commits

..

No commits in common. "main" and "feature" have entirely different histories.

13 changed files with 334 additions and 599 deletions

View File

@ -29,25 +29,17 @@ module UDP_data_process (
input eth_linked, input eth_linked,
output reg pulse_second, output reg pulse_second,
// input data_fifo_rden,
// UDP接收FIFO接口 // UDP接收FIFO接口
output reg udp_app_recv_fifo_rden_0, output reg udp_app_recv_fifo_rden,
input [7:0] udp_app_recv_fifo_rddata_0, input [7:0] udp_app_recv_fifo_rddata,
input [11:0] udp_app_recv_fifo_rdcnt_0, input [11:0] udp_app_recv_fifo_rdcnt,
input udp_app_recv_fifo_empty_0, input udp_app_recv_fifo_empty,
// UDP0发送FIFO接口 // UDP发送FIFO接口
input udp_app_send_fifo_rden_0, input udp_app_send_fifo_rden,
output [7:0] udp_app_send_fifo_rddata_0, output [7:0] udp_app_send_fifo_rddata,
output [11:0] udp_app_send_fifo_rdcnt_0, output [11:0] udp_app_send_fifo_rdcnt,
output udp_app_send_fifo_empty_0, output udp_app_send_fifo_empty,
// UDP1接收FIFO接口
//we don't need
// UDP1发送FIFO接口
input udp_app_send_fifo_rden_1,
output [7:0] udp_app_send_fifo_rddata_1,
output [11:0] udp_app_send_fifo_rdcnt_1,
output udp_app_send_fifo_empty_1,
// TOE寄存器接口 // TOE寄存器接口
output reg TOE_reg_wren, output reg TOE_reg_wren,
output reg TOE_reg_rden, output reg TOE_reg_rden,
@ -71,16 +63,16 @@ module UDP_data_process (
input [31:0] DAQ_Status_Info_data input [31:0] DAQ_Status_Info_data
); );
// wire udp_app_recv_fifo_rden_r;
wire udp_app_recv_fifo_ready; wire udp_app_recv_fifo_ready;
wire udp_recv_data_tvalid; wire udp_recv_data_tvalid;
wire [31:0]udp_recv_data; wire [31:0]udp_recv_data;
// 协议头 // 协议头
parameter [15:0] HDR_DATA = 16'h494e; parameter [15:0] HDR_DATA = 16'h4d44;
parameter [15:0] HDR_CTRL = 16'h4d44; parameter [15:0] HDR_CTRL = 16'h4547;
parameter [15:0] HDR_TOE = 16'h4547; parameter [15:0] HDR_TOE = 16'h494e;
// 4个状态空闲读Header读Length读Payload&Check // 4个状态空闲读Header读Length读Payload&Check
reg [1:0] parse_state; reg [1:0] parse_state;
@ -92,20 +84,16 @@ localparam P_DATA = 2'd1;
reg [2:0] deal_state; reg [2:0] deal_state;
reg deal_busy; reg deal_busy;
localparam D_IDLE = 3'd0; localparam D_IDLE = 3'd0;
localparam D_R_WAIT =3'd7; //后面新增的作用是等待读出新数据解决多级驱动问题
localparam D_HEAD = 3'd1; localparam D_HEAD = 3'd1;
localparam D_TOE_1 = 3'd2; localparam D_TOE_1 = 3'd2;
localparam D_TOE_2 = 3'd3; localparam D_TOE_2 = 3'd3;
localparam D_TOE_3 = 3'd4; localparam D_EXE = 3'd4;
localparam D_EXE = 3'd5; localparam D_CTRL =3'd5;
localparam D_CTRL =3'd6;
reg [3:0]TOE_SFP_ID; reg [3:0]TOE_SFP_ID;
reg TOE_RW_FLAG; reg TOE_RW_FLAG;
reg [31:0] TOE_ADDR; reg [31:0] TOE_ADDR;
reg [31:0] TOE_DATA; reg [31:0] TOE_DATA;
reg [19:0] TOE_LENGTH;
reg [15:0] header_reg; reg [15:0] header_reg;
@ -122,7 +110,7 @@ wire [31:0]udp_recv_data_reorder;
reg cnt; reg cnt;
wire data_fifo_rst ;
reg data_fifo_wren; reg data_fifo_wren;
reg [31:0] data_fifo_din; reg [31:0] data_fifo_din;
reg data_fifo_rden; reg data_fifo_rden;
@ -135,64 +123,29 @@ reg [27:0] second_timer = 'b0;
//观察内部的ila
ila_00 ila_udp_data (
.clk(clk), // input wire clk
.probe0({
reset ,
udp_recv_data_tvalid ,
udp_recv_data ,
// data_fifo_din,
// data_fifo_wren,
parse_state,
recv_udp_frame_last,
payload_remain,
crc32_calc,
crc_match ,
crc_error ,
deal_state,
udp_app_recv_fifo_ready,
TOE_reg_wren,
TOE_reg_rden,
data_fifo_dout,
data_fifo_rden,
TOE_reg_din,
header_reg,
state_report_en,
TOE_SFP_ID,
TOE_DATA,
TOE_ADDR,
TOE_RW_FLAG,
second_timer,
pulse_second
})
);
// --------------------------- // ---------------------------
// 读取FIFO逻辑 // 读取FIFO逻辑
// --------------------------- // ---------------------------
always@(posedge clk) always@(posedge clk)
if(reset) if(reset)
udp_app_recv_fifo_rden_0 <= 1'b0; //仿真和上板的区别有2个地方一个是这边另外一个是秒脉冲的计数器2处 udp_app_recv_fifo_rden <= 1'b0;
else if(udp_app_recv_fifo_rdcnt_0 == 12'b1) //上板后不得注释记得取消注释 //实际应该是读计数为1时候就要拉低了不然板子会多读一个 else if((~udp_app_recv_fifo_empty) && udp_app_recv_fifo_ready && (~deal_busy))
udp_app_recv_fifo_rden_0 <= 1'b0; udp_app_recv_fifo_rden <= 1'b1;
else if((~udp_app_recv_fifo_empty_0) && udp_app_recv_fifo_ready && (~deal_busy) && eth_linked) //如果连接成功才会去读,连接失败不能去读fifo else if(udp_app_recv_fifo_rdcnt == 12'b0)
udp_app_recv_fifo_rden_0 <= 1'b1; udp_app_recv_fifo_rden <= 1'b0;
else else
udp_app_recv_fifo_rden_0 <= 1'b0; udp_app_recv_fifo_rden <= 1'b0;
//assign udp_app_recv_fifo_rden_r = udp_app_recv_fifo_rden && (~udp_app_recv_fifo_empty); // udp recv data does not delay, so the en needn't delay
axis_dwidth_converter_0 axis_dwidth_converter_udprx( axis_dwidth_converter_0 axis_dwidth_converter_udprx(
.aclk (clk), // input .aclk (clk), // input
.aresetn (~reset), // input .aresetn (~reset), // input
.s_axis_tvalid(udp_app_recv_fifo_rden_0), // input .s_axis_tvalid(udp_app_recv_fifo_rden), // input
.s_axis_tready(udp_app_recv_fifo_ready), // output .s_axis_tready(udp_app_recv_fifo_ready), // output
.s_axis_tdata (udp_app_recv_fifo_rddata_0), // input [7:0] .s_axis_tdata (udp_app_recv_fifo_rddata), // input [7:0]
.m_axis_tvalid(udp_recv_data_tvalid), // output .m_axis_tvalid(udp_recv_data_tvalid), // output
.m_axis_tready(1'b1), // input .m_axis_tready(1'b1), // input
.m_axis_tdata (udp_recv_data) // output [63:0] .m_axis_tdata (udp_recv_data) // output [63:0]
@ -236,7 +189,7 @@ always @(posedge clk or posedge reset) begin
parse_state <= P_IDLE; parse_state <= P_IDLE;
crc32_recv <= udp_recv_data_reorder; crc32_recv <= udp_recv_data_reorder;
recv_udp_frame_last <=1'b1; //收到完整一帧 recv_udp_frame_last <=1'b1; //收到完整一帧
// data_fifo_rden <= 1'b1; //不读的话又会不完整 data_fifo_rden <= 1'b1;
if(crc32_calc == udp_recv_data_reorder) if(crc32_calc == udp_recv_data_reorder)
crc_match =1'b1; crc_match =1'b1;
else else
@ -256,12 +209,12 @@ always @(posedge clk or posedge reset) begin
end end
end end
//数据接收完成接下来开始处理数据
fifo_generator_0 data_cache_fifo ( fifo_generator_0 data_cache_fifo (
.clk (clk), // 时钟 .clk (clk), // 时钟
.srst (reset), // 同步复位 .srst (data_fifo_rst), // 同步复位
.din (data_fifo_din), // 写入数据 .din (data_fifo_din), // 写入数据
.wr_en (data_fifo_wren), // 写使能 .wr_en (data_fifo_wren), // 写使能
.rd_en (data_fifo_rden), // 读使能 .rd_en (data_fifo_rden), // 读使能
@ -270,7 +223,6 @@ fifo_generator_0 data_cache_fifo (
.empty (data_fifo_empty) // 空标志 .empty (data_fifo_empty) // 空标志
); );
//处理状态机 //处理状态机
always @(posedge clk or posedge reset) begin always @(posedge clk or posedge reset) begin
if(reset)begin if(reset)begin
@ -280,7 +232,6 @@ always @(posedge clk or posedge reset) begin
TOE_SFP_ID <=0; TOE_SFP_ID <=0;
TOE_RW_FLAG <=0; TOE_RW_FLAG <=0;
TOE_ADDR <= 0; TOE_ADDR <= 0;
TOE_LENGTH <= 0;
TOE_DATA <= 0; TOE_DATA <= 0;
header_reg <=0; header_reg <=0;
TOE_reg_wren <= 0; TOE_reg_wren <= 0;
@ -296,13 +247,10 @@ always @(posedge clk or posedge reset) begin
TOE_reg_din <= 0; TOE_reg_din <= 0;
if(recv_udp_frame_last)begin //last拉高的同时 也把data_fifo_rden拉高了 if(recv_udp_frame_last)begin //last拉高的同时 也把data_fifo_rden拉高了
deal_busy <= 1'b1; deal_busy <= 1'b1;
data_fifo_rden <= 1; data_fifo_rden <= 1; // 这个拉高其实没用如果这时候拉高下个时钟数据处来下下个时钟才能触发所以这个时钟数据就要出来
deal_state <= D_R_WAIT; deal_state <= D_HEAD;
end end
end end
D_R_WAIT:begin
deal_state <= D_HEAD;
end
D_HEAD :begin //判断是头的类型执行对应操作 D_HEAD :begin //判断是头的类型执行对应操作
header_reg <= data_fifo_dout[31:16]; // Header高字节 data_fifo_dout出来的操作和被赋值的操作是同时进行的默认赋值前一个数 header_reg <= data_fifo_dout[31:16]; // Header高字节 data_fifo_dout出来的操作和被赋值的操作是同时进行的默认赋值前一个数
if( data_fifo_dout[31:16]== HDR_TOE )begin if( data_fifo_dout[31:16]== HDR_TOE )begin
@ -311,64 +259,37 @@ always @(posedge clk or posedge reset) begin
end end
else if(data_fifo_dout[31:16] == HDR_CTRL)begin else if(data_fifo_dout[31:16] == HDR_CTRL)begin
deal_state <= D_CTRL; deal_state <= D_CTRL;
data_fifo_rden <= 0; data_fifo_rden <= 0; //如果现在拉低了
end end
else else
deal_state <= D_IDLE; deal_state <= D_IDLE;
end end
D_TOE_1 :begin //第一个为CMD高32bit 2 D_TOE_1 :begin
TOE_reg_wren <= 0; TOE_reg_wren <= 0;
TOE_reg_rden <= 0; TOE_reg_rden <= 0;
TOE_reg_din <= 0; //TOE控制清除 TOE_reg_din <= 0; //TOE控制清除
TOE_SFP_ID <= data_fifo_dout[19:16]; //高32bit [28:25] TOE_SFP_ID <= data_fifo_dout[23:20]; //TOE是64比特的数据此时获得的是高32bit
TOE_RW_FLAG <= data_fifo_dout[31] ; /// TOE_RW_FLAG <= data_fifo_dout[16] ;
TOE_ADDR <= data_fifo_dout[15:0] ; // TOE_ADDR <= data_fifo_dout[15:0] ; //虽然是32比特的寄存器但地址就是16位
deal_state <= D_TOE_2; deal_state <= D_TOE_2;
data_fifo_rden <= 1; data_fifo_rden <= 1;
end end
D_TOE_2 : begin //第二个为CMD低32bit 3 D_TOE_2 : begin
TOE_LENGTH <= data_fifo_dout[19:0];
// TOE_DATA <= data_fifo_dout;
deal_state <= D_TOE_3;
data_fifo_rden <= 1;
end
D_TOE_3 : begin // 4
TOE_LENGTH <= TOE_LENGTH -3'd4;
TOE_DATA <= data_fifo_dout; TOE_DATA <= data_fifo_dout;
deal_state <= D_EXE; deal_state <= D_EXE;
data_fifo_rden <= 1'b0; data_fifo_rden <= 0;
TOE_reg_wren <= 1'b0;
TOE_reg_rden <= 1'b0;
end end
D_EXE : begin //5 D_EXE : begin
if(header_reg == HDR_TOE)begin if(header_reg == HDR_TOE)begin
//开始TOE命令处理 //开始TOE命令处理
if(TOE_LENGTH == 0)begin if(TOE_RW_FLAG) TOE_reg_rden <= 1'b1;
if(TOE_RW_FLAG) TOE_reg_rden <= 1'b1; else TOE_reg_wren <= 1'b1;
else TOE_reg_wren <= 1'b1; TOE_reg_din <= {TOE_SFP_ID[1:0],TOE_ADDR,TOE_DATA};
TOE_reg_din <= {TOE_SFP_ID[1:0],TOE_ADDR,TOE_DATA};
end
else if(TOE_LENGTH == 3'd4)begin
if(TOE_RW_FLAG) TOE_reg_rden <= 1'b1;
else TOE_reg_wren <= 1'b1;
TOE_reg_din <= {TOE_SFP_ID[1:0],TOE_ADDR,TOE_DATA};
deal_state <= D_TOE_3;
TOE_ADDR <= TOE_ADDR + 4'd4;
data_fifo_rden <= 1'b0; //这时候关刚刚好
end
else
begin
if(TOE_RW_FLAG) TOE_reg_rden <= 1'b1;
else TOE_reg_wren <= 1'b1;
TOE_reg_din <= {TOE_SFP_ID[1:0],TOE_ADDR,TOE_DATA};
deal_state <= D_TOE_3;
TOE_ADDR <= TOE_ADDR + 4'd4;
data_fifo_rden <= 1'b1;
end
//处理结束 //处理结束
if(TOE_LENGTH == 0) begin deal_state <=D_IDLE; deal_busy = 1'b0; end if(data_fifo_empty) begin deal_state <=D_IDLE; deal_busy = 1'b0; end
else begin deal_state <= D_TOE_1; data_fifo_rden <= 1; end
end end
end end
@ -416,7 +337,7 @@ endfunction
always@(posedge clk) always@(posedge clk)
if(reset) if(reset)
second_timer <= 'b0; second_timer <= 'b0;
else if((second_timer < 28'd125000000 - 1) && state_report_en) //状态上报开启秒计数器才开始工作 实际为28'd125000000 要改2个地方 else if((second_timer < 28'd125 - 1) && state_report_en) //状态上报开启秒计数器才开始工作 实际为28'd125000000
second_timer <= second_timer + 1'b1; second_timer <= second_timer + 1'b1;
else else
second_timer <= 28'd0; second_timer <= 28'd0;
@ -425,46 +346,12 @@ always@(posedge clk)
always@(posedge clk) always@(posedge clk)
if(reset) if(reset)
pulse_second <= 1'b0; pulse_second <= 1'b0;
else if( (second_timer >28'd125000000 - 1 -16))begin //8ns x125 =1us 8ns x125000 =1ms 8ns x125000000 =1s else if( (second_timer >28'd125 - 1 -16))begin
pulse_second <= 1'b1; pulse_second <= 1'b1;
end end
else else
pulse_second <= 1'b0; pulse_second <= 1'b0;
status_to_udp status_to_udp_0 (
.clk(clk),
.reset(reset),
.status_report_en(state_report_en),
.TOE_reg_out_valid(TOE_reg_out_valid),
.TOE_reg_dout(TOE_reg_dout),
.CMU_Status_Info_ready(CMU_Status_Info_ready),
.CMU_Status_Info_valid(CMU_Status_Info_valid),
.CMU_Status_Info_last(CMU_Status_Info_last),
.CMU_Status_Info_data(CMU_Status_Info_data),
.XYZ_Status_Info_ready(XYZ_Status_Info_ready),
.XYZ_Status_Info_valid(XYZ_Status_Info_valid),
.XYZ_Status_Info_last(XYZ_Status_Info_last),
.XYZ_Status_Info_data(XYZ_Status_Info_data),
.DAQ_Status_Info_ready(DAQ_Status_Info_ready),
.DAQ_Status_Info_valid(DAQ_Status_Info_valid),
.DAQ_Status_Info_last(DAQ_Status_Info_last),
.DAQ_Status_Info_data(DAQ_Status_Info_data),
.udp_app_send_fifo_rden_0(udp_app_send_fifo_rden_0),
.udp_app_send_fifo_rddata_0(udp_app_send_fifo_rddata_0),
.udp_app_send_fifo_rdcnt_0(udp_app_send_fifo_rdcnt_0),
.udp_app_send_fifo_empty_0(udp_app_send_fifo_empty_0),
.udp_app_send_fifo_rden_1(udp_app_send_fifo_rden_1),
.udp_app_send_fifo_rddata_1(udp_app_send_fifo_rddata_1),
.udp_app_send_fifo_rdcnt_1(udp_app_send_fifo_rdcnt_1),
.udp_app_send_fifo_empty_1(udp_app_send_fifo_empty_1)
);
endmodule endmodule

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,81 +0,0 @@
# 功能分析
## 原先
UDP_data_process.v主要负责接收UDP传过来的信息然后执行对应操作。比如说接收到一个TOE写的网络包然后会进行解析与执行。接收到开启秒脉冲的包就会控制pluse_second。
转发功能全打包到status_to_udp.v中实现功能解耦代码也更好看。从TOE和另外3个信息模块拿到数据打包成UDP帧结构然后发送出去。
## 现在
![a83dc5096e9434783ed57f826a2f50e2](./变成两个udp,一个负责收一个负责发.assets/a83dc5096e9434783ed57f826a2f50e2.png)
本来是一个udp接口收发数据现在实际是两个。udp1只负责发送状态数据**不需要接收**udp0负责配置数据和指令等**需要接收TOE命令**。所以在你的模块顶层会有两组这个udp数据接口。
# 改动
## status to udp
仲裁存储状态机不用改。TOE valid的来进的是TOE_rec_fifo 。而状态信息进的是info_cache_fifo。
发送状态机需要改。关键是fifo_wr_en fifo_wr_data得改。
改了fifo发现端口添加很容易关键是添加了fifo_wr_en_TOEfifo_wr_data_TOE
## UDP_data_process
除了端口改了。
由于该模块主要是执行功能所以主要改接口就ok了
![局部截取_20260109_212429](./变成两个udp,一个负责收一个负责发.assets/局部截取_20260109_212429.png)
# 仿真
## Status to udp 转发模块验证
### 保证状态信息info转发正确
//秒脉冲开启////////////////////////////////////
send_fifo_data(64'h4d44000410000001);
send_fifo_data_32(31'h34D1ED6F);
\#100000;
send_fifo_data(64'h4d44000410000000);
send_fifo_data_32(31'h3010F0D8);
//////////////////////////////////////////////
之后验证fifo_wr_en fifo_wr_data[31:0]是否正确
![局部截取_20260109_211614](./变成两个udp,一个负责收一个负责发.assets/局部截取_20260109_211614.png)
### 保证状态TOE转发正确
\#1000;
send_toe_data(66'h10102030405060708,66'h2b1b2b3b4b5b6b7b8,66'h3c1c2c3c4c5c6c7c8,66'h0a1a2a3a4a5a6a7a8,4);
\#5000;
之后验证fifo_wr_en_TOE fifo_wr_data_TOE[31:0]是否正确
![局部截取_20260109_211301](./变成两个udp,一个负责收一个负责发.assets/局部截取_20260109_211301.png)
成功!
## udp_data_process
![局部截取_20260109_214254](./变成两个udp,一个负责收一个负责发.assets/局部截取_20260109_214254.png)
成功!

View File

@ -1,7 +1,6 @@
module status_to_udp ( module status_to_udp (
input clk, input clk,
input reset, input reset,
input status_report_en,
input TOE_reg_out_valid, input TOE_reg_out_valid,
input [65:0] TOE_reg_dout, input [65:0] TOE_reg_dout,
@ -23,121 +22,85 @@ module status_to_udp (
input DAQ_Status_Info_last, input DAQ_Status_Info_last,
input [31:0] DAQ_Status_Info_data, input [31:0] DAQ_Status_Info_data,
// UDP0发送FIFO接口负责TOE // UDP发送FIFO接口
input udp_app_send_fifo_rden_0, input udp_app_send_fifo_rden,
output [7:0] udp_app_send_fifo_rddata_0, output [7:0] udp_app_send_fifo_rddata,
output [11:0] udp_app_send_fifo_rdcnt_0, output [11:0] udp_app_send_fifo_rdcnt,
output udp_app_send_fifo_empty_0, output udp_app_send_fifo_empty
// UDP1发送FIFO接口负责3块板子
input udp_app_send_fifo_rden_1,
output [7:0] udp_app_send_fifo_rddata_1,
output [11:0] udp_app_send_fifo_rdcnt_1,
output udp_app_send_fifo_empty_1
); );
// =========================== 参数定义 =========================== // =========================== 参数定义 ===========================
reg [3:0] A_state; // 需要4位因为增加了WAIT_CMU_VALID等状态 reg [2:0] A_state;
localparam IDLE = 4'd0; localparam IDLE = 3'd0;
localparam WAIT_READ = 4'd1; localparam WAIT_READ =3'd1;
localparam RECV_TOE = 4'd2; localparam RECV_TOE = 3'd2;
localparam WAIT_CMU_VALID = 4'd3; // 新增等待CMU valid localparam RECV_CMU = 3'd3;
localparam RECV_CMU = 4'd4; localparam RECV_XYZ = 3'd4;
localparam WAIT_XYZ_VALID = 4'd5; // 新增等待XYZ valid localparam RECV_DAQ = 3'd5;
localparam RECV_XYZ = 4'd6;
localparam WAIT_DAQ_VALID = 4'd7; // 新增等待DAQ valid
localparam RECV_DAQ = 4'd8; reg [2:0]S_state;
localparam SEND_IDLE = 3'd0;
localparam SEND_TOE_HEAD_LENGTH = 3'd1;
localparam SEND_TOE_DATA_1 = 3'd2;
localparam SEND_TOE_DATA_2 = 3'd3;
localparam SEND_CRC = 3'd4;
localparam SEND_INFO_HEAD_LENGTH = 3'd5;
localparam SEND_INFO_DATA = 3'd6;
reg [3:0] S_state;
localparam SEND_IDLE = 4'd0;
localparam SEND_TOE_HEAD_LENGTH = 4'd1;
localparam SEND_TOE_DATA_1 = 4'd2;
localparam SEND_TOE_DATA_LENGTH = 4'd3;
localparam SEND_TOE_DATA_2 = 4'd4;
localparam SEND_CRC_TOE = 4'd5;
localparam SEND_INFO_HEAD_LENGTH = 4'd6;
localparam SEND_INFO_DATA = 4'd7;
localparam SEND_CRC_INFO = 4'd8;
// =========================== 寄存器定义 =========================== // =========================== 寄存器定义 ===========================
reg [31:0] data_buffer; reg [31:0] data_buffer;
reg [1:0] byte_counter; reg [1:0] byte_counter;
reg buffer_valid; reg buffer_valid;
// FIFO相关信号 // FIFO相关信号
reg fifo_wr_en; //udp1 reg fifo_wr_en;
reg [31:0] fifo_wr_data; reg [31:0] fifo_wr_data;
reg fifo_wr_en_TOE; //udp0 wire fifo_full;
reg [31:0] fifo_wr_data_TOE;
wire TOE_rec_fifo_empty; wire TOE_rec_fifo_empty;
reg TOE_rec_fifo_rden; reg TOE_rec_fifo_rden;
wire [65:0] TOE_rec_fifo_dout; wire [65:0]TOE_rec_fifo_dout;
reg [63:0] TOE_ready_Data; reg [63:0]TOE_ready_Data;
reg TOE_ready_Data_valid; reg TOE_ready_Data_valid;
reg [63:0] TOE_payload; reg [63:0]TOE_payload;
reg [31:0] CMU_Status_data; reg [31:0]CMU_Status_data;
reg send_busy; reg send_busy;
reg send_finish; reg [31:0]crc32_calc;
reg [31:0] crc32_calc;
reg info_recv_flag; reg info_recv_flag;
reg [15:0] Info_data_bytes_num; reg [15:0]Info_data_bytes_num;
reg [15:0] Info_data_bytes_num_reg;
// 超时计数器
reg [7:0] wait_timeout_cnt;
// 轮询计数器
reg [1:0] poll_counter;
reg [31:0] info_cache_fifo_din; // =========================== FIFO实例化 ===========================
reg info_cache_fifo_wren;
reg info_cache_fifo_rden;
wire [31:0] info_cache_fifo_dout;
wire info_cache_fifo_full;
wire info_cache_fifo_empty;
// =========================== FIFO =========================== //512 depth 32to8
fifo_generator_32to8 fifo_32to8 (
//512 depth 32to8 --responsible for UDP0(TOE)
fifo_generator_32to8 fifo_32to8_TOE (
.clk(clk), // input wire clk .clk(clk), // input wire clk
.rst(reset), // input wire rst .rst(reset), // input wire rst
.wr_en(fifo_wr_en_TOE), // input wire wr_en .wr_en(fifo_wr_en), // input wire wr_en
.din(fifo_wr_data_TOE), // input wire [31 : 0] din .din(fifo_wr_data), // input wire [31 : 0] din
.full(), // output wire full .full(), // output wire full
.rd_en(udp_app_send_fifo_rden_0), // input wire rd_en .rd_en(udp_app_send_fifo_rden), // input wire rd_en
.dout(udp_app_send_fifo_rddata_0), // output wire [7 : 0] dout .dout(udp_app_send_fifo_rddata), // output wire [7 : 0] doutCMU
.empty(udp_app_send_fifo_empty_0), // output wire empty .empty(udp_app_send_fifo_empty), // output wire empty
.rd_data_count(udp_app_send_fifo_rdcnt_0), // output wire [11 : 0] rd_data_count .rd_data_count(udp_app_send_fifo_rdcnt), // output wire [11 : 0] rd_data_count
.wr_rst_busy(), // output wire wr_rst_busy .wr_rst_busy(), // output wire wr_rst_busy
.rd_rst_busy() // output wire rd_rst_busy .rd_rst_busy() // output wire rd_rst_busy
); );
//512 depth 32to8 --responsible for UDP1(state_info) //256 depth 66 to 66
fifo_generator_32to8 fifo_32to8_INFO (
.clk(clk), // input wire clk
.rst(reset), // input wire rst
.wr_en(fifo_wr_en), // input wire wr_en
.din(fifo_wr_data), // input wire [31 : 0] din
.full(), // output wire full
.rd_en(udp_app_send_fifo_rden_1), // input wire rd_en
.dout(udp_app_send_fifo_rddata_1), // output wire [7 : 0] dout
.empty(udp_app_send_fifo_empty_1), // output wire empty
.rd_data_count(udp_app_send_fifo_rdcnt_1), // output wire [11 : 0] rd_data_count
.wr_rst_busy(), // output wire wr_rst_busy
.rd_rst_busy() // output wire rd_rst_busy
);
//256 depth 66 to 66
fifo_generator_66to66 TOE_rec_fifo ( fifo_generator_66to66 TOE_rec_fifo (
.clk(clk), // input wire clk .clk(clk), // input wire clk
.srst(reset), // input wire srst
.din(TOE_reg_dout), // input wire [65 : 0] din .din(TOE_reg_dout), // input wire [65 : 0] din
.wr_en(TOE_reg_out_valid), // input wire wr_en .wr_en(TOE_reg_out_valid), // input wire wr_en
.rd_en(TOE_rec_fifo_rden), // input wire rd_en .rd_en(TOE_rec_fifo_rden), // input wire rd_en
@ -146,10 +109,15 @@ fifo_generator_66to66 TOE_rec_fifo (
.empty(TOE_rec_fifo_empty) // output wire empty .empty(TOE_rec_fifo_empty) // output wire empty
); );
reg [31:0]info_cache_fifo_din;
reg info_cache_fifo_wren;
reg info_cache_fifo_rden;
wire [31:0]info_cache_fifo_dout;
wire info_cache_fifo_full;
wire info_cache_fifo_empty;
//32 to 32 //32 to 32
fifo_generator_32to32 info_cache_fifo ( fifo_generator_32to32 info_cache_fifo (
.clk(clk), // input wire clk .clk(clk), // input wire clk
.srst(reset), // input wire srst
.din(info_cache_fifo_din), // input wire [31 : 0] din .din(info_cache_fifo_din), // input wire [31 : 0] din
.wr_en(info_cache_fifo_wren), // input wire wr_en .wr_en(info_cache_fifo_wren), // input wire wr_en
.rd_en(info_cache_fifo_rden), // input wire rd_en .rd_en(info_cache_fifo_rden), // input wire rd_en
@ -158,224 +126,99 @@ fifo_generator_32to32 info_cache_fifo (
.empty(info_cache_fifo_empty) // output wire empty .empty(info_cache_fifo_empty) // output wire empty
); );
// ILA实例化调试用
ila_00 ila_udp_data (
.clk(clk), // input wire clk
.probe0({
reset,
fifo_wr_en,
fifo_wr_data,
TOE_reg_dout,
TOE_reg_out_valid,
TOE_rec_fifo_rden,
TOE_rec_fifo_dout,
TOE_rec_fifo_empty,
info_cache_fifo_din,
info_cache_fifo_wren,
info_cache_fifo_rden,
info_cache_fifo_dout,
info_cache_fifo_empty,
TOE_ready_Data,
TOE_ready_Data_valid,
info_recv_flag,
send_busy,
A_state,
S_state,
crc32_calc,
TOE_payload,
Info_data_bytes_num,
Info_data_bytes_num_reg,
wait_timeout_cnt,
poll_counter
})
);
// =========================== 仲裁存储状态机 =========================== // =========================== 仲裁存储状态机 ===========================
always @(posedge clk) begin always @(posedge clk or posedge reset) begin
if (reset) begin if (reset)begin
A_state <= IDLE; A_state <= IDLE;
TOE_ready_Data <= 64'b0; TOE_ready_Data <= 64'b0;
TOE_ready_Data_valid <= 1'b0;
TOE_rec_fifo_rden <= 1'b0; TOE_rec_fifo_rden <= 1'b0;
info_cache_fifo_din <= 32'b0; info_cache_fifo_din <= 32'b0;
info_cache_fifo_wren <= 1'b0; info_cache_fifo_wren <= 1'b0;
info_recv_flag <= 1'b0; info_recv_flag <= 1'b0;
Info_data_bytes_num <= 16'b0; Info_data_bytes_num <= 16'b0;
send_busy <= 1'b0; end
CMU_Status_Info_ready <= 1'b0; else
XYZ_Status_Info_ready <= 1'b0; begin
DAQ_Status_Info_ready <= 1'b0;
wait_timeout_cnt <= 8'b0;
poll_counter <= 2'b00;
end else begin
case (A_state) case (A_state)
IDLE: begin //0 IDLE: begin
TOE_ready_Data <= 64'b0; TOE_ready_Data <= 64'b0;
TOE_ready_Data_valid <= 1'b0; TOE_ready_Data_valid <=1'b0;
info_cache_fifo_wren <= 1'b0; info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= 32'b0; info_cache_fifo_din <= 32'b0;
info_recv_flag <= 1'b0; info_recv_flag = 1'b0;
CMU_Status_Info_ready <= 1'b0; CMU_Status_Info_ready <=1'b0;
XYZ_Status_Info_ready <= 1'b0; DAQ_Status_Info_ready <=1'b0;
DAQ_Status_Info_ready <= 1'b0; XYZ_Status_Info_ready <=1'b0;
Info_data_bytes_num <= 16'b0; // 优先级仲裁TOE >CMU > XYZ > DAQ
wait_timeout_cnt <= 8'b0; if((!TOE_rec_fifo_empty) &&(!send_busy))begin
if (send_finish) begin
send_busy <= 1'b0;
end
// 优先级仲裁TOE > 状态信息板卡
if ((!TOE_rec_fifo_empty) && (!send_busy)) begin
A_state <= WAIT_READ; A_state <= WAIT_READ;
TOE_rec_fifo_rden <= 1'b1; TOE_rec_fifo_rden <= 1'b1;
end else if (status_report_en && (!send_busy)) begin
// 轮询不同的板卡按照CMU->XYZ->DAQ的顺序
case (poll_counter)
2'b00: begin // CMU
A_state <= WAIT_CMU_VALID;
CMU_Status_Info_ready <= 1'b1;
end
2'b01: begin // XYZ
A_state <= WAIT_XYZ_VALID;
XYZ_Status_Info_ready <= 1'b1;
end
2'b10: begin // DAQ
A_state <= WAIT_DAQ_VALID;
DAQ_Status_Info_ready <= 1'b1;
end
default: begin
A_state <= IDLE;
poll_counter <= 2'b00;
end
endcase
end else begin
A_state <= IDLE;
end end
end else if (CMU_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_CMU;
end
else if (XYZ_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_XYZ;
end
WAIT_READ: begin //1 else if (DAQ_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_DAQ;
end
else
A_state <= IDLE;
end
WAIT_READ : begin
A_state <= RECV_TOE; A_state <= RECV_TOE;
TOE_rec_fifo_rden <= 1'b0; TOE_rec_fifo_rden <= 1'b0;
end end
RECV_TOE: begin //2 RECV_TOE: begin
TOE_ready_Data[63] <= 1'b1; // 读标志位 //执行TOE发送操作
TOE_ready_Data[56:52] <= 5'h02; // 新增 TOE_ready_Data[53:52]<=TOE_rec_fifo_dout[65:64];
TOE_ready_Data[49:48] <= TOE_rec_fifo_dout[65:64]; // CID TOE_ready_Data[48]<= 1'b1;
TOE_ready_Data[47:32] <= TOE_rec_fifo_dout[47:32]; // 地址 TOE_ready_Data[47:32]<=TOE_rec_fifo_dout[47:32];
TOE_ready_Data[31:0] <= TOE_rec_fifo_dout[31:0]; // 数据 TOE_ready_Data[31:0] <= TOE_rec_fifo_dout[31:0];
TOE_ready_Data_valid <= 1'b1; TOE_ready_Data_valid <= 1'b1;
send_busy <= 1'b1; // 拿到数立马进行发送状态 send_busy <= 1'b1; //拿到数立马进行发送状态
A_state <= IDLE; A_state <= IDLE;
poll_counter <= 2'b00; // 重置轮询计数器
end end
WAIT_CMU_VALID: begin //3 RECV_CMU: begin
wait_timeout_cnt <= wait_timeout_cnt + 1; CMU_Status_Info_ready <=1'b1;
if (CMU_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_CMU;
info_cache_fifo_wren <= 1'b1; info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= CMU_Status_Info_data; info_cache_fifo_din <= CMU_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4; Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期 if (CMU_Status_Info_last)begin
wait_timeout_cnt <= 8'b0;
CMU_Status_Info_ready <= 1'b0;
poll_counter <= poll_counter + 1; // 尝试下一个板卡
A_state <= IDLE; A_state <= IDLE;
send_busy <= 1'b1; //拿到数立马进行发送状态
info_recv_flag = 1'b1;
end end
end end
RECV_CMU: begin //4 RECV_XYZ: begin
// 保持ready为高直到last信号到来 XYZ_Status_Info_ready <=1'b1;
CMU_Status_Info_ready <= 1'b1;
if(CMU_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= CMU_Status_Info_data;
if (CMU_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (CMU_Status_Info_last) begin
A_state <= IDLE;
CMU_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1; // 拿到数立马进行发送状态
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end
end
WAIT_XYZ_VALID: begin //5
wait_timeout_cnt <= wait_timeout_cnt + 1;
if (XYZ_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_XYZ;
info_cache_fifo_wren <= 1'b1; info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= XYZ_Status_Info_data; info_cache_fifo_din <= XYZ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4; Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期 if (XYZ_Status_Info_last)begin
wait_timeout_cnt <= 8'b0;
XYZ_Status_Info_ready <= 1'b0;
poll_counter <= poll_counter + 1; // 尝试下一个板卡
A_state <= IDLE; A_state <= IDLE;
send_busy <= 1'b1; //拿到数立马进行发送状态
info_recv_flag = 1'b1;
end end
end end
RECV_XYZ: begin //6 RECV_DAQ: begin //5
XYZ_Status_Info_ready <= 1'b1; DAQ_Status_Info_ready <=1'b1;
if(XYZ_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= XYZ_Status_Info_data;
if (XYZ_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (XYZ_Status_Info_last) begin
A_state <= IDLE;
XYZ_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1;
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end
end
WAIT_DAQ_VALID: begin //7
wait_timeout_cnt <= wait_timeout_cnt + 1;
if (DAQ_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_DAQ;
info_cache_fifo_wren <= 1'b1; info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= DAQ_Status_Info_data; info_cache_fifo_din <= DAQ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4; Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期 if (DAQ_Status_Info_last)begin
wait_timeout_cnt <= 8'b0;
DAQ_Status_Info_ready <= 1'b0;
poll_counter <= 2'b00; // 轮询回到CMU
A_state <= IDLE; A_state <= IDLE;
end send_busy <= 1'b1; //拿到数立马进行发送状态
end info_recv_flag = 1'b1;
RECV_DAQ: begin //8
DAQ_Status_Info_ready <= 1'b1;
if(DAQ_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= DAQ_Status_Info_data;
if (DAQ_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (DAQ_Status_Info_last) begin
A_state <= IDLE;
DAQ_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1;
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end end
end end
@ -384,112 +227,89 @@ always @(posedge clk) begin
end end
end end
// =========================== 发送状态机 =========================== //发送状态机
always @(posedge clk or posedge reset) begin
if(reset) begin always @(posedge clk or posedge reset) begin
S_state <= SEND_IDLE; if(reset)begin
fifo_wr_en <= 1'b0; S_state <= SEND_IDLE;
fifo_wr_data <= 32'b0; send_busy <=1'b0;
fifo_wr_en_TOE <= 1'b0;//udp0 fifo_wr_en<= 1'b0;
fifo_wr_data_TOE <= 32'b0; fifo_wr_data <= 32'b0;
crc32_calc <= 32'hFFFFFFFF; crc32_calc <= 32'hFFFFFFFF;
info_cache_fifo_rden <= 1'b0; info_cache_fifo_rden <= 1'b0;
TOE_payload <= 64'b0; TOE_payload <= 64'b0;
send_finish <= 1'b0; end
Info_data_bytes_num_reg <= 1'b0; else begin
end else begin case(S_state)
case(S_state) SEND_IDLE : begin
SEND_IDLE: begin //0
fifo_wr_en <= 1'b0; fifo_wr_en <= 1'b0;
fifo_wr_data <= 32'b0; fifo_wr_data <= 32'b0;
fifo_wr_en_TOE <= 1'b0;//udp0
fifo_wr_data_TOE <= 32'b0;
crc32_calc <= 32'hFFFFFFFF; crc32_calc <= 32'hFFFFFFFF;
send_finish <= 1'b0;
Info_data_bytes_num_reg <= 1'b0;
info_cache_fifo_rden <= 1'b0;
if(TOE_ready_Data_valid) begin if(TOE_ready_Data_valid) begin
TOE_payload <= TOE_ready_Data; TOE_payload <= TOE_ready_Data;
S_state <= SEND_TOE_HEAD_LENGTH; S_state <= SEND_TOE_HEAD_LENGTH;
end else if(info_recv_flag) begin
S_state <= SEND_INFO_HEAD_LENGTH;
info_cache_fifo_rden <= 1'b1;
Info_data_bytes_num_reg <= Info_data_bytes_num;
end end
end else if(info_recv_flag) begin
S_state <= SEND_INFO_HEAD_LENGTH;
info_cache_fifo_rden <= 1;
end
SEND_TOE_HEAD_LENGTH: begin //1 end
fifo_wr_en_TOE <= 1'b1; SEND_TOE_HEAD_LENGTH :begin
fifo_wr_data_TOE <= 32'h4547000c; fifo_wr_en <=1;
fifo_wr_data <= 32'h45470008;
S_state <= SEND_TOE_DATA_1; S_state <= SEND_TOE_DATA_1;
end end
SEND_TOE_DATA_1: begin //2 SEND_TOE_DATA_1 : begin
fifo_wr_en_TOE <= 1'b1; fifo_wr_en <=1;
fifo_wr_data_TOE <= TOE_payload[63:32]; fifo_wr_data <= TOE_payload[63:32];
crc32_calc <= calc_crc32(TOE_payload[63:32], crc32_calc); crc32_calc <= calc_crc32(TOE_payload[63:32],crc32_calc);
S_state <= SEND_TOE_DATA_LENGTH;
end
SEND_TOE_DATA_LENGTH: begin //3
fifo_wr_en_TOE <= 1'b1;
fifo_wr_data_TOE <= 32'd4; // 固定四字节长度
crc32_calc <= calc_crc32(32'd4, crc32_calc);
S_state <= SEND_TOE_DATA_2; S_state <= SEND_TOE_DATA_2;
end end
SEND_TOE_DATA_2 : begin
SEND_TOE_DATA_2: begin //4 fifo_wr_en <=1;
fifo_wr_en_TOE <= 1'b1; fifo_wr_data <= TOE_payload[31:0];
fifo_wr_data_TOE <= TOE_payload[31:0]; crc32_calc <= calc_crc32(TOE_payload[31:0],crc32_calc);
crc32_calc <= calc_crc32(TOE_payload[31:0], crc32_calc); S_state <= SEND_CRC;
S_state <= SEND_CRC_TOE;
end end
SEND_CRC : begin //
SEND_CRC_TOE: begin //5 fifo_wr_en <=1;
fifo_wr_en_TOE <= 1'b1; fifo_wr_data <= crc32_calc;
fifo_wr_data_TOE <= crc32_calc;
S_state <= SEND_IDLE; S_state <= SEND_IDLE;
send_finish <= 1'b1; send_busy <= 1'b0;
info_cache_fifo_rden <= 1'b0; info_cache_fifo_rden <= 1'b0;
end end
SEND_INFO_HEAD_LENGTH: begin //6 SEND_INFO_HEAD_LENGTH : begin //5
fifo_wr_en <= 1'b1; fifo_wr_en <=1;
fifo_wr_data[31:16] <= 16'h494e; // "IN" fifo_wr_data[31:16] <= 32'h494e;
fifo_wr_data[15:0] <= Info_data_bytes_num_reg; fifo_wr_data[15:0] <= Info_data_bytes_num;
crc32_calc <= 32'hFFFFFFFF; //be ready to caculate crc Info_data_bytes_num <= 16'b0; //用完就清零
S_state <= SEND_INFO_DATA; S_state <= SEND_INFO_DATA;
end end
SEND_INFO_DATA: begin //7 SEND_INFO_DATA : begin //6
fifo_wr_en <= 1'b1; fifo_wr_en <=1;
fifo_wr_data <= info_cache_fifo_dout; fifo_wr_data <= info_cache_fifo_dout;
crc32_calc <= calc_crc32(info_cache_fifo_dout, crc32_calc); crc32_calc <= calc_crc32(info_cache_fifo_dout,crc32_calc);
if(info_cache_fifo_empty)begin
if(info_cache_fifo_empty) begin S_state <= SEND_CRC;
info_cache_fifo_rden <= 1'b0;
S_state <= SEND_CRC_INFO;
end else begin
info_cache_fifo_rden <= 1'b1;
end end
end end
SEND_CRC_INFO: begin //8
fifo_wr_en <= 1'b1;
fifo_wr_data <= crc32_calc;
S_state <= SEND_IDLE;
send_finish <= 1'b1;
info_cache_fifo_rden <= 1'b0;
end
endcase
end
default: S_state <= SEND_IDLE;
endcase
end end
end
// =========================== CRC32计算函数 ===========================
// // =========================== FIFO写入控制 ===========================
//CRC32计算函数生成多项式G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1初始值0xffffffff
function [31:0] calc_crc32; function [31:0] calc_crc32;
input [31:0] data; input [31:0] data;
input [31:0] crc; input [31:0] crc;
@ -509,4 +329,5 @@ begin
end end
endfunction endfunction
endmodule endmodule

15
try_smg/counter.v Normal file
View File

@ -0,0 +1,15 @@
module counter
(
input clk, enable, rst_n,
output reg [8-1:0] count
);
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
count <= 0;
else if (enable == 1'b1)
count <= count + 1;//aabbcc
end
endmodule

46
try_smg/exp6_changed.v Normal file
View File

@ -0,0 +1,46 @@
module exp6_changed(
input clk,pbl,enable,
output [7-1:0] led_high,led_low
);
wire clk_3Hz;
wire[7:0] cnt;
reg clk_3Hz_ff0;
wire positive_edge_clk3Hz;
freq_div #(
.n(3)
) u_freq_div(
.clk(clk),
.rst_n(pbl),
.freqdiv_out(clk_3Hz)
);
always @ (posedge clk or negedge pbl)
begin
if (!pbl)
clk_3Hz_ff0 <= 0;
else
clk_3Hz_ff0 <= clk_3Hz;
end
assign positive_edge_clk3Hz = clk_3Hz==1 && clk_3Hz_ff0==0;
counter u_counter(
.clk(clk),
.enable(enable && positive_edge_clk3Hz),
.rst_n(pbl),
.count(cnt)
);
seg7_led u_seg7_led_high(
.data_in(cnt[7:4]),
.led_out(led_high)
);
seg7_led u_seg7_led_low(
.data_in(cnt[3:0]),
.led_out(led_low)
);
endmodule

21
try_smg/freq_div.v Normal file
View File

@ -0,0 +1,21 @@
module freq_div
#(
parameter n
)
(
input clk,rst_n,
output freqdiv_out
);
reg [n-1:0] count;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= 0;
else
count <= count + 1;
end
assign freqdiv_out = count[n-1];
//feature
endmodule

26
try_smg/seg7_led.v Normal file
View File

@ -0,0 +1,26 @@
module seg7_led(
input [4-1:0] data_in,
output reg [7-1:0] led_out
);
always @(*) begin
case(data_in)
4'h0:led_out = 7'b1000000;
4'h1:led_out = 7'b1111001;
4'h2:led_out = 7'b0100100;
4'h3:led_out = 7'b0110000;
4'h4:led_out = 7'b0011001;
4'h5:led_out = 7'b0010010;
4'h6:led_out = 7'b0000010;
4'h7:led_out = 7'b1111000;
4'h8:led_out = 7'b0000000;
4'h9:led_out = 7'b0010000;
4'ha:led_out = 7'b0001000;
4'hb:led_out = 7'b0000011;
4'hc:led_out = 7'b1000110;
4'hd:led_out = 7'b0100001;
4'he:led_out = 7'b0000110;
4'hf:led_out = 7'b0001110;
default:led_out = 7'b1111111;
endcase
end
endmodule