收到聯發科筆試邀請,臨時抱個佛腳,手動狗頭
1、verilog程式設計題目
請用Verilog寫出以下邏輯。
在data_in的資料中找到特殊字元32’hA1b9_0000,特殊字元前的資料全部丢掉,特殊字元後的資料全部收下來,并且儲存在sync_fifo中,當sync_fifo為非空的時候,将資料讀出放到data_out上,并用data_out_vld訓示資料的有效性。
2、題目分析
本題的代碼實作主要分為兩部分
- 第一部分是檢測到指定資料,也就是32’hA1b9_0000
- 第二部分就是對檢測到的資料,及其之後的資料進行存儲,和讀出,本題也有提示其實就是自己寫一個同步fifo,當檢測到資料之後,給出相應的讀使能和寫使能,寫入和讀出資料,是以再實作整個代碼前我特定複習了以下同步fifo的實作
- 接下來我們就寫代碼
3、verilog實作
module filter_data_store(
input wire clk_ck,
input wire rst_b,
input wire req_in,
output reg req_in_ack,
input wire [31:0] data_in,
output reg data_out_vld,
output reg [31:0] data_out
);
wire data_in_valid;
reg data_in_valid_reg0,data_in_valid_reg1;
reg [31:0] data_in_reg,data_in_reg1;
reg find_out;
reg [31:0] mem [15:0];
wire empty;
wire full;
reg [3:0] rd_addr;
reg [3:0] wr_addr;
wire rd_en;
wire wr_en;
reg [3:0] count;
localparam deepth = 4'd15;
assign empty =(count == 4'd0)? 1'b1: 1'b0 ;
assign full = (count == 4'd15) ? 1'b1:1'b0;
assign data_in_valid = (req_in & req_in_ack);
assign rd_en = (~empty);
always @(posedge clk_ck or negedge rst_b) begin
{data_in_valid_reg1,data_in_valid_reg0} ={data_in_valid_reg0,data_in_valid};
end
always @(posedge clk_ck or negedge rst_b)
if(!rst_b)
req_in_ack <= 1'b0;
else if(req_in)
req_in_ack <= 1'b1;
else
req_in_ack <= 1'b0;
always @(posedge clk_ck or negedge rst_b) begin
if (!rst_b)
data_in_reg <= 32'd0;
else if (data_in_valid)
data_in_reg <= data_in;
else begin
data_in_reg <= 32'd0;
end
end
always @(posedge clk_ck)
if(!rst_b)
data_in_reg1 <= 32'd0;
else
data_in_reg1 <= data_in_reg;
always @(posedge clk_ck or negedge rst_b) begin
if (!rst_b)
find_out <= 1'b0;
else if (data_in_valid && data_in_reg == 32'hA1B9_0000 )
find_out <= 1'b1;
else
find_out <= find_out;
end
assign wr_en = (find_out && ~full && data_in_valid_reg1);
always @(posedge clk_ck or negedge rst_b)
if(!rst_b)
wr_addr <= 4'd0;
else if (wr_en) begin
mem[wr_addr] = data_in_reg1;
wr_addr <= wr_addr + 1'b1;
end
else begin
mem[wr_addr] <= mem[wr_addr];
wr_addr <= wr_addr;
end
always @(posedge clk_ck or negedge rst_b)
if(!rst_b) begin
rd_addr <= 4'd0;
data_out <= 32'd0;
data_out_vld <= 1'b0;
end
else if(rd_en) begin
data_out <= mem[rd_addr];
rd_addr <= rd_addr + 1'b1;
data_out_vld <= 1'b1;
end
else begin
rd_addr <= rd_addr;
data_out <= data_out;
data_out_vld<= 1'b0;
end
//count 的控制
always @(posedge clk_ck or negedge rst_b)
if(!rst_b)
count <= 4'd0;
else if(wr_en && ~rd_en)
count <= count + 1'b1;
else if(rd_en && ~wr_en)
count <= count - 1'b1;
else
count <= count;
endmodule
4、子產品的仿真代碼
`timescale 1ns/1ps
module tb_mtk();
reg clk;
reg rst_n;
reg req_in;
wire req_in_ack;
reg [31:0] data_in;
wire data_out_vld;
wire [31:0] data_out;
initial begin
clk = 0;
rst_n =0;
//req_in_ack =0;
req_in =0;
data_in =0;
#100;
rst_n = 1;
#1000;
req_in = 1'b1;
data_in = 32'h53;
#20;
data_in = 32'h01;
#20;
data_in = 32'h11;
#20;
data_in = 32'hA1B9_0000;
#20;
data_in = 32'h05;
#20;
data_in = 32'h01;
#20;
data_in = 32'h02;
#20;
data_in = 32'h05;
#20;
data_in = 32'h01;
#20;
data_in = 32'h02;
#20;
data_in = 32'h05;
#20;
data_in = 32'h01;
#20;
data_in = 32'h02;
#20;
data_in = 32'h02;
#20;
data_in = 32'h05;
#20;
data_in = 32'h01;
#20;
data_in = 32'h02;
#20;
data_in = 32'h05;
#20;
data_in = 32'h01;
#20;
data_in = 32'h02;
#20;
req_in = 0;
end
always #10 clk = ~clk;
filter_data_store filter_data_store_inst(
.clk_ck(clk),
.rst_b(rst_n),
.req_in(req_in),
.req_in_ack(req_in_ack),
.data_in(data_in),
.data_out_vld(data_out_vld),
.data_out(data_out)
);
endmodule
5、仿真結果
感覺筆試的時候,想要完整寫出代碼,并且不出錯,還是挺難的,這次的代碼也是反複調整時序,才寫出來。