reg和wire 与 always和assign没有匹配正确 concurrent assignment to a non-net c is not permitted

本文分析了在Verilog设计中,当使用assign给wire类型和reg类型变量赋值时的区别,指出assign用于连续赋值(wire)导致无错误,而assign给reg赋值在always块中是非法的。同时解释了reg在always中的不同用法,包括电平检测和边沿检测所对应的逻辑结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#一. 问题现象
当output为wire型时,利用assign对c进行赋值,综合结束后没有报错;
module mux2(
input a,
input b,
input sys_clk,
input sel,
output c
);
assign c=(sel==1)?a:b;
endmodule

当output为reg型时,利用assign对c进行赋值,综合结束后有报错:[Synth 8-1852] concurrent assignment to a non-net c is not permitted;
module mux2(
input a,
input b,
input sys_clk,
input sel,
output reg c
);
assign c=(sel==1)?a:b;
endmodule

当output为reg型时,在always中对c进行赋值,综合结束后没有报错;
module mux2(
input a,
input b,
input sys_clk,
input sel,
output reg c
);
always@(posedge sys_clk)
begin
c=(sel==1)?a:b;
end
endmodule

当output为wire型时,在always中对c进行赋值,综合结束后报错,[Synth 8-2576] procedural assignment to a non-register c is not permitted;
module mux2(
input a,
input b,
input sys_clk,
input sel,
output wire c
);
always@(posedge sys_clk)
begin
c=(sel==1)?a:b;
end
endmodule
#二. 问题现象分析
a) 根据报错信息分析,是因为reg和wire 与 always和assign没有匹配正确;
b) 根据查找资料总结:https://blog.youkuaiyun.com/u013025203/article/details/53410715
Wire型变量一般综合结果为一根导线,对应于连续赋值,即在赋值语句中右边变量发生变化时,左边的值随之发生变化;连续赋值需要在assign中
Reg型变量在always中有两种情况:1.检测电平,即不带时钟边沿检测,综合出来还是组合逻辑;2.检测上升沿或者下降沿,综合出来为时序逻辑;该reg对应于过程赋值,即右边的变量发生变化时,左边的值不会立刻发生变化,一般需要等待下一个周期;过程赋值需要在always或initial中;

// serial_protocol_converter.v `timescale 1ns / 1ps module serial_protocol_converter( input wire clk, // 100MHz系统时钟 input wire rst_n, // 低电平复位 // USB接口 (模拟UART) input wire usb_rx_valid, // USB接收数据有效 input wire [7:0] usb_rx_data, // USB接收数据 output reg usb_tx_valid, // USB发送数据有效 output reg [7:0] usb_tx_data, // USB发送数据 // SPI接口 output wire spi_clk, // SPI时钟 output wire spi_cs, // SPI片选 output wire spi_mosi, // SPI主出从入 input wire spi_miso, // SPI主入从出 // UART接口 output wire uart_tx, // UART发送 input wire uart_rx, // UART接收 // I2C接口 (双向信号处理) output wire i2c_scl, // I2C时钟 inout wire i2c_sda, // I2C数据 // PWM接口 output wire [7:0] pwm_out // PWM输出 ); // ================= 参数定义 ================= localparam [1:0] PROTOCOL_SPI = 2'b00, PROTOCOL_I2C = 2'b01, PROTOCOL_UART = 2'b10, PROTOCOL_PWM = 2'b11; localparam [1:0] STATE_IDLE = 2'b00, STATE_RECEIVE = 2'b01, STATE_PROCESS = 2'b10, STATE_TRANSMIT = 2'b11; // ================= 寄存器定义 ================= reg [1:0] protocol_sel; // 当前协议选择 reg [1:0] state; // 主状态机状态 reg [7:0] data_buffer [0:15]; // 数据缓冲区 reg [3:0] data_length; // 数据长度 reg [3:0] data_counter; // 数据计数器 reg [7:0] config_reg; // 配置寄存器 // SPI相关 reg [15:0] spi_clk_div; // SPI时钟分频 reg spi_clk_en; reg spi_clk_phase; reg [7:0] spi_tx_data; reg [7:0] spi_rx_data; reg spi_busy; reg spi_start; // UART相关 reg [15:0] uart_baud_div; // UART波特率分频 reg uart_tx_busy; reg [7:0] uart_tx_data; reg uart_tx_start; // I2C相关 reg i2c_start; reg i2c_stop; reg i2c_rw; // 0:写, 1:reg [6:0] i2c_addr; reg i2c_busy; reg [7:0] i2c_tx_data; // PWM相关 reg [7:0] pwm_duty; // PWM占空比 // ================= 状态机控制 ================= always @(posedge clk or negedge rst_n) begin if (!rst_n) begin state <= STATE_IDLE; protocol_sel <= PROTOCOL_SPI; data_length <= 0; data_counter <= 0; usb_tx_valid <= 0; spi_clk_div <= 500; // 默认100kHz SPI时钟 uart_baud_div <= 868; // 115200波特率 (100MHz/115200) end else begin usb_tx_valid <= 0; // 默认无效 case (state) STATE_IDLE: begin if (usb_rx_valid) begin // 协议选择命令: 0x8X (X=协议选择) if (usb_rx_data[7:4] == 4'b1000) begin protocol_sel <= usb_rx_data[1:0]; state <= STATE_IDLE; end // 配置命令: 0x9X (X=配置类型) else if (usb_rx_data[7:4] == 4'b1001) begin state <= STATE_RECEIVE; data_length <= usb_rx_data[3:0]; // 配置数据长度 data_counter <= 0; end // 数据发送命令: 0xAX (X=数据长度) else if (usb_rx_data[7:4] == 4'b1010) begin state <= STATE_RECEIVE; data_length <= usb_rx_data[3:0]; // 数据长度 data_counter <= 0; end end end STATE_RECEIVE: begin if (usb_rx_valid) begin data_buffer[data_counter] <= usb_rx_data; if (data_counter == data_length - 1) begin state <= STATE_PROCESS; data_counter <= 0; end else begin data_counter <= data_counter + 1; end end end STATE_PROCESS: begin // 处理配置或数据 case (protocol_sel) PROTOCOL_SPI: begin spi_tx_data <= data_buffer[0]; spi_start <= 1; state <= STATE_TRANSMIT; end PROTOCOL_UART: begin uart_tx_data <= data_buffer[0]; uart_tx_start <= 1; state <= STATE_TRANSMIT; end PROTOCOL_I2C: begin i2c_addr <= data_buffer[0][6:0]; i2c_rw <= data_buffer[0][7]; i2c_tx_data <= data_buffer[1]; i2c_start <= 1; state <= STATE_TRANSMIT; end PROTOCOL_PWM: begin pwm_duty <= data_buffer[0]; state <= STATE_IDLE; // PWM无需传输状态 end endcase end STATE_TRANSMIT: begin case (protocol_sel) PROTOCOL_SPI: begin if (!spi_busy) begin usb_tx_data <= spi_rx_data; usb_tx_valid <= 1; state <= STATE_IDLE; end end PROTOCOL_UART: begin if (!uart_tx_busy) begin // 对于UART,我们假设没有接收数据 state <= STATE_IDLE; end end PROTOCOL_I2C: begin if (!i2c_busy) begin usb_tx_data <= i2c_rx_data; usb_tx_valid <= 1; state <= STATE_IDLE; end end endcase end endcase // 复位传输信号 if (spi_start) spi_start <= 0; if (uart_tx_start) uart_tx_start <= 0; if (i2c_start) i2c_start <= 0; end end // ================= SPI引擎 ================= spi_engine spi_inst ( .clk(clk), .rst_n(rst_n), .clk_div(spi_clk_div), .tx_data(spi_tx_data), .start(spi_start), .busy(spi_busy), .rx_data(spi_rx_data), .spi_clk(spi_clk), .spi_cs(spi_cs), .spi_mosi(spi_mosi), .spi_miso(spi_miso) ); // ================= UART引擎 ================= uart_engine uart_inst ( .clk(clk), .rst_n(rst_n), .baud_div(uart_baud_div), .tx_data(uart_tx_data), .tx_start(uart_tx_start), .tx_busy(uart_tx_busy), .tx(uart_tx), .rx(uart_rx), .rx_data(), // 未实现接收 .rx_valid() // 未实现接收 ); // ================= PWM引擎 ================= pwm_engine pwm_inst ( .clk(clk), .rst_n(rst_n), .duty(pwm_duty), .pwm_out(pwm_out) ); // ================= I2C引擎 ================= i2c_engine i2c_inst ( .clk(clk), .rst_n(rst_n), .scl(i2c_scl), .sda(i2c_sda), .addr(i2c_addr), .rw(i2c_rw), .tx_data(i2c_tx_data), .start(i2c_start), .stop(i2c_stop), .busy(i2c_busy), .rx_data(i2c_rx_data), .rx_valid(i2c_rx_valid) ); endmodule 出现报错 ERROR (EX3805) : Concurrent assignment to a non-net 'spi_busy' is not permitted("D:\GowinFPGA\Project\serial_protocol_converter\src\serial_protocol_converter.v":199) ERROR (EX3805) : Concurrent assignment to a non-net 'spi_rx_data' is not permitted("D:\GowinFPGA\Project\serial_protocol_converter\src\serial_protocol_converter.v":200) ERROR (EX3805) : Concurrent assignment to a non-net 'uart_tx_busy' is not permitted("D:\GowinFPGA\Project\serial_protocol_converter\src\serial_protocol_converter.v":214) ERROR (EX3805) : Concurrent assignment to a non-net 'i2c_busy' is not permitted("D:\GowinFPGA\Project\serial_protocol_converter\src\serial_protocol_converter.v":240)
最新发布
07-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值