|
本帖最后由 xxppno1 于 2025-3-20 18:18 编辑
论坛有个人提问如何把32bit转换成24bit,相当于上下文拼接转换,这还是蛮容易的问题.正好试试deepseek能不能用,因为deepseek被一帮人吹能做IC我是不是太相信的.但是deepseek做ACM竞赛题每道题还是能一点虽然拿不到满分,但是告诉他错误的输入和正确输出后,有时候还是可以自我纠正,但是大部分时候还是纠正不了错误.
我提问
"用systemverilog帮我写一个可以综合的,32bit数据转换成24bit数据, 接口 为input clk, input rst, input in_valid, output in_ready, input [31:0] in_data, output out_valid, input out_ready, output [23:0] out_data"
他推导过程还是挺令人惊讶的"不过用户没有给出具体的转换规则,比如是高位截断还是低位截断,或者是否有其他处理方式,比如取平均、压缩等。但根据常见的转换需求,可能只是简单的截断或重新组合。比如,可能需要将32位的数据分成两个24位的部分,但这可能需要存储中间数据。例如,32和24的最小公倍数是96,所以可能需要积累三个32位的数据,然后分成四个24位的数据?或者可能每次输入一个32位数据,输出一个24位数据,剩下的8位保存下来,下次输入时再拼接起来。"
我的确忘了说是截断还是分包,他根据我的接口推断出是分包拼接.
经过10分钟左右漫长的推理
module data_converter (
input logic clk,
input logic rst_n,
input logic in_valid,
output logic in_ready,
input logic [31:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [23:0] out_data
);
typedef enum logic {IDLE, OUTPUT} state_t;
state_t state;
// 剩余数据寄存器 (最大保存 23 位)
logic [23:0] residual_data;
logic [4:0] residual_bits; // 0-23 位
// 处理过程中的临时数据
logic [55:0] processing_data; // 32+23=55 位最大
logic [5:0] total_bits; // 当前处理的总位数
logic [5:0] remaining_bits; // 处理后的剩余位数
logic [5:0] blocks_remaining; // 剩余需要输出的块数
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
residual_data <= '0;
residual_bits <= '0;
processing_data <= '0;
total_bits <= '0;
remaining_bits <= '0;
blocks_remaining <= '0;
out_valid <= '0;
out_data <= '0;
end else begin
case (state)
IDLE: begin
out_valid <= '0;
if (in_valid && in_ready) begin
// 拼接剩余数据和新数据
processing_data = {residual_data, in_data};
total_bits = residual_bits + 32;
// 计算输出块数和剩余位数
blocks_remaining = total_bits / 24;
remaining_bits = total_bits % 24;
if (blocks_remaining > 0) begin
state <= OUTPUT;
out_valid <= 1'b1;
out_data <= processing_data[total_bits-1 -:24];
blocks_remaining <= blocks_remaining - 1;
end else begin
residual_data <= processing_data[31:0];
residual_bits <= total_bits;
end
end
end
OUTPUT: begin
if (out_ready) begin
if (blocks_remaining > 0) begin
// 处理后续块
processing_data <= processing_data << 24;
out_data <= processing_data[total_bits-25 -:24];
blocks_remaining <= blocks_remaining - 1;
total_bits <= total_bits - 24;
end else begin
// 更新剩余数据并返回 IDLE
residual_data <= processing_data << (total_bits - 24);
residual_bits <= remaining_bits;
state <= IDLE;
out_valid <= '0;
end
end
end
endcase
end
end
// 输入就绪信号在空闲状态且无剩余块时有效
assign in_ready = (state == IDLE);
endmodule
除了格式好看,就看不出一点可取之处,因为结果是错的不能再错了,vivado 综合效果是用了.
可能是我问的不对,我又重新问了"用systemverilog帮我写一个可以综合的,32bit数据转换成24bit数据,32bit都是有效数据,每个周期应该通过拼接得到24bit,并且有反压信号,接口为module data_converter (
input logic clk,
input logic rst_n,
input logic in_valid,
output logic in_ready,
input logic [31:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [23:0] out_data
);" 又经过漫长的10分钟等待
module data_converter (
input logic clk,
input logic rst_n,
input logic in_valid,
output logic in_ready,
input logic [31:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [23:0] out_data
);
logic [63:0] buffer; // 数据缓冲区(足够存储两次输入)
logic [6:0] buf_len; // 有效数据长度计数器(0-64)
// 输入就绪条件:缓冲区剩余空间足够容纳新数据
assign in_ready = (buf_len <= 32);
// 输出有效条件:缓冲区有足够数据生成输出
assign out_valid = (buf_len >= 24);
// 输出数据选择器(从高位开始取)
assign out_data = buffer[buf_len-1 -:24];
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
buffer <= '0;
buf_len <= '0;
end else begin
// 输出处理优先
if (out_valid && out_ready) begin
buffer <= buffer << 24;
buf_len <= buf_len - 24;
end
// 输入处理
if (in_valid && in_ready) begin
buffer <= (buffer << 32) | in_data;
buf_len <= buf_len + 32;
end
end
end
endmodule
这次错的就更离谱了.根本没有推理出我要的东西.所以我也不指望他能推理了.我就想把思路告诉它,恨不得状态机描述出来让它帮我码代码.
"你的理解有误区比如开始第一个周期输入32bit数据是0x04030201 输出24bit是0x030201, 第二个周期输入32bit数据0x08070605 输出24bit数据是0x060504, 第三个周期输入32bit数据是0x0c0b0a09,输出的24bit是0x090807, 第四个周期禁止输入,输出24bit数据是0x0c0b0a 然后持续往下.用systemverilog帮我写一个可以综合的,32bit数据,转换成24bit数据,32bit都是有效数据,应该通过拼接得到24bit,如果in_valid和out_ready一直为高的话(当然不是一直为高),会有4个周期为一个循环,因为32bit和24bit最大公约数是8, 也就是32bit/8也就是4个周期一个循环. 也就是第一个周期in_ready=1输出输入的32bit中低24bit,并且保存输入32bit中的高8bit. 第二个周期in_ready=1,输出上个周期保存的8bit和第二周期输入进来的16bit,保存第二周期输入进来的剩下16bit,第三个时钟in_ready=1,输出上个周期保存的16bit和第三个周期输入的8bit,保存第三个周期输入剩下的24bit,第四个时钟,in_ready=0阻止输入输出上个周期保存的24bit,大致是这样不必完全听我的思路, 接口 为input clk, input rst, input in_valid, output in_ready, input [31:0] in_data, output out_valid, input out_ready, output [23:0] out_data"
又经过漫长的5分钟等待
module data_converter (
input clk,
input rst,
input in_valid,
output logic in_ready,
input [31:0] in_data,
output logic out_valid,
input out_ready,
output logic [23:0] out_data
);
typedef enum logic [1:0] {
S0, S1, S2, S3
} state_t;
state_t state;
logic [23:0] saved_data;
// Input control
assign in_ready = (state != S3) && out_ready;
// Output generation
always_comb begin
case(state)
S0: out_data = in_data[23:0];
S1: out_data = {in_data[15:0], saved_data[7:0]};
S2: out_data = {in_data[7:0], saved_data[15:0]};
S3: out_data = saved_data;
default: out_data = 24'b0;
endcase
end
// Output validation
assign out_valid = (state == S3) ? 1'b1 : (in_valid & in_ready);
// Main state machine
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
state <= S0;
saved_data <= 24'b0;
end else begin
if (out_valid && out_ready) begin
case(state)
S0: begin
if (in_valid && in_ready) begin
saved_data[7:0] <= in_data[31:24];
state <= S1;
end
end
S1: begin
if (in_valid && in_ready) begin
saved_data[15:0] <= in_data[31:16];
state <= S2;
end
end
S2: begin
if (in_valid && in_ready) begin
saved_data <= in_data[31:8];
state <= S3;
end
end
S3: begin
state <= S0;
saved_data <= 24'b0;
end
endcase
end
end
end
endmodule
终于得到正确答案 用了52LUT和26个FF
说明给出详细设计过程,还是可以得到正确答案,帮我码代码还是很舒服的.但是模糊的设计需求,让它推理得到你想要的东西,还是比较困难的
|
|